refactor(css/parser): Canonicalize only if required (#6532)

This commit is contained in:
Alexander Akait 2022-11-30 08:07:46 +03:00 committed by GitHub
parent a19ff0843c
commit 251e98c055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 285 deletions

View File

@ -187,7 +187,6 @@ where
{
let ctx = Ctx {
in_import_at_rule: true,
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
};
let func = self.with_ctx(ctx).parse_as::<Function>()?;
@ -784,7 +783,6 @@ where
Token::Function { value, .. } if *value.to_ascii_lowercase() == *"supports" => {
let ctx = Ctx {
in_import_at_rule: true,
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
};
let func = self.with_ctx(ctx).parse_as::<Function>()?;
@ -1189,7 +1187,6 @@ where
Token::Function { value, .. } if &*value.to_ascii_lowercase() == "selector" => {
// TODO improve me
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
in_supports_at_rule: true,
..self.ctx
};
@ -1217,7 +1214,7 @@ where
match cur!(self) {
tok!("function") => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationList,
need_canonicalize: false,
..self.ctx
};
let function = self.with_ctx(ctx).parse_as::<Function>()?;
@ -1297,11 +1294,7 @@ where
Ok(DocumentPreludeMatchingFunction::Url(self.parse()?))
} else {
// TODO improve me
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
};
let function = self.with_ctx(ctx).parse_as::<Function>()?;
let function = self.parse()?;
Ok(DocumentPreludeMatchingFunction::Function(function))
}
@ -1881,11 +1874,7 @@ where
tok!("ident") => Ok(MediaFeatureValue::Ident(self.parse()?)),
tok!("dimension") => Ok(MediaFeatureValue::Dimension(self.parse()?)),
Token::Function { value, .. } if is_math_function(value) => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
};
let function = self.with_ctx(ctx).parse_as::<Function>()?;
let function = self.parse()?;
Ok(MediaFeatureValue::Function(function))
}
@ -2478,11 +2467,7 @@ where
tok!("ident") => Ok(SizeFeatureValue::Ident(self.parse()?)),
tok!("dimension") => Ok(SizeFeatureValue::Dimension(self.parse()?)),
Token::Function { value, .. } if is_math_function(value) => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
};
let function = self.with_ctx(ctx).parse_as::<Function>()?;
let function = self.parse()?;
Ok(SizeFeatureValue::Function(function))
}

View File

@ -55,7 +55,6 @@ pub enum BlockContentsGrammar {
DeclarationList,
RuleList,
Stylesheet,
DeclarationValue,
}
impl Default for BlockContentsGrammar {
@ -64,11 +63,12 @@ impl Default for BlockContentsGrammar {
}
}
#[derive(Debug, Default, Clone, Copy)]
#[derive(Debug, Clone, Copy)]
struct Ctx {
is_top_level: bool,
block_contents_grammar: BlockContentsGrammar,
mixed_with_declarations: bool,
need_canonicalize: bool,
in_keyframes_at_rule: bool,
in_supports_at_rule: bool,
@ -78,6 +78,24 @@ struct Ctx {
in_font_feature_values_at_rule: bool,
}
impl Default for Ctx {
fn default() -> Self {
Ctx {
is_top_level: false,
block_contents_grammar: BlockContentsGrammar::default(),
mixed_with_declarations: false,
need_canonicalize: true,
in_keyframes_at_rule: false,
in_supports_at_rule: false,
in_import_at_rule: false,
in_page_at_rule: false,
in_container_at_rule: false,
in_font_feature_values_at_rule: false,
}
}
}
#[derive(Debug, Clone)]
pub struct Parser<I>
where

View File

@ -181,7 +181,9 @@ where
at_rule.span = span!(self, span.lo);
// Canonicalization against a grammar
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
if self.ctx.need_canonicalize {
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
}
return Ok(at_rule);
}
@ -197,8 +199,10 @@ where
at_rule.span = span!(self, span.lo);
// Canonicalization against a grammar
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
at_rule = self.canonicalize_at_rule_block(at_rule)?;
if self.ctx.need_canonicalize {
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;
at_rule = self.canonicalize_at_rule_block(at_rule)?;
}
return Ok(at_rule);
}
@ -267,8 +271,11 @@ where
};
// Canonicalization against a grammar
qualified_rule = self.canonicalize_qualified_rule_prelude(qualified_rule)?;
qualified_rule = self.canonicalize_qualified_rule_block(qualified_rule)?;
if self.ctx.need_canonicalize {
qualified_rule =
self.canonicalize_qualified_rule_prelude(qualified_rule)?;
qualified_rule = self.canonicalize_qualified_rule_block(qualified_rule)?;
}
return Ok(qualified_rule);
}
@ -748,7 +755,9 @@ where
}
// Canonicalization against a grammar
declaration = self.canonicalize_declaration_value(declaration)?;
if self.ctx.need_canonicalize {
declaration = self.canonicalize_declaration_value(declaration)?;
}
// 8. Return the declaration.
Ok(declaration)
@ -774,7 +783,8 @@ where
let function = self
.with_ctx({
Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationList,
// We canonize it later
need_canonicalize: false,
..self.ctx
}
})
@ -944,7 +954,9 @@ where
function.span = span!(self, span.lo);
// Canonicalization against a grammar
function = self.canonicalize_function_value(function)?;
if self.ctx.need_canonicalize {
function = self.canonicalize_function_value(function)?;
}
return Ok(function);
}

View File

@ -267,27 +267,21 @@ where
&mut self,
mut function: Function,
) -> PResult<Function> {
match self.ctx.block_contents_grammar {
BlockContentsGrammar::DeclarationList => {}
_ => {
let function_name = function.name.value.to_ascii_lowercase();
let function_name = function.name.value.to_ascii_lowercase();
let locv = self.create_locv(function.value);
let locv = self.create_locv(function.value);
function.value = match self.parse_according_to_grammar(&locv, |parser| {
parser.parse_function_values(&function_name)
}) {
Ok(values) => values,
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}
function.value = match self.parse_according_to_grammar(&locv, |parser| {
parser.parse_function_values(&function_name)
}) {
Ok(values) => values,
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}
locv.children
}
};
locv.children
}
}
};
Ok(function)
}

View File

@ -1,7 +1,7 @@
use swc_common::{BytePos, Span};
use swc_css_ast::*;
use super::{input::ParserInput, BlockContentsGrammar, Ctx, PResult, Parser};
use super::{input::ParserInput, PResult, Parser};
use crate::{
error::{Error, ErrorKind},
Parse,
@ -56,13 +56,7 @@ where
return Ok(ComponentValue::Color(self.parse()?));
}
_ => {
return Ok(ComponentValue::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
));
return Ok(ComponentValue::Function(self.parse()?));
}
},
@ -484,15 +478,7 @@ where
}
tok!("number") => Ok(Some(ComponentValue::Number(parser.parse()?))),
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
is_legacy_syntax = false;
@ -550,15 +536,7 @@ where
}
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
_ => {
if !has_variable_before {
@ -613,15 +591,7 @@ where
}
tok!("number") => Ok(Some(ComponentValue::Number(parser.parse()?))),
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") if !is_legacy_syntax => {
let ident: Ident = parser.parse()?;
@ -665,15 +635,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -745,15 +707,7 @@ where
}
tok!("number") => Ok(Some(ComponentValue::Number(parser.parse()?))),
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") if !is_legacy_syntax => {
let ident: Ident = parser.parse()?;
@ -797,15 +751,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -858,15 +804,7 @@ where
Ok(Some(ComponentValue::AlphaValue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
_ => {
if !has_variable_before {
@ -900,15 +838,7 @@ where
Ok(Some(ComponentValue::AlphaValue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -982,15 +912,7 @@ where
Ok(Some(ComponentValue::Hue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1035,15 +957,7 @@ where
}
tok!("number") => Ok(Some(ComponentValue::Number(parser.parse()?))),
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1106,15 +1020,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1163,15 +1069,7 @@ where
Ok(Some(ComponentValue::Number(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1239,15 +1137,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1296,15 +1186,7 @@ where
Ok(Some(ComponentValue::Number(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1350,15 +1232,7 @@ where
Ok(Some(ComponentValue::Hue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1441,15 +1315,7 @@ where
Ok(Some(ComponentValue::AlphaValue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") if !matches!(function_name, "device-cmyk") => {
let ident: Ident = parser.parse()?;
@ -1558,15 +1424,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1621,14 +1479,7 @@ where
"var" | "env" | "constant"
) =>
{
ComponentValue::Function(
self.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
)
ComponentValue::Function(self.parse()?)
}
tok!("ident") => {
let ident: Ident = self.parse()?;
@ -1659,15 +1510,7 @@ where
Ok(Some(ComponentValue::Percentage(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") => {
let ident: Ident = parser.parse()?;
@ -1723,15 +1566,7 @@ where
}
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
_ => {
if !has_variable_before {
@ -1768,15 +1603,7 @@ where
Ok(Some(ComponentValue::AlphaValue(parser.parse()?)))
}
Token::Function { value, .. } if is_math_function(value) => {
Ok(Some(ComponentValue::Function(
parser
.with_ctx(Ctx {
block_contents_grammar:
BlockContentsGrammar::DeclarationValue,
..parser.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(parser.parse()?)))
}
tok!("ident") if !matches!(function_name, "device-cmyk") => {
let ident: Ident = parser.parse()?;
@ -1928,13 +1755,7 @@ where
{
*has_before_variable = true;
Ok(Some(ComponentValue::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
)))
Ok(Some(ComponentValue::Function(self.parse()?)))
}
_ => fallback(self, *has_before_variable),
}
@ -2564,13 +2385,7 @@ where
}
// <device-cmyk()>
Token::Function { value, .. } if value.as_ref().eq_ignore_ascii_case("device-cmyk") => {
Ok(Color::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
))
Ok(Color::Function(self.parse()?))
}
// <absolute-color-base>
_ => match self.parse() {
@ -2611,13 +2426,7 @@ where
Ok(AbsoluteColorBase::NamedColorOrTransparent(self.parse()?))
}
Token::Function { value, .. } if is_absolute_color_base_function(value) => {
Ok(AbsoluteColorBase::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
))
Ok(AbsoluteColorBase::Function(self.parse()?))
}
_ => {
return Err(Error::new(
@ -2728,13 +2537,7 @@ where
return Err(Error::new(span, ErrorKind::Expected("math function token")));
}
Ok(CmykComponent::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
))
Ok(CmykComponent::Function(self.parse()?))
}
_ => {
unreachable!()
@ -2879,13 +2682,7 @@ where
modifiers.push(UrlModifier::Ident(self.parse()?));
}
tok!("function") => {
modifiers.push(UrlModifier::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
));
modifiers.push(UrlModifier::Function(self.parse()?));
}
_ => {
let span = self.input.cur_span();
@ -3522,13 +3319,7 @@ where
Ok(CalcValue::Sum(calc_sum_in_parens))
}
tok!("function") => Ok(CalcValue::Function(
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
})
.parse_as::<Function>()?,
)),
tok!("function") => Ok(CalcValue::Function(self.parse()?)),
_ => {
let span = self.input.cur_span();