Skip to content

Commit

Permalink
fix(css/parser): Fix a bug with scope in block (#6402)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Nov 15, 2022
1 parent fafc625 commit 3d7545d
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 224 deletions.
2 changes: 1 addition & 1 deletion crates/swc_css_parser/src/parser/at_rules/mod.rs
Expand Up @@ -565,7 +565,7 @@ where
| js_word!("-o-keyframes")
| js_word!("-ms-keyframes") => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationList,
block_contents_grammar: BlockContentsGrammar::RuleList,
is_top_level: false,
in_keyframes_at_rule: true,
..self.ctx
Expand Down
266 changes: 45 additions & 221 deletions crates/swc_css_parser/src/parser/syntax/mod.rs
Expand Up @@ -134,24 +134,18 @@ where
unreachable!()
}
};
let (normalized_at_rule_name, name) = if at_keyword_name.0.starts_with("--") {
(
at_keyword_name.0.to_ascii_lowercase(),
AtRuleName::DashedIdent(DashedIdent {
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
value: at_keyword_name.0,
raw: Some(at_keyword_name.1),
}),
)
let name = if at_keyword_name.0.starts_with("--") {
AtRuleName::DashedIdent(DashedIdent {
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
value: at_keyword_name.0,
raw: Some(at_keyword_name.1),
})
} else {
(
at_keyword_name.0.to_ascii_lowercase(),
AtRuleName::Ident(Ident {
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
value: at_keyword_name.0,
raw: Some(at_keyword_name.1),
}),
)
AtRuleName::Ident(Ident {
span: Span::new(span.lo + BytePos(1), span.hi, Default::default()),
value: at_keyword_name.0,
raw: Some(at_keyword_name.1),
})
};
let mut prelude = vec![];
let mut at_rule = AtRule {
Expand Down Expand Up @@ -181,103 +175,31 @@ where
tok!(";") => {
self.input.bump();

let list_of_component_values = self.create_locv(prelude);

at_rule.prelude = match self
.parse_according_to_grammar(&list_of_component_values, |parser| {
parser.parse_at_rule_prelude(&normalized_at_rule_name)
}) {
Ok(at_rule_prelude) => match at_rule_prelude {
None if normalized_at_rule_name == js_word!("layer") => {
self.errors.push(Error::new(
span,
ErrorKind::Expected("at least one name"),
));

Some(Box::new(AtRulePrelude::ListOfComponentValues(
list_of_component_values,
)))
}
_ => at_rule_prelude.map(Box::new),
},
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}

if !list_of_component_values.children.is_empty() {
Some(Box::new(AtRulePrelude::ListOfComponentValues(
list_of_component_values,
)))
} else {
None
}
}
};
at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
self.create_locv(prelude),
)));
at_rule.span = span!(self, span.lo);

// Canonicalization against a grammar
at_rule = self.canonicalize_at_rule_prelude(at_rule)?;

return Ok(at_rule);
}
// <{-token>
// Consume a simple block and assign it to the at-rule’s block. Return the at-rule.
tok!("{") => {
let mut block = self.parse_as::<SimpleBlock>()?;

let list_of_component_values = self.create_locv(prelude);

at_rule.prelude = match self
.parse_according_to_grammar(&list_of_component_values, |parser| {
parser.parse_at_rule_prelude(&normalized_at_rule_name)
}) {
Ok(at_rule_prelude) => match at_rule_prelude {
Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(
name_list,
))) if name_list.name_list.len() > 1 => {
self.errors.push(Error::new(
name_list.span,
ErrorKind::Expected("only one name"),
));

Some(Box::new(AtRulePrelude::ListOfComponentValues(
list_of_component_values,
)))
}
_ => at_rule_prelude.map(Box::new),
},
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}

if !list_of_component_values.children.is_empty() {
Some(Box::new(AtRulePrelude::ListOfComponentValues(
list_of_component_values,
)))
} else {
None
}
}
};
let block = self.parse_as::<SimpleBlock>()?;

at_rule.block = match self.parse_according_to_grammar(
&self.create_locv(block.value.clone()),
|parser| parser.parse_at_rule_block(&normalized_at_rule_name),
) {
Ok(block_contents) => {
block.value = block_contents;

Some(block)
}
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}

Some(block)
}
};
at_rule.prelude = Some(Box::new(AtRulePrelude::ListOfComponentValues(
self.create_locv(prelude),
)));
at_rule.block = Some(block);
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)?;

return Ok(at_rule);
}
// anything else
Expand All @@ -299,50 +221,10 @@ where
{
fn parse(&mut self) -> PResult<QualifiedRule> {
// To consume a qualified rule:
let create_prelude =
|p: &mut Parser<I>, list: Vec<ComponentValue>| -> PResult<QualifiedRulePrelude> {
let list_of_component_values = p.create_locv(list);

if p.ctx.in_keyframes_at_rule {
Ok(QualifiedRulePrelude::ListOfComponentValues(
list_of_component_values,
))
} else if p.ctx.mixed_with_declarations {
match p.parse_according_to_grammar::<RelativeSelectorList>(
&list_of_component_values,
|parser| parser.parse(),
) {
Ok(relative_selector_list) => Ok(
QualifiedRulePrelude::RelativeSelectorList(relative_selector_list),
),
Err(err) => {
p.errors.push(err);

Ok(QualifiedRulePrelude::ListOfComponentValues(
list_of_component_values,
))
}
}
} else {
match p.parse_according_to_grammar::<SelectorList>(
&list_of_component_values,
|parser| parser.parse(),
) {
Ok(selector_list) => Ok(QualifiedRulePrelude::SelectorList(selector_list)),
Err(err) => {
p.errors.push(err);

Ok(QualifiedRulePrelude::ListOfComponentValues(
list_of_component_values,
))
}
}
}
};

let span = self.input.cur_span();
// Create a new qualified rule with its prelude initially set to an empty list,
// and its value initially set to nothing.
let span = self.input.cur_span();
let mut prelude = vec![];

// Repeatedly consume the next input token:
Expand Down Expand Up @@ -375,30 +257,20 @@ where
// Consume a simple block and assign it to the qualified rule’s block. Return the
// qualified rule.
tok!("{") => {
let mut block = self.parse_as::<SimpleBlock>()?;

block.value = match self.ctx.block_contents_grammar {
BlockContentsGrammar::DeclarationList => self
.parse_according_to_grammar(&self.create_locv(block.value), |parser| {
parser.parse_as::<Vec<DeclarationOrAtRule>>()
})?
.into_iter()
.map(ComponentValue::DeclarationOrAtRule)
.collect(),
_ => self
.parse_according_to_grammar(&self.create_locv(block.value), |parser| {
parser.parse_as::<Vec<StyleBlock>>()
})?
.into_iter()
.map(ComponentValue::StyleBlock)
.collect(),
};

return Ok(QualifiedRule {
let block = self.parse_as::<SimpleBlock>()?;
let mut qualified_rule = QualifiedRule {
span: span!(self, span.lo),
prelude: create_prelude(self, prelude)?,
prelude: QualifiedRulePrelude::ListOfComponentValues(
self.create_locv(prelude),
),
block,
});
};

// Canonicalization against a grammar
qualified_rule = self.canonicalize_qualified_rule_prelude(qualified_rule)?;
qualified_rule = self.canonicalize_qualified_rule_block(qualified_rule)?;

return Ok(qualified_rule);
}
// Reconsume the current input token. Consume a component value. Append the returned
// value to the qualified rule’s prelude.
Expand Down Expand Up @@ -458,12 +330,7 @@ where
// Reconsume the current input token. Consume an at-rule, and append the result to
// rules.
tok!("@") => {
let at_rule = self
.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::StyleBlock,
..self.ctx
})
.parse_as::<AtRule>()?;
let at_rule = self.parse()?;

rules.push(StyleBlock::AtRule(Box::new(at_rule)));
}
Expand Down Expand Up @@ -880,32 +747,8 @@ where
return Ok(declaration);
}

// Grammar parsing
let list_of_component_values = self.create_locv(declaration.value);

declaration.value =
match self.parse_according_to_grammar(&list_of_component_values, |parser| {
let mut values = vec![];

loop {
if is!(parser, EOF) {
break;
}

values.push(parser.parse_generic_value()?);
}

Ok(values)
}) {
Ok(values) => values,
Err(err) => {
if *err.kind() != ErrorKind::Ignore {
self.errors.push(err);
}

list_of_component_values.children
}
};
// Canonicalization against a grammar
declaration = self.canonicalize_declaration_value(declaration)?;

// 8. Return the declaration.
Ok(declaration)
Expand Down Expand Up @@ -1055,9 +898,8 @@ where
unreachable!()
}
};
let function_name = &*ident.0.to_ascii_lowercase();
let name = Ident {
span: swc_common::Span::new(span.lo, span.hi - BytePos(1), Default::default()),
span: Span::new(span.lo, span.hi - BytePos(1), Default::default()),
value: ident.0,
raw: Some(ident.1),
};
Expand Down Expand Up @@ -1101,26 +943,8 @@ where

function.span = span!(self, span.lo);

// Grammar parsing
match self.ctx.block_contents_grammar {
BlockContentsGrammar::DeclarationList => {}
_ => {
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);
}

locv.children
}
};
}
}
// Canonicalization against a grammar
function = self.canonicalize_function_value(function)?;

return Ok(function);
}
Expand Down

1 comment on commit 3d7545d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 3d7545d Previous: 8ca3cc7 Ratio
es/full/bugs-1 343131 ns/iter (± 18927) 356010 ns/iter (± 28302) 0.96
es/full/minify/libraries/antd 1879029520 ns/iter (± 86154105) 1868954143 ns/iter (± 41828480) 1.01
es/full/minify/libraries/d3 414102995 ns/iter (± 17005550) 427267789 ns/iter (± 16138148) 0.97
es/full/minify/libraries/echarts 1577618030 ns/iter (± 58450498) 1577385149 ns/iter (± 22702097) 1.00
es/full/minify/libraries/jquery 102708379 ns/iter (± 4908626) 106672079 ns/iter (± 2651444) 0.96
es/full/minify/libraries/lodash 125489448 ns/iter (± 6342439) 131443744 ns/iter (± 5431446) 0.95
es/full/minify/libraries/moment 59496706 ns/iter (± 2012974) 62479974 ns/iter (± 2256311) 0.95
es/full/minify/libraries/react 19967860 ns/iter (± 1038082) 22295733 ns/iter (± 2495811) 0.90
es/full/minify/libraries/terser 337947003 ns/iter (± 54535627) 341305748 ns/iter (± 37992550) 0.99
es/full/minify/libraries/three 573368575 ns/iter (± 33838779) 581803883 ns/iter (± 24392579) 0.99
es/full/minify/libraries/typescript 3503261209 ns/iter (± 124237777) 3324414259 ns/iter (± 141363385) 1.05
es/full/minify/libraries/victory 864893126 ns/iter (± 39416137) 840069254 ns/iter (± 30542715) 1.03
es/full/minify/libraries/vue 171950018 ns/iter (± 10840345) 163713162 ns/iter (± 9059088) 1.05
es/full/codegen/es3 35524 ns/iter (± 2234) 40217 ns/iter (± 6880) 0.88
es/full/codegen/es5 35047 ns/iter (± 3099) 35006 ns/iter (± 5217) 1.00
es/full/codegen/es2015 34463 ns/iter (± 1634) 33851 ns/iter (± 1235) 1.02
es/full/codegen/es2016 34603 ns/iter (± 1133) 33814 ns/iter (± 1497) 1.02
es/full/codegen/es2017 34599 ns/iter (± 1274) 34624 ns/iter (± 2010) 1.00
es/full/codegen/es2018 34350 ns/iter (± 1591) 34166 ns/iter (± 1046) 1.01
es/full/codegen/es2019 34720 ns/iter (± 2050) 33853 ns/iter (± 1048) 1.03
es/full/codegen/es2020 34496 ns/iter (± 1178) 34083 ns/iter (± 2527) 1.01
es/full/all/es3 200853664 ns/iter (± 13412938) 239787286 ns/iter (± 21209274) 0.84
es/full/all/es5 234003167 ns/iter (± 30838241) 223411060 ns/iter (± 23802659) 1.05
es/full/all/es2015 181154661 ns/iter (± 21853824) 170529182 ns/iter (± 20469715) 1.06
es/full/all/es2016 161489277 ns/iter (± 26404058) 159386307 ns/iter (± 14381462) 1.01
es/full/all/es2017 161681927 ns/iter (± 8902858) 164722662 ns/iter (± 52563112) 0.98
es/full/all/es2018 158742089 ns/iter (± 9826764) 159779349 ns/iter (± 21667518) 0.99
es/full/all/es2019 174600328 ns/iter (± 11801874) 166757541 ns/iter (± 17136334) 1.05
es/full/all/es2020 155677061 ns/iter (± 9995349) 159267746 ns/iter (± 21235222) 0.98
es/full/parser 756093 ns/iter (± 52006) 765942 ns/iter (± 87392) 0.99
es/full/base/fixer 28013 ns/iter (± 2796) 27953 ns/iter (± 1146) 1.00
es/full/base/resolver_and_hygiene 97198 ns/iter (± 4485) 94553 ns/iter (± 4436) 1.03
serialization of ast node 220 ns/iter (± 7) 232 ns/iter (± 12) 0.95
serialization of serde 224 ns/iter (± 5) 226 ns/iter (± 6) 0.99

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.