Skip to content

Commit

Permalink
refactor(css/parser): Fix parsing of declarations (#6234)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Oct 22, 2022
1 parent ac3949e commit e4fe840
Show file tree
Hide file tree
Showing 48 changed files with 1,263 additions and 398 deletions.
3 changes: 1 addition & 2 deletions crates/swc_css_codegen/tests/fixture/values/url/1/output.css
Expand Up @@ -45,8 +45,7 @@ div {
background: url('\"foo\"');
}
.bar {
background: url(http://example.com/image.svg param(--color var(--primary-color);
));}
background: url(http://example.com/image.svg param(--color var(--primary-color)));}
.baz {
background: url("http://example.com/image.svg" param(--color var(--primary-color)));
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/swc_css_parser/src/error.rs
Expand Up @@ -42,6 +42,7 @@ impl Error {
ErrorKind::Ignore => "Not an error".into(),
ErrorKind::UnexpectedChar(c) => format!("Unexpected character `{:?}`", c).into(),
ErrorKind::Expected(s) => format!("Expected {}", s).into(),
ErrorKind::Unexpected(s) => format!("Unexpected {}", s).into(),
ErrorKind::ExpectedButGot(s) => format!("Expected {}", s).into(),
ErrorKind::ExpectedSelectorText => "Expected a text for selector".into(),
ErrorKind::UnterminatedBlockComment => "Unterminated block comment".into(),
Expand Down Expand Up @@ -91,6 +92,7 @@ pub enum ErrorKind {
Ignore,
UnexpectedChar(char),
Expected(&'static str),
Unexpected(&'static str),
ExpectedButGot(&'static str),
ExpectedSelectorText,
UnterminatedBlockComment,
Expand Down
111 changes: 71 additions & 40 deletions crates/swc_css_parser/src/parser/syntax/mod.rs
@@ -1,4 +1,4 @@
use swc_common::Span;
use swc_common::{Span, Spanned};
use swc_css_ast::*;

use super::{input::ParserInput, PResult, Parser};
Expand Down Expand Up @@ -252,19 +252,33 @@ where
// <semicolon-token>
// Do nothing.
tok!(";") => {
bump!(self);
let token_and_span = self.input.bump().unwrap();

// For recovery mode
// TODO revisit it after refactor parser
if let Some(StyleBlock::ListOfComponentValues(list_of_component_values)) =
declarations.last_mut()
{
list_of_component_values.span = Span::new(
list_of_component_values.span_lo(),
token_and_span.span_hi(),
Default::default(),
);
list_of_component_values
.children
.push(ComponentValue::PreservedToken(token_and_span));
}
}
// <at-keyword-token>
// Reconsume the current input token. Consume an at-rule, and append the result to
// rules.
tok!("@") => {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::StyleBlock,
..self.ctx
};

rules.push(StyleBlock::AtRule(Box::new(
self.with_ctx(ctx).parse_as::<AtRule>()?,
self.with_ctx(Ctx {
block_contents_grammar: BlockContentsGrammar::StyleBlock,
..self.ctx
})
.parse_as::<AtRule>()?,
)));
}
// <ident-token>
Expand All @@ -276,11 +290,12 @@ where
tok!("ident") => {
if self.config.legacy_nesting {
let state = self.input.state();
let ctx = Ctx {
is_trying_legacy_nesting: true,
..self.ctx
};
let legacy_nested = self.with_ctx(ctx).parse_as::<QualifiedRule>();
let legacy_nested = self
.with_ctx(Ctx {
is_trying_legacy_nesting: true,
..self.ctx
})
.parse_as::<QualifiedRule>();

match legacy_nested {
Ok(legacy_nested) => {
Expand All @@ -294,39 +309,36 @@ where
};
}

let state = self.input.state();
let prop = match self.parse() {
Ok(v) => StyleBlock::Declaration(v),
Err(err) => {
self.errors.push(err);
self.input.reset(&state);
let span = self.input.cur_span();
let mut temporary_list = ListOfComponentValues {
span: Default::default(),
children: vec![],
};

let span = self.input.cur_span();
let mut children = vec![];
while !is_one_of!(self, ";", EOF) {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::NoGrammar,
..self.ctx
};

while !is_one_of!(self, EOF) {
if let Some(token_and_span) = self.input.bump() {
children.push(ComponentValue::PreservedToken(token_and_span));
}
let component_value = self.with_ctx(ctx).parse_as::<ComponentValue>()?;

if is!(self, ";") {
if let Some(token_and_span) = self.input.bump() {
children
.push(ComponentValue::PreservedToken(token_and_span));
}
temporary_list.children.push(component_value);
}

break;
}
}
let decl_or_list_of_component_values =
match self.parse_according_to_grammar::<Declaration>(&temporary_list) {
Ok(decl) => StyleBlock::Declaration(Box::new(decl)),
Err(err) => {
self.errors.push(err);

StyleBlock::ListOfComponentValues(ListOfComponentValues {
span: span!(self, span.lo),
children,
})
}
};
temporary_list.span = span!(self, span.lo);

declarations.push(prop);
StyleBlock::ListOfComponentValues(temporary_list)
}
};

declarations.push(decl_or_list_of_component_values);
}

// <delim-token> with a value of "&" (U+0026 AMPERSAND)
Expand Down Expand Up @@ -881,6 +893,25 @@ where
}
}
}

match value.last() {
Some(ComponentValue::PreservedToken(TokenAndSpan {
span,
token: Token::BadUrl { .. },
..
}))
| Some(ComponentValue::PreservedToken(TokenAndSpan {
span,
token: Token::BadString { .. },
..
})) => {
return Err(Error::new(
*span,
ErrorKind::Unexpected("token in <declaration-value>"),
));
}
_ => {}
};
}

// 5. If the last two non-<whitespace-token>s in the declaration’s value are a
Expand Down
4 changes: 1 addition & 3 deletions crates/swc_css_parser/src/parser/values_and_units/mod.rs
Expand Up @@ -25,9 +25,7 @@ where

match cur!(self) {
// ... <bad-string-token>, <bad-url-token>,
tok!("bad-string") | tok!("bad-url") => {
break;
}
tok!("bad-string") | tok!("bad-url") => break,

// ... unmatched <)-token>, <]-token>, or <}-token>,
tok!(")") | tok!("]") | tok!("}") => {
Expand Down
4 changes: 2 additions & 2 deletions crates/swc_css_parser/tests/fixture/csstree/1/output.json
Expand Up @@ -3626,7 +3626,7 @@
"type": "Declaration",
"span": {
"start": 1285,
"end": 1299,
"end": 1298,
"ctxt": 0
},
"name": {
Expand All @@ -3646,7 +3646,7 @@
"type": "Declaration",
"span": {
"start": 1304,
"end": 1315,
"end": 1314,
"ctxt": 0
},
"name": {
Expand Down
12 changes: 6 additions & 6 deletions crates/swc_css_parser/tests/fixture/csstree/1/span.rust-debug
Expand Up @@ -3686,19 +3686,19 @@
x ComponentValue
,-[$DIR/tests/fixture/csstree/1/input.css:52:5]
52 | --empty-var: ;
: ^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^
`----

x StyleBlock
,-[$DIR/tests/fixture/csstree/1/input.css:52:5]
52 | --empty-var: ;
: ^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^
`----

x Declaration
,-[$DIR/tests/fixture/csstree/1/input.css:52:5]
52 | --empty-var: ;
: ^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^
`----

x DeclarationName
Expand All @@ -3716,19 +3716,19 @@
x ComponentValue
,-[$DIR/tests/fixture/csstree/1/input.css:53:5]
53 | --bad-var:;
: ^^^^^^^^^^^
: ^^^^^^^^^^
`----

x StyleBlock
,-[$DIR/tests/fixture/csstree/1/input.css:53:5]
53 | --bad-var:;
: ^^^^^^^^^^^
: ^^^^^^^^^^
`----

x Declaration
,-[$DIR/tests/fixture/csstree/1/input.css:53:5]
53 | --bad-var:;
: ^^^^^^^^^^^
: ^^^^^^^^^^
`----

x DeclarationName
Expand Down
Expand Up @@ -430,7 +430,7 @@
"type": "Declaration",
"span": {
"start": 206,
"end": 216,
"end": 215,
"ctxt": 0
},
"name": {
Expand All @@ -450,7 +450,7 @@
"type": "Declaration",
"span": {
"start": 221,
"end": 236,
"end": 231,
"ctxt": 0
},
"name": {
Expand Down Expand Up @@ -544,7 +544,7 @@
"type": "Declaration",
"span": {
"start": 297,
"end": 322,
"end": 314,
"ctxt": 0
},
"name": {
Expand Down
Expand Up @@ -658,19 +658,19 @@
x ComponentValue
,-[$DIR/tests/fixture/value/custom-property/input.css:10:5]
10 | --empty: ;
: ^^^^^^^^^^
: ^^^^^^^^^
`----

x StyleBlock
,-[$DIR/tests/fixture/value/custom-property/input.css:10:5]
10 | --empty: ;
: ^^^^^^^^^^
: ^^^^^^^^^
`----

x Declaration
,-[$DIR/tests/fixture/value/custom-property/input.css:10:5]
10 | --empty: ;
: ^^^^^^^^^^
: ^^^^^^^^^
`----

x DeclarationName
Expand All @@ -688,19 +688,19 @@
x ComponentValue
,-[$DIR/tests/fixture/value/custom-property/input.css:11:5]
11 | --empty2: /**/;
: ^^^^^^^^^^^^^^^
: ^^^^^^^^^^
`----

x StyleBlock
,-[$DIR/tests/fixture/value/custom-property/input.css:11:5]
11 | --empty2: /**/;
: ^^^^^^^^^^^^^^^
: ^^^^^^^^^^
`----

x Declaration
,-[$DIR/tests/fixture/value/custom-property/input.css:11:5]
11 | --empty2: /**/;
: ^^^^^^^^^^^^^^^
: ^^^^^^^^^^
`----

x DeclarationName
Expand Down Expand Up @@ -802,19 +802,19 @@
x ComponentValue
,-[$DIR/tests/fixture/value/custom-property/input.css:14:5]
14 | --empty5:/* 1 */ /* 2 */;
: ^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^
`----

x StyleBlock
,-[$DIR/tests/fixture/value/custom-property/input.css:14:5]
14 | --empty5:/* 1 */ /* 2 */;
: ^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^
`----

x Declaration
,-[$DIR/tests/fixture/value/custom-property/input.css:14:5]
14 | --empty5:/* 1 */ /* 2 */;
: ^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^
`----

x DeclarationName
Expand Down

1 comment on commit e4fe840

@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: e4fe840 Previous: ac619e8 Ratio
es/full/bugs-1 355400 ns/iter (± 36968) 417132 ns/iter (± 31386) 0.85
es/full/minify/libraries/antd 1811454597 ns/iter (± 38003432) 1929838236 ns/iter (± 62155638) 0.94
es/full/minify/libraries/d3 393229153 ns/iter (± 15423522) 448627098 ns/iter (± 26588188) 0.88
es/full/minify/libraries/echarts 1547064241 ns/iter (± 48450832) 1685534636 ns/iter (± 57821745) 0.92
es/full/minify/libraries/jquery 102090045 ns/iter (± 2525431) 121054014 ns/iter (± 7567893) 0.84
es/full/minify/libraries/lodash 116027910 ns/iter (± 3111979) 146773775 ns/iter (± 20427694) 0.79
es/full/minify/libraries/moment 62199599 ns/iter (± 7207774) 68356029 ns/iter (± 9635188) 0.91
es/full/minify/libraries/react 21210005 ns/iter (± 813021) 23907140 ns/iter (± 2384930) 0.89
es/full/minify/libraries/terser 330256402 ns/iter (± 11377486) 401071439 ns/iter (± 105774281) 0.82
es/full/minify/libraries/three 580301508 ns/iter (± 25364145) 597464635 ns/iter (± 30496218) 0.97
es/full/minify/libraries/typescript 3280295049 ns/iter (± 23532606) 3710322952 ns/iter (± 91292997) 0.88
es/full/minify/libraries/victory 782087702 ns/iter (± 14015832) 911988820 ns/iter (± 49920259) 0.86
es/full/minify/libraries/vue 147424260 ns/iter (± 3849611) 180925651 ns/iter (± 11752773) 0.81
es/full/codegen/es3 32822 ns/iter (± 2268) 33633 ns/iter (± 781) 0.98
es/full/codegen/es5 32348 ns/iter (± 823) 33781 ns/iter (± 1393) 0.96
es/full/codegen/es2015 32328 ns/iter (± 1239) 33687 ns/iter (± 1360) 0.96
es/full/codegen/es2016 32401 ns/iter (± 693) 33704 ns/iter (± 1263) 0.96
es/full/codegen/es2017 32722 ns/iter (± 1368) 33601 ns/iter (± 1826) 0.97
es/full/codegen/es2018 32543 ns/iter (± 1411) 33619 ns/iter (± 536) 0.97
es/full/codegen/es2019 32489 ns/iter (± 1972) 33609 ns/iter (± 1886) 0.97
es/full/codegen/es2020 32928 ns/iter (± 405) 33720 ns/iter (± 985) 0.98
es/full/all/es3 189124039 ns/iter (± 4798009) 221332019 ns/iter (± 17767951) 0.85
es/full/all/es5 180291595 ns/iter (± 8839620) 206741870 ns/iter (± 14488315) 0.87
es/full/all/es2015 143373696 ns/iter (± 5764054) 161918906 ns/iter (± 16384092) 0.89
es/full/all/es2016 142534850 ns/iter (± 3827517) 163775795 ns/iter (± 16926496) 0.87
es/full/all/es2017 141811895 ns/iter (± 4774052) 163407731 ns/iter (± 11877118) 0.87
es/full/all/es2018 140683347 ns/iter (± 7212672) 156692344 ns/iter (± 12641828) 0.90
es/full/all/es2019 139783809 ns/iter (± 3691302) 160795826 ns/iter (± 11177785) 0.87
es/full/all/es2020 136331026 ns/iter (± 6546232) 151948687 ns/iter (± 15465789) 0.90
es/full/parser 694424 ns/iter (± 23902) 724786 ns/iter (± 35636) 0.96
es/full/base/fixer 25860 ns/iter (± 531) 27052 ns/iter (± 1184) 0.96
es/full/base/resolver_and_hygiene 91362 ns/iter (± 3610) 92554 ns/iter (± 3164) 0.99
serialization of ast node 214 ns/iter (± 12) 213 ns/iter (± 4) 1.00
serialization of serde 217 ns/iter (± 4) 218 ns/iter (± 17) 1.00

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

Please sign in to comment.