Skip to content

Commit

Permalink
fix(css/parser): Add more error recovery (#6240)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 committed Oct 24, 2022
1 parent 1a3ceaa commit 6341554
Show file tree
Hide file tree
Showing 9 changed files with 670 additions and 15 deletions.
13 changes: 7 additions & 6 deletions crates/swc_css_parser/src/lexer/mod.rs
@@ -1,4 +1,4 @@
use std::{cell::RefCell, char::REPLACEMENT_CHARACTER, mem::take, rc::Rc};
use std::{cell::RefCell, char::REPLACEMENT_CHARACTER, rc::Rc};

use swc_atoms::{js_word, JsWord};
use swc_common::{input::Input, BytePos, Span};
Expand All @@ -11,7 +11,7 @@ use crate::{

pub(crate) type LexResult<T> = Result<T, ErrorKind>;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Lexer<I>
where
I: Input,
Expand All @@ -27,7 +27,7 @@ where
raw_buf: Rc<RefCell<String>>,
sub_buf: Rc<RefCell<String>>,
sub_raw_buf: Rc<RefCell<String>>,
errors: Vec<Error>,
errors: Rc<RefCell<Vec<Error>>>,
}

impl<I> Lexer<I>
Expand All @@ -48,7 +48,7 @@ where
raw_buf: Rc::new(RefCell::new(String::with_capacity(256))),
sub_buf: Rc::new(RefCell::new(String::with_capacity(32))),
sub_raw_buf: Rc::new(RefCell::new(String::with_capacity(32))),
errors: vec![],
errors: Default::default(),
}
}

Expand Down Expand Up @@ -155,7 +155,7 @@ where
}

fn take_errors(&mut self) -> Vec<Error> {
take(&mut self.errors)
self.errors.take()
}

fn skip_ws(&mut self) -> Option<BytePos> {
Expand Down Expand Up @@ -220,7 +220,7 @@ where

#[cold]
fn emit_error(&mut self, kind: ErrorKind) {
self.errors.push(Error::new(
self.errors.borrow_mut().push(Error::new(
Span::new(self.cur_pos, self.input.cur_pos(), Default::default()),
kind,
));
Expand Down Expand Up @@ -510,6 +510,7 @@ where
let span = Span::new(self.start_pos, end, Default::default());

self.errors
.borrow_mut()
.push(Error::new(span, ErrorKind::UnterminatedBlockComment));

return;
Expand Down
8 changes: 4 additions & 4 deletions crates/swc_css_parser/src/parser/input.rs
Expand Up @@ -7,7 +7,7 @@ use swc_css_ast::{ComponentValue, ListOfComponentValues, Token, TokenAndSpan};
use super::PResult;
use crate::error::{Error, ErrorKind};

pub trait ParserInput: Iterator<Item = TokenAndSpan> {
pub trait ParserInput: Clone + Iterator<Item = TokenAndSpan> {
type State: Debug;

fn start_pos(&mut self) -> BytePos;
Expand All @@ -22,7 +22,7 @@ pub trait ParserInput: Iterator<Item = TokenAndSpan> {
fn skip_ws(&mut self) -> Option<BytePos>;
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub(super) struct Buffer<I>
where
I: ParserInput,
Expand Down Expand Up @@ -184,7 +184,7 @@ pub struct TokensState {
idx: usize,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct TokensInput<'a> {
tokens: &'a Tokens,
idx: usize,
Expand Down Expand Up @@ -272,7 +272,7 @@ pub struct ListOfComponentValuesState {
balance_stack: Vec<BalanceToken>,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ListOfComponentValuesInput<'a> {
list: &'a ListOfComponentValues,
idx: Vec<usize>,
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_css_parser/src/parser/mod.rs
Expand Up @@ -78,7 +78,7 @@ struct Ctx {
is_trying_legacy_nesting: bool,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Parser<I>
where
I: ParserInput,
Expand Down
15 changes: 15 additions & 0 deletions crates/swc_css_parser/src/parser/util.rs
Expand Up @@ -31,6 +31,21 @@ where
self.parse()
}

pub(super) fn try_parse<Ret>(
&mut self,
op: impl FnOnce(&mut Parser<I>) -> PResult<Ret>,
) -> Option<Ret> {
let mut parser = self.clone();

match op(&mut parser) {
Ok(v) => {
*self = parser;
Some(v)
}
Err(..) => None,
}
}

pub(super) fn create_locv(&self, children: Vec<ComponentValue>) -> ListOfComponentValues {
let span = match (children.first(), children.last()) {
(Some(first), Some(last)) => {
Expand Down
25 changes: 21 additions & 4 deletions crates/swc_css_parser/src/parser/values_and_units/mod.rs
Expand Up @@ -1273,12 +1273,29 @@ where
break;
}

let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..self.ctx
let value = match self.try_parse(|p| {
let ctx = Ctx {
block_contents_grammar: BlockContentsGrammar::DeclarationValue,
..p.ctx
};

p.with_ctx(ctx).parse_as::<ComponentValue>()
}) {
Some(v) => v,
None => {
if is_one_of!(self, ";", ":") {
let tok = self.input.bump().unwrap();
ComponentValue::PreservedToken(tok)
} else {
return Err(Error::new(
self.input.cur_span(),
ErrorKind::Expected("Declaration value"),
));
}
}
};

values.push(self.with_ctx(ctx).parse_as::<ComponentValue>()?);
values.push(value);
},
};

Expand Down
5 changes: 5 additions & 0 deletions crates/swc_css_parser/tests/fixture/only/1/input.css
@@ -0,0 +1,5 @@
@media screen and(-webkit-min-device-pixel-ratio:0) {
.gradientWrapper {
-chrome-: only(; z-index: 10;);
}
}

1 comment on commit 6341554

@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: 6341554 Previous: 0b267ed Ratio
es/full/bugs-1 349087 ns/iter (± 20818) 355581 ns/iter (± 39531) 0.98
es/full/minify/libraries/antd 1848473868 ns/iter (± 89935269) 1928488840 ns/iter (± 64163949) 0.96
es/full/minify/libraries/d3 409614343 ns/iter (± 20760508) 427469362 ns/iter (± 13265853) 0.96
es/full/minify/libraries/echarts 1608486119 ns/iter (± 130846741) 1578547149 ns/iter (± 388670958) 1.02
es/full/minify/libraries/jquery 114887462 ns/iter (± 19828807) 106093789 ns/iter (± 4869573) 1.08
es/full/minify/libraries/lodash 141491343 ns/iter (± 13563362) 122618801 ns/iter (± 3870064) 1.15
es/full/minify/libraries/moment 67796655 ns/iter (± 40822761) 63180789 ns/iter (± 5252635) 1.07
es/full/minify/libraries/react 22435310 ns/iter (± 3741412) 23790206 ns/iter (± 1742091) 0.94
es/full/minify/libraries/terser 349695740 ns/iter (± 13995615) 340527912 ns/iter (± 20514644) 1.03
es/full/minify/libraries/three 617500618 ns/iter (± 26562555) 579913136 ns/iter (± 27142857) 1.06
es/full/minify/libraries/typescript 3781451248 ns/iter (± 144088185) 3553069132 ns/iter (± 89545042) 1.06
es/full/minify/libraries/victory 917639175 ns/iter (± 52057858) 815506142 ns/iter (± 37507673) 1.13
es/full/minify/libraries/vue 184650808 ns/iter (± 11525434) 162169590 ns/iter (± 5989461) 1.14
es/full/codegen/es3 35940 ns/iter (± 8064) 34585 ns/iter (± 3581) 1.04
es/full/codegen/es5 36320 ns/iter (± 5812) 34379 ns/iter (± 1997) 1.06
es/full/codegen/es2015 35949 ns/iter (± 8535) 34377 ns/iter (± 2691) 1.05
es/full/codegen/es2016 35237 ns/iter (± 2479) 34626 ns/iter (± 2536) 1.02
es/full/codegen/es2017 36933 ns/iter (± 4912) 34467 ns/iter (± 3375) 1.07
es/full/codegen/es2018 35356 ns/iter (± 4065) 34766 ns/iter (± 2299) 1.02
es/full/codegen/es2019 34649 ns/iter (± 2951) 35465 ns/iter (± 4376) 0.98
es/full/codegen/es2020 34145 ns/iter (± 2065) 34788 ns/iter (± 3729) 0.98
es/full/all/es3 192718234 ns/iter (± 8895139) 204233260 ns/iter (± 10065402) 0.94
es/full/all/es5 180903546 ns/iter (± 6581988) 195629506 ns/iter (± 10886601) 0.92
es/full/all/es2015 145556227 ns/iter (± 4293097) 154909038 ns/iter (± 8769112) 0.94
es/full/all/es2016 143451902 ns/iter (± 10965848) 152288678 ns/iter (± 10809508) 0.94
es/full/all/es2017 142534738 ns/iter (± 8596021) 154481543 ns/iter (± 8108200) 0.92
es/full/all/es2018 141394124 ns/iter (± 6813176) 149083155 ns/iter (± 10952965) 0.95
es/full/all/es2019 141617993 ns/iter (± 5599785) 147755494 ns/iter (± 6376355) 0.96
es/full/all/es2020 136159374 ns/iter (± 6421679) 141138137 ns/iter (± 4611129) 0.96
es/full/parser 696640 ns/iter (± 32206) 735728 ns/iter (± 61180) 0.95
es/full/base/fixer 26099 ns/iter (± 1156) 26446 ns/iter (± 2154) 0.99
es/full/base/resolver_and_hygiene 90454 ns/iter (± 3091) 93057 ns/iter (± 5434) 0.97
serialization of ast node 218 ns/iter (± 9) 219 ns/iter (± 24) 1.00
serialization of serde 221 ns/iter (± 17) 221 ns/iter (± 18) 1

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

Please sign in to comment.