diff --git a/crates/swc_css_codegen/src/ctx.rs b/crates/swc_css_codegen/src/ctx.rs index 04d12be43830..9b5601f2dd64 100644 --- a/crates/swc_css_codegen/src/ctx.rs +++ b/crates/swc_css_codegen/src/ctx.rs @@ -22,6 +22,7 @@ where pub(crate) struct Ctx { pub in_single_line_selectors: bool, pub allow_to_lowercase: bool, + pub in_list_of_component_values: bool, } pub(super) struct WithCtx<'w, I: 'w + CssWriter> { diff --git a/crates/swc_css_codegen/src/lib.rs b/crates/swc_css_codegen/src/lib.rs index f45be61e7827..5d6c4a822a76 100644 --- a/crates/swc_css_codegen/src/lib.rs +++ b/crates/swc_css_codegen/src/lib.rs @@ -68,7 +68,15 @@ where match n { Rule::QualifiedRule(n) => emit!(self, n), Rule::AtRule(n) => emit!(self, n), - Rule::ListOfComponentValues(n) => emit!(self, n), + Rule::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } @@ -81,11 +89,19 @@ where #[emitter] fn emit_qualified_rule_prelude(&mut self, n: &QualifiedRulePrelude) -> Result { match n { - QualifiedRulePrelude::ListOfComponentValues(n) => emit!(self, n), QualifiedRulePrelude::SelectorList(n) => { emit!(self, n); formatting_space!(self); } + QualifiedRulePrelude::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } @@ -135,7 +151,6 @@ where #[emitter] fn emit_at_rule_prelude(&mut self, n: &AtRulePrelude) -> Result { match n { - AtRulePrelude::ListOfComponentValues(n) => emit!(self, n), AtRulePrelude::CharsetPrelude(n) => { space!(self); emit!(self, n); @@ -295,6 +310,15 @@ where space!(self); emit!(self, n); } + AtRulePrelude::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } @@ -1118,6 +1142,10 @@ where for (idx, node) in iter.enumerate() { emit!(self, node); + if self.ctx.in_list_of_component_values { + continue; + } + let is_current_preserved_token = matches!(node, ComponentValue::PreservedToken(_)); let next = nodes.get(idx + 1); let is_next_preserved_token = matches!(next, Some(ComponentValue::PreservedToken(_))); @@ -1333,7 +1361,7 @@ where decrease_indent!(self); } _ => { - if ending == "]" && idx != len - 1 { + if !self.ctx.in_list_of_component_values && ending == "]" && idx != len - 1 { space!(self); } } @@ -1380,7 +1408,15 @@ where #[emitter] fn emit_style_block(&mut self, n: &StyleBlock) -> Result { match n { - StyleBlock::ListOfComponentValues(n) => emit!(self, n), + StyleBlock::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } StyleBlock::AtRule(n) => emit!(self, n), StyleBlock::Declaration(n) => emit!(self, n), StyleBlock::QualifiedRule(n) => emit!(self, n), @@ -1392,7 +1428,15 @@ where match n { DeclarationOrAtRule::Declaration(n) => emit!(self, n), DeclarationOrAtRule::AtRule(n) => emit!(self, n), - DeclarationOrAtRule::ListOfComponentValues(n) => emit!(self, n), + DeclarationOrAtRule::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } @@ -2137,7 +2181,15 @@ where fn emit_forgiving_complex_list(&mut self, n: &ForgivingComplexSelector) -> Result { match n { ForgivingComplexSelector::ComplexSelector(n) => emit!(self, n), - ForgivingComplexSelector::ListOfComponentValues(n) => emit!(self, n), + ForgivingComplexSelector::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } @@ -2175,7 +2227,15 @@ where fn emit_forgiving_relative_selector(&mut self, n: &ForgivingRelativeSelector) -> Result { match n { ForgivingRelativeSelector::RelativeSelector(n) => emit!(self, n), - ForgivingRelativeSelector::ListOfComponentValues(n) => emit!(self, n), + ForgivingRelativeSelector::ListOfComponentValues(n) => { + emit!( + &mut *self.with_ctx(Ctx { + in_list_of_component_values: true, + ..self.ctx + }), + n + ) + } } } diff --git a/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.css b/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.css index 61b4504646e3..c2ce1c80cb8c 100644 --- a/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.css +++ b/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.css @@ -23,9 +23,9 @@ $bad: rule; a { div.major { color: blue } color: red } a { - div: hover {color:blue} color:red; + div: hover { color: blue } color:red; } a { - div: hover {color:blue}; + div: hover { color: blue }; color: red; } diff --git a/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.min.css b/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.min.css index 97b9cc7cae2c..c8ea0b3e704f 100644 --- a/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.min.css +++ b/crates/swc_css_codegen/tests/fixture/qualified_rule/recovery/output.min.css @@ -1,4 +1,4 @@ {}{color:red}#broken# {color:red}$bad{color:red}$bad {color:red}$bad foo{color:red}$bad foo {color:red}$bad: rule; -a {div.major { color: blue } color: red }a{div:hover{color:blue}color:red}a{div:hover{color:blue};color:red} +a {div.major { color: blue } color: red }a{div:hover{ color: blue }color:red}a{div:hover{ color: blue };color:red} diff --git a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.css b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.css index 8f032a57b5e5..638eedb17c41 100644 --- a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.css +++ b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.css @@ -3,12 +3,10 @@ .selector:not(*:root) {} @supports (-webkit-appearance: none) {} .selector { - (;property: value; - );} + (;property: value;);} .selector { - [;property: value; - ];} -@media screen {} + [;property: value;];} +@media \\0 screen {} @media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) { .selector {} } @@ -153,11 +151,9 @@ _:-ms-fullscreen, .selector:not(*:root) {} @supports (-webkit-appearance: none) {} .selector { - (;property: value; - );} + (;property: value;);} .selector { - [;property: value; - ];} + [;property: value;];} html:first-child .selector {} _:-o-prefocus, body:last-child .selector {} @@ -173,11 +169,9 @@ body:last-child .selector {} .selector:not(*:root) {} @supports (-webkit-appearance: none) {} .selector { - (;property: value; - );} + (;property: value;);} .selector { - [;property: value; - ];} + [;property: value;];} @media screen and (min-width: 0\0) {} @media screen { @media (min-width: 0px) {} @@ -188,7 +182,7 @@ html[xmlns*=""]:root .selector {} *|html[xmlns*=""] .selector {} _::-moz-svg-foreign-content, :root .selector {} -@media screen {} +@media \\0 screen {} a { *color : black;_background: white; font-size: big; diff --git a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css index 8a9fcb31e50b..a51089ce3b68 100644 --- a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css +++ b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/hacks/output.min.css @@ -1 +1 @@ -.selector:not(*:root){}@media screen and (min-width:0\0){}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property:value;);}.selector{[;property:value;];}@media screen{}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}body:empty .selector{}body:last-child .selector,x:-moz-any-link{}@media \0 all{}body:last-child .selector,x:-moz-any-link,x:default{}body:not(:-moz-handler-blocked) .selector{}@media screen and (-moz-images-in-menus:0){}@media screen and (min--moz-device-pixel-ratio:0){}_::-moz-progress-bar,body:last-child .selector{}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:.001dpcm){}@media all and (-moz-images-in-menus:0)and (min-resolution:.001dpcm){}@media all and (min--moz-device-pixel-ratio:0){@media(min-width:0px){}}@media all and (-moz-images-in-menus:0){@media(min-width:0px){}}@supports(-moz-appearance:meterbar){}_::-moz-range-track,body:last-child .selector{}@supports(-moz-appearance:meterbar)and (display:flex){}@supports(-moz-appearance:meterbar)and (cursor:zoom-in){}@supports(-moz-appearance:meterbar)and (background-attachment:local){}@supports(-moz-appearance:meterbar)and (image-orientation:90deg){}@supports(-moz-appearance:meterbar)and (all:initial){}@supports(-moz-appearance:meterbar)and (list-style-type:japanese-formal){}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:30dpcm){}@supports(-moz-appearance:meterbar)and (background-blend-mode:difference,normal){}_:-moz-tree-row(hover),.selector{}_::selection,.selector:not([attr*=""]){}@supports(-webkit-appearance:none){}* html .selector{}.unused-class.selector{}html>body .selector{}*:first-child+html .selector{}.selector,x:-ie7{}*+html .selector{}body *.selector{}.selector\ {}html>body .selector{}head~body .selector{}_::selection,.selector:not([attr*=""]){}:root .selector{}body:last-child .selector{}body:nth-of-type(1) .selector{}body:first-of-type .selector{}.selector:not([attr*=""]){}.selector{_property:value}.selector{-property:value}.selector{property:value\9}.selector{property:value\9}.selector{!property: value;color:red}.selector{$property: value;color:red}.selector{color:red;&property: value;}.selector{*property: value;color:red}.selector{)property: value;color:red}.selector{=property: value;color:red}.selector{%property: value;color:red}.selector{+property: value;color:red}.selector{color:red;@property: value;}.selector{,property: value;color:red}.selector{.property: value;color:red}.selector{/property: value;color:red}.selector{`property: value;color:red}.selector{]property: value;color:red}.selector{#property: value;color:red}.selector{~property: value;color:red}.selector{?property: value;color:red}.selector{:property: value;color:red}.selector{|property: value;color:red}.selector{property: value !ie;}@media screen\9{}@media \0screen\,screen\9 {}@media \0screen{}@media screen and (min-width:0\0){}_:-ms-input-placeholder,:root .selector{}_:-ms-fullscreen,:root .selector{}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){}@media screen{@media(min-width:0px){}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property:value;);}.selector{[;property:value;];}html:first-child .selector{}_:-o-prefocus,body:last-child .selector{}@media all and (-webkit-min-device-pixel-ratio:1e4),not all and (-webkit-min-device-pixel-ratio:0){}@media(min-resolution:.001dpcm){_:-o-prefocus,.selector{}}*|html[xmlns*=""] .selector{}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property:value;);}.selector{[;property:value;];}@media screen and (min-width:0\0){}@media screen{@media(min-width:0px){}}html:first-child .selector{}html[xmlns*=""] body:last-child .selector{}html[xmlns*=""]:root .selector{}*|html[xmlns*=""] .selector{}_::-moz-svg-foreign-content,:root .selector{}@media screen{}a{*color : black;_background:white;font-size:big;$(var)-size: 100%;}a{*b:c}div{color:red}selector{property:value;property:normal-value}div{color:red} +.selector:not(*:root){}@media screen and (min-width:0\0){}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media \\0 screen {}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}body:empty .selector{}body:last-child .selector,x:-moz-any-link{}@media \0 all{}body:last-child .selector,x:-moz-any-link,x:default{}body:not(:-moz-handler-blocked) .selector{}@media screen and (-moz-images-in-menus:0){}@media screen and (min--moz-device-pixel-ratio:0){}_::-moz-progress-bar,body:last-child .selector{}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:.001dpcm){}@media all and (-moz-images-in-menus:0)and (min-resolution:.001dpcm){}@media all and (min--moz-device-pixel-ratio:0){@media(min-width:0px){}}@media all and (-moz-images-in-menus:0){@media(min-width:0px){}}@supports(-moz-appearance:meterbar){}_::-moz-range-track,body:last-child .selector{}@supports(-moz-appearance:meterbar)and (display:flex){}@supports(-moz-appearance:meterbar)and (cursor:zoom-in){}@supports(-moz-appearance:meterbar)and (background-attachment:local){}@supports(-moz-appearance:meterbar)and (image-orientation:90deg){}@supports(-moz-appearance:meterbar)and (all:initial){}@supports(-moz-appearance:meterbar)and (list-style-type:japanese-formal){}@media all and (min--moz-device-pixel-ratio:0)and (min-resolution:30dpcm){}@supports(-moz-appearance:meterbar)and (background-blend-mode:difference,normal){}_:-moz-tree-row(hover),.selector{}_::selection,.selector:not([attr*=""]){}@supports(-webkit-appearance:none){}* html .selector{}.unused-class.selector{}html>body .selector{}*:first-child+html .selector{}.selector,x:-ie7{}*+html .selector{}body *.selector{}.selector\ {}html>body .selector{}head~body .selector{}_::selection,.selector:not([attr*=""]){}:root .selector{}body:last-child .selector{}body:nth-of-type(1) .selector{}body:first-of-type .selector{}.selector:not([attr*=""]){}.selector{_property:value}.selector{-property:value}.selector{property:value\9}.selector{property:value\9}.selector{!property: value;color:red}.selector{$property: value;color:red}.selector{color:red;&property: value;}.selector{*property: value;color:red}.selector{)property: value;color:red}.selector{=property: value;color:red}.selector{%property: value;color:red}.selector{+property: value;color:red}.selector{color:red;@property: value;}.selector{,property: value;color:red}.selector{.property: value;color:red}.selector{/property: value;color:red}.selector{`property: value;color:red}.selector{]property: value;color:red}.selector{#property: value;color:red}.selector{~property: value;color:red}.selector{?property: value;color:red}.selector{:property: value;color:red}.selector{|property: value;color:red}.selector{property: value !ie;}@media screen\9{}@media \0screen\,screen\9 {}@media \0screen{}@media screen and (min-width:0\0){}_:-ms-input-placeholder,:root .selector{}_:-ms-fullscreen,:root .selector{}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){}@media screen{@media(min-width:0px){}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}html:first-child .selector{}_:-o-prefocus,body:last-child .selector{}@media all and (-webkit-min-device-pixel-ratio:1e4),not all and (-webkit-min-device-pixel-ratio:0){}@media(min-resolution:.001dpcm){_:-o-prefocus,.selector{}}*|html[xmlns*=""] .selector{}@media all and (-webkit-min-device-pixel-ratio:0)and (min-resolution:.001dpcm){.selector{}}.selector:not(*:root){}@supports(-webkit-appearance:none){}.selector{(;property: value;);}.selector{[;property: value;];}@media screen and (min-width:0\0){}@media screen{@media(min-width:0px){}}html:first-child .selector{}html[xmlns*=""] body:last-child .selector{}html[xmlns*=""]:root .selector{}*|html[xmlns*=""] .selector{}_::-moz-svg-foreign-content,:root .selector{}@media \\0 screen {}a{*color : black;_background:white;font-size:big;$(var)-size: 100%;}a{*b:c}div{color:red}selector{property:value;property:normal-value}div{color:red} diff --git a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.css b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.css index 71ca24392800..2adaf96bea4f 100644 --- a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.css +++ b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.css @@ -14,13 +14,13 @@ unknown: x {a,b}; } * { - unknown: x (a+b); + unknown: x ( a + b ); } * { unknown: x (a/b); } * { - unknown: x (a*b); + unknown: x ( a * b ); } * { unknown: x (a,b); diff --git a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.min.css b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.min.css index 35c2378d7f29..9c16f2f706b8 100644 --- a/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.min.css +++ b/crates/swc_css_codegen/tests/fixture/style-blocks-contents/simple-block/output.min.css @@ -1 +1 @@ -*{unknown:x (a+b)}*{unknown:x (a-b)}*{unknown:x (a,b)}*{unknown:x[a , b]}*{unknown:x{a,b}}*{unknown:x (a+b)}*{unknown:x (a/b)}*{unknown:x (a*b)}*{unknown:x (a,b)}a{b:c,d}a{b:c,(d,e)}a{b:c,d,e}a{b:c,(d,e),f}a{grid-template-rows:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3];grid-template-rows:[linename1 linename2]100px repeat(4,[col-start]min-content[col-middle]max-content[col-end])1fr[linename3];grid-template:[linename]100px/[columnname1]30%[columnname2]70%;grid-template:fit-content(100px)/fit-content(40%)} +*{unknown:x (a+b)}*{unknown:x (a-b)}*{unknown:x (a,b)}*{unknown:x[a , b]}*{unknown:x{a,b}}*{unknown:x ( a + b )}*{unknown:x (a/b)}*{unknown:x ( a * b )}*{unknown:x (a,b)}a{b:c,d}a{b:c,(d,e)}a{b:c,d,e}a{b:c,(d,e),f}a{grid-template-rows:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3];grid-template-rows:[linename1 linename2]100px repeat(4,[col-start]min-content[col-middle]max-content[col-end])1fr[linename3];grid-template:[linename]100px/[columnname1]30%[columnname2]70%;grid-template:fit-content(100px)/fit-content(40%)} diff --git a/crates/swc_css_lints/tests/rules/fail/no-duplicate-at-import-rules/11/output.stderr b/crates/swc_css_lints/tests/rules/fail/no-duplicate-at-import-rules/11/output.stderr index 75dcbb68ad3d..2dd8531a4779 100644 --- a/crates/swc_css_lints/tests/rules/fail/no-duplicate-at-import-rules/11/output.stderr +++ b/crates/swc_css_lints/tests/rules/fail/no-duplicate-at-import-rules/11/output.stderr @@ -1,10 +1,4 @@ - x Unexpected duplicate '@import' rule 'a.css'. - ,-[$DIR/tests/rules/fail/no-duplicate-at-import-rules/11/input.css:2:1] - 2 | @import 'a.css' layer(); - : ^^^^^^^^^^^^^^^^^^^^^^^^ - `---- - x Unexpected duplicate '@import' rule 'a.css'. ,-[$DIR/tests/rules/fail/no-duplicate-at-import-rules/11/input.css:3:1] 3 | @import 'a.css' layer(default); diff --git a/crates/swc_css_modules/tests/fixture/import/import.compiled.css b/crates/swc_css_modules/tests/fixture/import/import.compiled.css index 9b1bdcb3eebb..f858c5580534 100644 --- a/crates/swc_css_modules/tests/fixture/import/import.compiled.css +++ b/crates/swc_css_modules/tests/fixture/import/import.compiled.css @@ -17,6 +17,8 @@ @import ''; @import ""; @import " "; +@import " +"; @import url(); @import url(''); @import url(""); @@ -136,7 +138,7 @@ st.css'); @import url("./test.css") layer(default) supports(display: flex) screen and (min-width: 400px); @import url("./test.css") layer supports(display: flex) screen and (min-width: 400px); @import url("./test.css") layer() supports(display: flex) screen and (min-width: 400px); -@import url("./test.css"); +@import url("./test.css") layer(); @import url("http://example.com/style.css") supports(display: flex) screen and (min-width: 400px); @import url("./test.css") layer(default) supports(display: flex) screen and (min-width: 400px); @import url("./test.css") screen and (min-width: 400px); diff --git a/crates/swc_css_parser/src/error.rs b/crates/swc_css_parser/src/error.rs index f1c57fc1c918..56b085786024 100644 --- a/crates/swc_css_parser/src/error.rs +++ b/crates/swc_css_parser/src/error.rs @@ -39,6 +39,9 @@ impl Error { ErrorKind::UnexpectedCharInUrl => "Unexpected character in url".into(), // Parser + ErrorKind::EofButExpected(s) => { + format!("Unexpected end of file, but expected {}", s).into() + } ErrorKind::Ignore => "Not an error".into(), ErrorKind::UnexpectedChar(c) => format!("Unexpected character `{:?}`", c).into(), ErrorKind::Expected(s) => format!("Expected {}", s).into(), @@ -90,6 +93,7 @@ pub enum ErrorKind { // Parser errors Ignore, + EofButExpected(&'static str), UnexpectedChar(char), Expected(&'static str), Unexpected(&'static str), diff --git a/crates/swc_css_parser/src/parser/at_rules/mod.rs b/crates/swc_css_parser/src/parser/at_rules/mod.rs index 0418646cd822..dfe5b44b647d 100644 --- a/crates/swc_css_parser/src/parser/at_rules/mod.rs +++ b/crates/swc_css_parser/src/parser/at_rules/mod.rs @@ -1,5 +1,5 @@ -use swc_atoms::js_word; -use swc_common::{BytePos, Span}; +use swc_atoms::{js_word, JsWord}; +use swc_common::Span; use swc_css_ast::*; use super::{input::ParserInput, PResult, Parser}; @@ -9,818 +9,838 @@ use crate::{ Parse, }; -impl Parse for Parser +impl Parser where I: ParserInput, { - fn parse(&mut self) -> PResult { - // Consume the next input token. Create a new at-rule with its name set to the - // value of the current input token, its prelude initially set to an empty list, - // and its value initially set to nothing. - let at_rule_span = self.input.cur_span(); - let at_keyword_name = match bump!(self) { - Token::AtKeyword { value, raw } => (value, raw), - _ => { - unreachable!() - } - }; - let at_rule_name = if at_keyword_name.0.starts_with("--") { - AtRuleName::DashedIdent(DashedIdent { - span: Span::new( - at_rule_span.lo + BytePos(1), - at_rule_span.hi, - Default::default(), - ), - value: at_keyword_name.0, - raw: Some(at_keyword_name.1), - }) - } else { - AtRuleName::Ident(Ident { - span: Span::new( - at_rule_span.lo + BytePos(1), - at_rule_span.hi, - Default::default(), - ), - value: at_keyword_name.0, - raw: Some(at_keyword_name.1), - }) - }; - let mut at_rule = AtRule { - span: span!(self, at_rule_span.lo), - name: at_rule_name, - prelude: None, - block: None, - }; - let lowercased_name = match &at_rule.name { - AtRuleName::Ident(ident) => ident.value.to_ascii_lowercase(), - AtRuleName::DashedIdent(dashed_ident) => dashed_ident.value.to_ascii_lowercase(), - }; - let parse_prelude = |parser: &mut Parser| -> PResult>> { - match lowercased_name { - js_word!("viewport") - | js_word!("-ms-viewport") - | js_word!("-o-viewport") - | js_word!("font-face") => { - parser.input.skip_ws(); - - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - - Ok(None) - } - js_word!("charset") => { - parser.input.skip_ws(); - - let span = parser.input.cur_span(); - let charset = match cur!(parser) { - tok!("string") => parser.parse()?, - _ => { - return Err(Error::new(span, ErrorKind::InvalidCharsetAtRule)); - } - }; - - let prelude = AtRulePrelude::CharsetPrelude(charset); - - parser.input.skip_ws(); - - if !is!(parser, ";") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("';' token"))); - } - - Ok(Some(Box::new(prelude))) - } - js_word!("container") => { - parser.input.skip_ws(); - - let prelude = AtRulePrelude::ContainerPrelude(parser.parse()?); - - parser.input.skip_ws(); - - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - - Ok(Some(Box::new(prelude))) - } - js_word!("counter-style") => { - parser.input.skip_ws(); - - let prelude = AtRulePrelude::CounterStylePrelude(parser.parse()?); - - parser.input.skip_ws(); - - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - - Ok(Some(Box::new(prelude))) - } - js_word!("font-palette-values") => { - parser.input.skip_ws(); - - let prelude = AtRulePrelude::FontPaletteValuesPrelude(parser.parse()?); - - parser.input.skip_ws(); - - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - - Ok(Some(Box::new(prelude))) - } - js_word!("font-feature-values") => { - parser.input.skip_ws(); - - let prelude = AtRulePrelude::FontFeatureValuesPrelude(parser.parse()?); - - parser.input.skip_ws(); - - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - - Ok(Some(Box::new(prelude))) - } - js_word!("stylistic") - | js_word!("historical-forms") - | js_word!("styleset") - | js_word!("character-variant") - | js_word!("swash") - | js_word!("ornaments") - | js_word!("annotation") - if parser.ctx.in_font_feature_values_at_rule => - { - parser.input.skip_ws(); - - Ok(None) - } - js_word!("layer") => { - parser.input.skip_ws(); - - let prelude = if is!(parser, Ident) { - let mut name_list: Vec = vec![]; - - while is!(parser, Ident) { - name_list.push(parser.parse()?); - - parser.input.skip_ws(); + pub(super) fn parse_at_rule_prelude( + &mut self, + name: &JsWord, + ) -> PResult> { + let prelude = match *name { + js_word!("charset") => { + self.input.skip_ws(); - if is!(parser, ",") { - eat!(parser, ","); + let prelude = AtRulePrelude::CharsetPrelude(self.parse()?); - parser.input.skip_ws(); - } - } + self.input.skip_ws(); - if is!(parser, ";") { - let first = name_list[0].span; - let last = name_list[name_list.len() - 1].span; + Some(prelude) + } + js_word!("color-profile") => { + self.input.skip_ws(); - Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList( - LayerNameList { - name_list, - span: Span::new(first.lo, last.hi, Default::default()), - }, - ))) + let name = match cur!(self) { + Token::Ident { value, .. } => { + if value.starts_with("--") { + ColorProfileName::DashedIdent(self.parse()?) } else { - if name_list.len() > 1 { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("';' token"))); - } - - Some(AtRulePrelude::LayerPrelude(LayerPrelude::Name( - name_list.remove(0), - ))) - } - } else { - None - }; - - parser.input.skip_ws(); - - match prelude { - Some(AtRulePrelude::LayerPrelude(LayerPrelude::Name(_))) | None => { - if !is!(parser, "{") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } - } - Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList(_))) => { - if !is!(parser, ";") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("';' token"))); - } - } - _ => { - unreachable!(); + ColorProfileName::Ident(self.parse()?) } } + _ => { + let span = self.input.cur_span(); - Ok(prelude.map(Box::new)) - } - js_word!("document") | js_word!("-moz-document") => { - parser.input.skip_ws(); - - let span = parser.input.cur_span(); - let url_match_fn = parser.parse()?; - let mut matching_functions = vec![url_match_fn]; - - loop { - parser.input.skip_ws(); - - if !eat!(parser, ",") { - break; - } - - parser.input.skip_ws(); - - matching_functions.push(parser.parse()?); + return Err(Error::new(span, ErrorKind::Expected("ident token"))); } + }; - let prelude = AtRulePrelude::DocumentPrelude(DocumentPrelude { - span: span!(parser, span.lo), - matching_functions, - }); - - parser.input.skip_ws(); + let prelude = AtRulePrelude::ColorProfilePrelude(name); - if !is!(parser, "{") { - let span = parser.input.cur_span(); + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } + Some(prelude) + } + js_word!("container") => { + self.input.skip_ws(); - Ok(Some(Box::new(prelude))) - } - js_word!("page") => { - parser.input.skip_ws(); + let prelude = AtRulePrelude::ContainerPrelude(self.parse()?); - let prelude = if !is!(parser, "{") { - Some(AtRulePrelude::PagePrelude(parser.parse()?)) - } else { - None - }; - - parser.input.skip_ws(); + self.input.skip_ws(); - Ok(prelude.map(Box::new)) - } - js_word!("top-left-corner") - | js_word!("top-left") - | js_word!("top-center") - | js_word!("top-right") - | js_word!("top-right-corner") - | js_word!("bottom-left-corner") - | js_word!("bottom-left") - | js_word!("bottom-center") - | js_word!("bottom-right") - | js_word!("bottom-right-corner") - | js_word!("left-top") - | js_word!("left-middle") - | js_word!("left-bottom") - | js_word!("right-top") - | js_word!("right-middle") - | js_word!("right-bottom") - if parser.ctx.in_page_at_rule => - { - parser.input.skip_ws(); + Some(prelude) + } + js_word!("counter-style") => { + self.input.skip_ws(); - Ok(None) - } - js_word!("property") => { - parser.input.skip_ws(); + let prelude = AtRulePrelude::CounterStylePrelude(self.parse()?); - let prelude = AtRulePrelude::PropertyPrelude(parser.parse()?); + self.input.skip_ws(); - parser.input.skip_ws(); + Some(prelude) + } + js_word!("custom-media") => { + self.input.skip_ws(); - if !is!(parser, "{") { - let span = parser.input.cur_span(); + let prelude = AtRulePrelude::CustomMediaPrelude(self.parse()?); - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } + self.input.skip_ws(); - Ok(Some(Box::new(prelude))) - } - js_word!("namespace") => { - parser.input.skip_ws(); + Some(prelude) + } + js_word!("document") | js_word!("-moz-document") => { + self.input.skip_ws(); - let span = parser.input.cur_span(); - let mut prefix = None; + let span = self.input.cur_span(); + let url_match_fn = self.parse()?; + let mut matching_functions = vec![url_match_fn]; - if is!(parser, Ident) { - prefix = match cur!(parser) { - tok!("ident") => Some(parser.parse()?), - _ => { - unreachable!() - } - }; + loop { + self.input.skip_ws(); - parser.input.skip_ws(); + if !eat!(self, ",") { + break; } - let uri = match cur!(parser) { - tok!("string") => NamespacePreludeUri::Str(parser.parse()?), - tok!("url") => NamespacePreludeUri::Url(parser.parse()?), - tok!("function") => NamespacePreludeUri::Url(parser.parse()?), - _ => { - let span = parser.input.cur_span(); - - return Err(Error::new( - span, - ErrorKind::Expected("string, url or function tokens"), - )); - } - }; - - let prelude = AtRulePrelude::NamespacePrelude(NamespacePrelude { - span: span!(parser, span.lo), - prefix, - uri: Box::new(uri), - }); - - if !is!(parser, ";") { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("';' token"))); - } + self.input.skip_ws(); - Ok(Some(Box::new(prelude))) + matching_functions.push(self.parse()?); } - js_word!("color-profile") => { - parser.input.skip_ws(); - - let name = match cur!(parser) { - Token::Ident { value, .. } => { - if value.starts_with("--") { - ColorProfileName::DashedIdent(parser.parse()?) - } else { - ColorProfileName::Ident(parser.parse()?) - } - } - _ => { - let span = parser.input.cur_span(); - - return Err(Error::new(span, ErrorKind::Expected("ident"))); - } - }; - let prelude = Box::new(AtRulePrelude::ColorProfilePrelude(name)); + let prelude = AtRulePrelude::DocumentPrelude(DocumentPrelude { + span: span!(self, span.lo), + matching_functions, + }); - parser.input.skip_ws(); + self.input.skip_ws(); - if !is!(parser, "{") { - let span = parser.input.cur_span(); + Some(prelude) + } + js_word!("font-face") => { + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } + if !is!(self, EOF) { + let span = self.input.cur_span(); - Ok(Some(prelude)) + return Err(Error::new(span, ErrorKind::Expected("'{' token"))); } - js_word!("nest") => { - parser.input.skip_ws(); - let prelude = Box::new(AtRulePrelude::NestPrelude(parser.parse()?)); + None + } + js_word!("font-feature-values") => { + self.input.skip_ws(); - parser.input.skip_ws(); + let prelude = AtRulePrelude::FontFeatureValuesPrelude(self.parse()?); - if !is!(parser, "{") { - let span = parser.input.cur_span(); + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); - } + Some(prelude) + } + js_word!("font-palette-values") => { + self.input.skip_ws(); - Ok(Some(prelude)) - } - js_word!("media") => { - parser.input.skip_ws(); + let prelude = AtRulePrelude::FontPaletteValuesPrelude(self.parse()?); - let media = if !is!(parser, "{") { - let media_query_list = parser.parse()?; + self.input.skip_ws(); - Some(Box::new(AtRulePrelude::MediaPrelude(media_query_list))) - } else { - None - }; + Some(prelude) + } + js_word!("stylistic") + | js_word!("historical-forms") + | js_word!("styleset") + | js_word!("character-variant") + | js_word!("swash") + | js_word!("ornaments") + | js_word!("annotation") + if self.ctx.in_font_feature_values_at_rule => + { + self.input.skip_ws(); - parser.input.skip_ws(); + if !is!(self, EOF) { + let span = self.input.cur_span(); - Ok(media) + return Err(Error::new(span, ErrorKind::Expected("'{' token"))); } - js_word!("supports") => { - parser.input.skip_ws(); - - let prelude = Box::new(AtRulePrelude::SupportsPrelude(parser.parse()?)); - parser.input.skip_ws(); + None + } + js_word!("import") => { + self.input.skip_ws(); - Ok(Some(prelude)) - } - js_word!("import") => { - parser.input.skip_ws(); - - let span = parser.input.cur_span(); - let href = Box::new(match cur!(parser) { - tok!("string") => ImportPreludeHref::Str(parser.parse()?), - tok!("url") => ImportPreludeHref::Url(parser.parse()?), - tok!("function") => ImportPreludeHref::Url(parser.parse()?), - _ => { - return Err(Error::new( - span, - ErrorKind::Expected("string, url or function token"), - )) - } - }); + let span = self.input.cur_span(); + let href = Box::new(match cur!(self) { + tok!("string") => ImportPreludeHref::Str(self.parse()?), + tok!("url") => ImportPreludeHref::Url(self.parse()?), + tok!("function") => ImportPreludeHref::Url(self.parse()?), + _ => { + return Err(Error::new( + span, + ErrorKind::Expected("string, url or function token"), + )) + } + }); - parser.input.skip_ws(); + self.input.skip_ws(); - let layer_name = match cur!(parser) { + let layer_name = if !is!(self, EOF) { + match cur!(self) { Token::Ident { value, .. } if *value.to_ascii_lowercase() == *"layer" => { - let name = ImportPreludeLayerName::Ident(parser.parse()?); + let name = ImportPreludeLayerName::Ident(self.parse()?); - parser.input.skip_ws(); + self.input.skip_ws(); Some(Box::new(name)) } Token::Function { value, .. } if *value.to_ascii_lowercase() == *"layer" => { + let span = self.input.cur_span(); + let ctx = Ctx { in_import_at_rule: true, block_contents_grammar: BlockContentsGrammar::DeclarationValue, - ..parser.ctx + ..self.ctx }; - let func = parser.with_ctx(ctx).parse_as::()?; + let func = self.with_ctx(ctx).parse_as::()?; + + self.input.skip_ws(); + if func.value.len() != 1 { - parser.errors.push(Error::new( - func.span, + return Err(Error::new( + span, ErrorKind::Expected( "layer function inside @import expected to have exactly \ one ident argument", ), )); - None } else if let ComponentValue::LayerName(LayerName { name: name_raw, .. }) = &func.value[0] { - parser.input.skip_ws(); + self.input.skip_ws(); if name_raw.is_empty() { - parser.errors.push(Error::new( - func.span, + return Err(Error::new( + span, ErrorKind::Expected( "layer function inside @import expected to have \ exactly one ident argument", ), )); - None } else { Some(Box::new(ImportPreludeLayerName::Function(func))) } } else { - parser.errors.push(Error::new( - func.span, + return Err(Error::new( + span, ErrorKind::Expected( "layer function inside @import expected to have exactly \ one ident argument", ), )); - None } } _ => None, - }; + } + } else { + None + }; - let supports = match cur!(parser) { + let supports = if !is!(self, EOF) { + match cur!(self) { Token::Function { value, .. } if *value.to_ascii_lowercase() == *"supports" => { - bump!(parser); + bump!(self); - parser.input.skip_ws(); + self.input.skip_ws(); let supports = - if is_case_insensitive_ident!(parser, "not") || is!(parser, "(") { - ImportPreludeSupportsType::SupportsCondition(parser.parse()?) + if is_case_insensitive_ident!(self, "not") || is!(self, "(") { + ImportPreludeSupportsType::SupportsCondition(self.parse()?) } else { - ImportPreludeSupportsType::Declaration(parser.parse()?) + ImportPreludeSupportsType::Declaration(self.parse()?) }; - expect!(parser, ")"); + expect!(self, ")"); + + self.input.skip_ws(); Some(Box::new(supports)) } _ => None, - }; + } + } else { + None + }; - let media = if !is!(parser, ";") { - Some(parser.parse()?) - } else { - None - }; + let media = if !is!(self, EOF) { + let media_query_list = self.parse()?; - parser.input.skip_ws(); + self.input.skip_ws(); - let prelude = Box::new(AtRulePrelude::ImportPrelude(ImportPrelude { - span: span!(parser, span.lo), - href, - layer_name, - supports, - media, - })); + Some(media_query_list) + } else { + None + }; - if !is!(parser, ";") { - let span = parser.input.cur_span(); + let prelude = AtRulePrelude::ImportPrelude(ImportPrelude { + span: span!(self, span.lo), + href, + layer_name, + supports, + media, + }); + + Some(prelude) + } + js_word!("keyframes") + | js_word!("-webkit-keyframes") + | js_word!("-moz-keyframes") + | js_word!("-o-keyframes") + | js_word!("-ms-keyframes") => { + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Expected("';' token"))); - } + let prelude = AtRulePrelude::KeyframesPrelude(self.parse()?); - Ok(Some(prelude)) - } - js_word!("keyframes") - | js_word!("-webkit-keyframes") - | js_word!("-moz-keyframes") - | js_word!("-o-keyframes") - | js_word!("-ms-keyframes") => { - parser.input.skip_ws(); + self.input.skip_ws(); + + Some(prelude) + } + js_word!("layer") => { + self.input.skip_ws(); - let prelude = Box::new(AtRulePrelude::KeyframesPrelude(parser.parse()?)); + if is!(self, Ident) { + let mut name_list: Vec = vec![]; - parser.input.skip_ws(); + name_list.push(self.parse()?); - if !is!(parser, "{") { - let span = parser.input.cur_span(); + loop { + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Expected("'{' token"))); + if !eat!(self, ",") { + break; + } + + self.input.skip_ws(); + + name_list.push(self.parse()?); } - Ok(Some(prelude)) - } - js_word!("custom-media") => { - parser.input.skip_ws(); + let res = if name_list.len() == 1 { + Some(AtRulePrelude::LayerPrelude(LayerPrelude::Name( + name_list.remove(0), + ))) + } else { + let first = name_list[0].span; + let last = name_list[name_list.len() - 1].span; - let prelude = Box::new(AtRulePrelude::CustomMediaPrelude(parser.parse()?)); + Some(AtRulePrelude::LayerPrelude(LayerPrelude::NameList( + LayerNameList { + name_list, + span: Span::new(first.lo, last.hi, Default::default()), + }, + ))) + }; - parser.input.skip_ws(); + self.input.skip_ws(); - Ok(Some(prelude)) + res + } else { + None } - _ => { - let span = parser.input.cur_span(); + } + js_word!("media") => { + self.input.skip_ws(); - return Err(Error::new(span, ErrorKind::Ignore)); - } + let media = if !is!(self, EOF) { + let media_query_list = self.parse()?; + + Some(AtRulePrelude::MediaPrelude(media_query_list)) + } else { + None + }; + + self.input.skip_ws(); + + media } - }; - let parse_simple_block = |parser: &mut Parser| -> PResult { - let ctx = match lowercased_name { - js_word!("viewport") - | js_word!("-o-viewport") - | js_word!("-ms-viewport") - | js_word!("font-face") - | js_word!("font-palette-values") - | js_word!("stylistic") - | js_word!("historical-forms") - | js_word!("styleset") - | js_word!("character-variant") - | js_word!("swash") - | js_word!("ornaments") - | js_word!("annotation") - | js_word!("property") - | js_word!("color-profile") - | js_word!("counter-style") - | js_word!("top-left-corner") - | js_word!("top-left") - | js_word!("top-center") - | js_word!("top-right") - | js_word!("top-right-corner") - | js_word!("bottom-left-corner") - | js_word!("bottom-left") - | js_word!("bottom-center") - | js_word!("bottom-right") - | js_word!("bottom-right-corner") - | js_word!("left-top") - | js_word!("left-middle") - | js_word!("left-bottom") - | js_word!("right-top") - | js_word!("right-middle") - | js_word!("right-bottom") => Ctx { - block_contents_grammar: BlockContentsGrammar::DeclarationList, - ..parser.ctx - }, - js_word!("font-feature-values") => Ctx { - in_font_feature_values_at_rule: true, - block_contents_grammar: BlockContentsGrammar::DeclarationList, - ..parser.ctx - }, - js_word!("page") => Ctx { - in_page_at_rule: true, - block_contents_grammar: BlockContentsGrammar::DeclarationList, - ..parser.ctx - }, - js_word!("layer") => Ctx { - block_contents_grammar: BlockContentsGrammar::Stylesheet, - ..parser.ctx - }, - js_word!("media") - | js_word!("supports") - | js_word!("container") - | js_word!("document") - | js_word!("-moz-document") => match parser.ctx.block_contents_grammar { - BlockContentsGrammar::StyleBlock => Ctx { - in_container_at_rule: lowercased_name == js_word!("container"), - block_contents_grammar: BlockContentsGrammar::StyleBlock, - ..parser.ctx - }, - _ => Ctx { - in_container_at_rule: lowercased_name == js_word!("container"), - block_contents_grammar: BlockContentsGrammar::Stylesheet, - ..parser.ctx - }, - }, - js_word!("nest") => Ctx { - block_contents_grammar: BlockContentsGrammar::StyleBlock, - ..parser.ctx - }, - _ => Ctx { - block_contents_grammar: BlockContentsGrammar::NoGrammar, - ..parser.ctx - }, - }; - let block = match lowercased_name { - js_word!("keyframes") - | js_word!("-moz-keyframes") - | js_word!("-o-keyframes") - | js_word!("-webkit-keyframes") - | js_word!("-ms-keyframes") - if is!(parser, "{") => - { - let span_block = parser.input.cur_span(); - let name = parser.input.bump().unwrap(); - let mut block = SimpleBlock { - span: Default::default(), - name, - value: vec![], - }; + js_word!("namespace") => { + self.input.skip_ws(); - parser.input.skip_ws(); + let span = self.input.cur_span(); + let mut prefix = None; - loop { - if is!(parser, "}") { - break; + if is!(self, Ident) { + prefix = match cur!(self) { + tok!("ident") => Some(self.parse()?), + _ => { + unreachable!() } + }; - parser.input.skip_ws(); - - let keyframe_block: KeyframeBlock = parser.parse()?; + self.input.skip_ws(); + } - block - .value - .push(ComponentValue::KeyframeBlock(keyframe_block)); + let uri = match cur!(self) { + tok!("string") => NamespacePreludeUri::Str(self.parse()?), + tok!("url") => NamespacePreludeUri::Url(self.parse()?), + tok!("function") => NamespacePreludeUri::Url(self.parse()?), + _ => { + let span = self.input.cur_span(); - parser.input.skip_ws(); + return Err(Error::new( + span, + ErrorKind::Expected("string, url or function tokens"), + )); } + }; + + let prelude = AtRulePrelude::NamespacePrelude(NamespacePrelude { + span: span!(self, span.lo), + prefix, + uri: Box::new(uri), + }); + + self.input.skip_ws(); + + Some(prelude) + } + js_word!("nest") => { + self.input.skip_ws(); + + let prelude = AtRulePrelude::NestPrelude(self.parse()?); + + self.input.skip_ws(); + + Some(prelude) + } + js_word!("page") => { + self.input.skip_ws(); + + let prelude = if !is!(self, EOF) { + Some(AtRulePrelude::PagePrelude(self.parse()?)) + } else { + None + }; + + self.input.skip_ws(); - expect!(parser, "}"); + prelude + } + js_word!("top-left-corner") + | js_word!("top-left") + | js_word!("top-center") + | js_word!("top-right") + | js_word!("top-right-corner") + | js_word!("bottom-left-corner") + | js_word!("bottom-left") + | js_word!("bottom-center") + | js_word!("bottom-right") + | js_word!("bottom-right-corner") + | js_word!("left-top") + | js_word!("left-middle") + | js_word!("left-bottom") + | js_word!("right-top") + | js_word!("right-middle") + | js_word!("right-bottom") + if self.ctx.in_page_at_rule => + { + self.input.skip_ws(); - block.span = span!(parser, span_block.lo); + if !is!(self, EOF) { + let span = self.input.cur_span(); - block + return Err(Error::new(span, ErrorKind::Expected("'{' token"))); } - _ => parser.with_ctx(ctx).parse_as::()?, - }; - Ok(block) - }; + None + } + js_word!("property") => { + self.input.skip_ws(); - loop { - // - // This is a parse error. Return the at-rule. - if is!(self, EOF) { - at_rule.span = span!(self, at_rule_span.lo); + let prelude = AtRulePrelude::PropertyPrelude(self.parse()?); + + self.input.skip_ws(); - return Ok(at_rule); + Some(prelude) } + js_word!("supports") => { + self.input.skip_ws(); + + let prelude = AtRulePrelude::SupportsPrelude(self.parse()?); + + self.input.skip_ws(); - match cur!(self) { - // - // Return the at-rule. - tok!(";") => { - self.input.bump(); + Some(prelude) + } + js_word!("viewport") | js_word!("-ms-viewport") | js_word!("-o-viewport") => { + self.input.skip_ws(); - at_rule.span = span!(self, at_rule_span.lo); + if !is!(self, EOF) { + let span = self.input.cur_span(); - return Ok(at_rule); + return Err(Error::new(span, ErrorKind::Expected("'{' token"))); } - // <{-token> - // Consume a simple block and assign it to the at-rule’s block. Return the at-rule. - tok!("{") => { - let state = self.input.state(); - let block = match parse_simple_block(self) { - Ok(simple_block) => simple_block, - Err(err) => { - if *err.kind() != ErrorKind::Ignore { - self.errors.push(err); - } - self.input.reset(&state); + None + } + _ => { + return Err(Error::new(Default::default(), ErrorKind::Ignore)); + } + }; - let ctx = Ctx { - block_contents_grammar: BlockContentsGrammar::NoGrammar, - ..self.ctx - }; + if !is!(self, EOF) { + let span = self.input.cur_span(); - self.with_ctx(ctx).parse_as::()? - } + return Err(Error::new( + span, + ErrorKind::Unexpected("tokens in at-rule prelude"), + )); + } + + Ok(prelude) + } + + pub(super) fn parse_at_rule_block(&mut self, name: &JsWord) -> PResult> { + let block_contents = match *name { + js_word!("charset") => { + let span = self.input.cur_span(); + + return Err(Error::new(span, ErrorKind::Unexpected("'{' token"))); + } + js_word!("color-profile") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("container") => match self.ctx.block_contents_grammar { + BlockContentsGrammar::StyleBlock => { + let ctx = Ctx { + in_container_at_rule: true, + ..self.ctx }; - at_rule.block = Some(block); - at_rule.span = span!(self, at_rule_span.lo); + let style_blocks = self.with_ctx(ctx).parse_as::>()?; + let style_blocks: Vec = style_blocks + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(); - return Ok(at_rule); + style_blocks } - // anything else - // Reconsume the current input token. Consume a component value. Append the returned - // value to the at-rule’s prelude. _ => { - let state = self.input.state(); + let ctx = Ctx { + is_top_level: false, + in_container_at_rule: true, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + let rule_list: Vec = + rule_list.into_iter().map(ComponentValue::Rule).collect(); - match parse_prelude(self) { - Ok(prelude) => { - if let Some(prelude) = prelude { - at_rule.prelude = Some(prelude); - } - } - Err(err) => { - if *err.kind() != ErrorKind::Ignore { - self.errors.push(err); - } + rule_list + } + }, + js_word!("counter-style") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("custom-media") => { + let span = self.input.cur_span(); - self.input.reset(&state); + return Err(Error::new(span, ErrorKind::Unexpected("'{' token"))); + } + js_word!("document") | js_word!("-moz-document") => { + match self.ctx.block_contents_grammar { + BlockContentsGrammar::StyleBlock => { + let style_blocks: Vec = self.parse()?; + let style_blocks: Vec = style_blocks + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(); - let span = self.input.cur_span(); + style_blocks + } + _ => { + let ctx = Ctx { + is_top_level: false, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + let rule_list: Vec = + rule_list.into_iter().map(ComponentValue::Rule).collect(); + + rule_list + } + } + } + js_word!("font-face") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("font-feature-values") => { + let declaration_list = self + .with_ctx(Ctx { + in_font_feature_values_at_rule: true, + ..self.ctx + }) + .parse_as::>()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("stylistic") + | js_word!("historical-forms") + | js_word!("styleset") + | js_word!("character-variant") + | js_word!("swash") + | js_word!("ornaments") + | js_word!("annotation") + if self.ctx.in_font_feature_values_at_rule => + { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("font-palette-values") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("import") => { + let span = self.input.cur_span(); + + return Err(Error::new(span, ErrorKind::Unexpected("'{' token"))); + } + js_word!("keyframes") + | js_word!("-webkit-keyframes") + | js_word!("-moz-keyframes") + | js_word!("-o-keyframes") + | js_word!("-ms-keyframes") => { + let ctx = Ctx { + block_contents_grammar: BlockContentsGrammar::DeclarationList, + is_top_level: false, + in_keyframes_at_rule: true, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + + let rule_list: Vec = rule_list + .into_iter() + .map(|rule| match rule { + Rule::AtRule(at_rule) => { + self.errors.push(Error::new( + at_rule.span, + ErrorKind::Unexpected("at-rules are not allowed here"), + )); - let mut list_of_component_value = match at_rule.prelude.as_deref_mut() { - Some(AtRulePrelude::ListOfComponentValues( - ref mut list_of_component_value, - )) => list_of_component_value, + ComponentValue::Rule(Rule::AtRule(at_rule)) + } + Rule::QualifiedRule(qualified_rule) => { + let locv = match qualified_rule.prelude { + QualifiedRulePrelude::ListOfComponentValues(locv) => locv, _ => { - at_rule.prelude = - Some(Box::new(AtRulePrelude::ListOfComponentValues( - ListOfComponentValues { - span: span!(self, span.lo), - children: vec![], - }, - ))); - - match at_rule.prelude.as_deref_mut() { - Some(AtRulePrelude::ListOfComponentValues( - ref mut list_of_component_value, - )) => list_of_component_value, - _ => { - unreachable!(); - } - } + unreachable!(); } }; - let ctx = Ctx { - block_contents_grammar: BlockContentsGrammar::NoGrammar, - ..self.ctx - }; - let component_value = - self.with_ctx(ctx).parse_as::()?; - - list_of_component_value.children.push(component_value); - list_of_component_value.span = Span::new( - list_of_component_value.span.lo, - span.hi, - Default::default(), - ); + match self.parse_according_to_grammar(&locv, |parser| { + parser.input.skip_ws(); + + let child = parser.parse()?; + let mut keyframes_selectors: Vec = vec![child]; + + loop { + parser.input.skip_ws(); + + if !eat!(parser, ",") { + break; + } + + parser.input.skip_ws(); + + let child = parser.parse()?; + + keyframes_selectors.push(child); + } + + Ok(keyframes_selectors) + }) { + Ok(keyframes_selectors) => { + ComponentValue::KeyframeBlock(KeyframeBlock { + span: qualified_rule.span, + prelude: keyframes_selectors, + block: qualified_rule.block, + }) + } + Err(err) => { + self.errors.push(err); + + ComponentValue::Rule(Rule::ListOfComponentValues(Box::new( + locv, + ))) + } + } } - } + Rule::ListOfComponentValues(locv) => { + ComponentValue::Rule(Rule::ListOfComponentValues(locv)) + } + }) + .collect(); + + rule_list + } + js_word!("layer") => { + let ctx = Ctx { + is_top_level: false, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + let rule_list: Vec = + rule_list.into_iter().map(ComponentValue::Rule).collect(); + + rule_list + } + js_word!("media") => match self.ctx.block_contents_grammar { + BlockContentsGrammar::StyleBlock => { + let style_blocks: Vec = self.parse()?; + let style_blocks: Vec = style_blocks + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(); + + style_blocks + } + _ => { + let ctx = Ctx { + is_top_level: false, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + let rule_list: Vec = + rule_list.into_iter().map(ComponentValue::Rule).collect(); + + rule_list } + }, + js_word!("namespace") => { + let span = self.input.cur_span(); + + return Err(Error::new(span, ErrorKind::Unexpected(""))); } - } + js_word!("nest") => { + let style_blocks: Vec = self.parse()?; + let style_blocks: Vec = style_blocks + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(); + + style_blocks + } + js_word!("page") => { + let declaration_list = self + .with_ctx(Ctx { + in_page_at_rule: true, + ..self.ctx + }) + .parse_as::>()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("top-left-corner") + | js_word!("top-left") + | js_word!("top-center") + | js_word!("top-right") + | js_word!("top-right-corner") + | js_word!("bottom-left-corner") + | js_word!("bottom-left") + | js_word!("bottom-center") + | js_word!("bottom-right") + | js_word!("bottom-right-corner") + | js_word!("left-top") + | js_word!("left-middle") + | js_word!("left-bottom") + | js_word!("right-top") + | js_word!("right-middle") + | js_word!("right-bottom") + if self.ctx.in_page_at_rule => + { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("property") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + js_word!("supports") => match self.ctx.block_contents_grammar { + BlockContentsGrammar::StyleBlock => { + let style_blocks: Vec = self.parse()?; + let style_blocks: Vec = style_blocks + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(); + + style_blocks + } + _ => { + let ctx = Ctx { + is_top_level: false, + ..self.ctx + }; + let rule_list = self.with_ctx(ctx).parse_as::>()?; + let rule_list: Vec = + rule_list.into_iter().map(ComponentValue::Rule).collect(); + + rule_list + } + }, + js_word!("viewport") | js_word!("-ms-viewport") | js_word!("-o-viewport") => { + let declaration_list: Vec = self.parse()?; + let declaration_list: Vec = declaration_list + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(); + + declaration_list + } + _ => { + return Err(Error::new(Default::default(), ErrorKind::Ignore)); + } + }; + + Ok(block_contents) } } @@ -918,43 +938,46 @@ where } } -impl Parse for Parser +impl Parse for Parser where I: ParserInput, { - fn parse(&mut self) -> PResult { - let span = self.input.cur_span(); - - let mut font_family = vec![self.parse()?]; + fn parse(&mut self) -> PResult { + match cur!(self) { + tok!("ident") => { + let ident: Ident = self.parse()?; + let normalized_ident_value = ident.value.to_ascii_lowercase(); - loop { - self.input.skip_ws(); + if &*normalized_ident_value != "from" && &*normalized_ident_value != "to" { + return Err(Error::new( + ident.span, + ErrorKind::Expected("'from' or 'to' idents"), + )); + } - if !eat!(self, ",") { - break; + Ok(KeyframeSelector::Ident(ident)) } + tok!("percentage") => Ok(KeyframeSelector::Percentage(self.parse()?)), + _ => { + let span = self.input.cur_span(); - self.input.skip_ws(); - - font_family.push(self.parse()?); + return Err(Error::new( + span, + ErrorKind::Expected("ident or percentage token"), + )); + } } - - Ok(FontFeatureValuesPrelude { - span: span!(self, span.lo), - font_family, - }) } } -impl Parse for Parser +impl Parse for Parser where I: ParserInput, { - fn parse(&mut self) -> PResult { + fn parse(&mut self) -> PResult { let span = self.input.cur_span(); - let child = self.parse()?; - let mut prelude = vec![child]; + let mut font_family = vec![self.parse()?]; loop { self.input.skip_ws(); @@ -965,57 +988,16 @@ where self.input.skip_ws(); - let child = self.parse()?; - - prelude.push(child); + font_family.push(self.parse()?); } - let ctx = Ctx { - block_contents_grammar: BlockContentsGrammar::DeclarationList, - ..self.ctx - }; - let block = self.with_ctx(ctx).parse_as::()?; - - Ok(KeyframeBlock { + Ok(FontFeatureValuesPrelude { span: span!(self, span.lo), - prelude, - block, + font_family, }) } } -impl Parse for Parser -where - I: ParserInput, -{ - fn parse(&mut self) -> PResult { - match cur!(self) { - tok!("ident") => { - let ident: Ident = self.parse()?; - let normalized_ident_value = ident.value.to_ascii_lowercase(); - - if &*normalized_ident_value != "from" && &*normalized_ident_value != "to" { - return Err(Error::new( - ident.span, - ErrorKind::Expected("'from' or 'to' idents"), - )); - } - - Ok(KeyframeSelector::Ident(ident)) - } - tok!("percentage") => Ok(KeyframeSelector::Percentage(self.parse()?)), - _ => { - let span = self.input.cur_span(); - - return Err(Error::new( - span, - ErrorKind::Expected("ident or percentage token"), - )); - } - } - } -} - impl Parse for Parser where I: ParserInput, diff --git a/crates/swc_css_parser/src/parser/input.rs b/crates/swc_css_parser/src/parser/input.rs index 8b8c47702dcf..15c84e1a2f16 100644 --- a/crates/swc_css_parser/src/parser/input.rs +++ b/crates/swc_css_parser/src/parser/input.rs @@ -124,13 +124,16 @@ where } pub(super) fn skip_ws(&mut self) { + if self.cur.is_none() { + self.bump_inner(); + } + if let Some(TokenAndSpan { token: tok!(" "), span, }) = &self.cur { self.last_pos = span.hi; - self.cur = None; { @@ -156,6 +159,7 @@ where if let Some(last_pos) = self.input.skip_ws() { self.last_pos = last_pos; } + self.cur = self.input.next(); } } diff --git a/crates/swc_css_parser/src/parser/mod.rs b/crates/swc_css_parser/src/parser/mod.rs index 5c5a44173ad8..ac22c0b4b6ae 100644 --- a/crates/swc_css_parser/src/parser/mod.rs +++ b/crates/swc_css_parser/src/parser/mod.rs @@ -70,6 +70,7 @@ struct Ctx { is_top_level: bool, block_contents_grammar: BlockContentsGrammar, + in_keyframes_at_rule: bool, in_supports_at_rule: bool, in_import_at_rule: bool, in_page_at_rule: bool, diff --git a/crates/swc_css_parser/src/parser/syntax/mod.rs b/crates/swc_css_parser/src/parser/syntax/mod.rs index 4f1af07362a2..69d95223c11e 100644 --- a/crates/swc_css_parser/src/parser/syntax/mod.rs +++ b/crates/swc_css_parser/src/parser/syntax/mod.rs @@ -1,4 +1,5 @@ -use swc_common::{Span, Spanned}; +use swc_atoms::js_word; +use swc_common::{BytePos, Span, Spanned}; use swc_css_ast::*; use super::{input::ParserInput, PResult, Parser}; @@ -14,12 +15,12 @@ where { fn parse(&mut self) -> PResult { let start = self.input.cur_span(); - let ctx = Ctx { - is_top_level: true, - ..self.ctx - }; - let rules = self.with_ctx(ctx).parse_as::>()?; - + let rules = self + .with_ctx(Ctx { + is_top_level: true, + ..self.ctx + }) + .parse_as::>()?; let last = self.input.last_pos(); Ok(Stylesheet { @@ -116,57 +117,255 @@ where } } +impl Parse for Parser +where + I: ParserInput, +{ + fn parse(&mut self) -> PResult { + // Consume the next input token. Create a new at-rule with its name set to the + // value of the current input token, its prelude initially set to an empty list, + // and its value initially set to nothing. + let at_rule_span = self.input.cur_span(); + let at_keyword_name = match bump!(self) { + Token::AtKeyword { value, raw } => (value, raw), + _ => { + 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( + at_rule_span.lo + BytePos(1), + at_rule_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( + at_rule_span.lo + BytePos(1), + at_rule_span.hi, + Default::default(), + ), + value: at_keyword_name.0, + raw: Some(at_keyword_name.1), + }), + ) + }; + let mut prelude = vec![]; + let mut at_rule = AtRule { + span: Default::default(), + name, + prelude: None, + block: None, + }; + + loop { + // + // This is a parse error. Return the at-rule. + if is!(self, EOF) { + self.errors.push(Error::new( + at_rule_span, + ErrorKind::EofButExpected("semicolon or curly block"), + )); + + at_rule.span = span!(self, at_rule_span.lo); + + return Ok(at_rule); + } + + match cur!(self) { + // + // Return the at-rule. + 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( + at_rule_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.span = span!(self, at_rule_span.lo); + + 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 + .with_ctx(Ctx { + block_contents_grammar: BlockContentsGrammar::NoGrammar, + ..self.ctx + }) + .parse_as::()?; + + 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 + } + } + }; + + 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.span = span!(self, at_rule_span.lo); + + return Ok(at_rule); + } + // anything else + // Reconsume the current input token. Consume a component value. Append the returned + // value to the at-rule’s prelude. + _ => { + let component_value = self + .with_ctx(Ctx { + block_contents_grammar: BlockContentsGrammar::NoGrammar, + ..self.ctx + }) + .parse_as::()?; + + prelude.push(component_value); + } + } + } + } +} + impl Parse for Parser where I: ParserInput, { fn parse(&mut self) -> PResult { - let create_prelude = |p: &mut Parser, - list: Vec| - -> PResult { - let list_of_component_values = p.create_locv(list); - - match p.parse_according_to_grammar::(&list_of_component_values) { - Ok(selector_list) => { - if p.ctx.is_trying_legacy_nesting { - let selector_list = - p.legacy_nested_selector_list_to_modern_selector_list(selector_list)?; - - Ok(QualifiedRulePrelude::SelectorList(selector_list)) - } else { - Ok(QualifiedRulePrelude::SelectorList(selector_list)) - } - } - Err(err) => { - if p.ctx.is_trying_legacy_nesting { - match p.parse_according_to_grammar::( - &list_of_component_values, - ) { - Ok(relative_selector_list) => { + let create_prelude = + |p: &mut Parser, list: Vec| -> PResult { + let list_of_component_values = p.create_locv(list); + + if p.ctx.in_keyframes_at_rule { + Ok(QualifiedRulePrelude::ListOfComponentValues( + list_of_component_values, + )) + } else { + match p.parse_according_to_grammar::( + &list_of_component_values, + |parser| parser.parse(), + ) { + Ok(selector_list) => { + if p.ctx.is_trying_legacy_nesting { let selector_list = p - .legacy_relative_selector_list_to_modern_selector_list( - relative_selector_list, + .legacy_nested_selector_list_to_modern_selector_list( + selector_list, )?; + Ok(QualifiedRulePrelude::SelectorList(selector_list)) + } else { Ok(QualifiedRulePrelude::SelectorList(selector_list)) } - _ => Err(err), } - } else { - p.errors.push(err); - - let list_of_component_values = p - .parse_according_to_grammar::( - &list_of_component_values, - )?; + Err(err) => { + if p.ctx.is_trying_legacy_nesting { + match p.parse_according_to_grammar::( + &list_of_component_values, + |parser| parser.parse(), + ) { + Ok(relative_selector_list) => { + let selector_list = p + .legacy_relative_selector_list_to_modern_selector_list( + relative_selector_list, + )?; + + Ok(QualifiedRulePrelude::SelectorList(selector_list)) + } + _ => Err(err), + } + } else { + p.errors.push(err); - Ok(QualifiedRulePrelude::ListOfComponentValues( - list_of_component_values, - )) + 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, @@ -195,13 +394,22 @@ where }) .parse_as::()?; - block.value = self - .parse_according_to_grammar::>( - &self.create_locv(block.value), - )? - .into_iter() - .map(ComponentValue::StyleBlock) - .collect(); + block.value = match self.ctx.block_contents_grammar { + BlockContentsGrammar::DeclarationList => self + .parse_according_to_grammar(&self.create_locv(block.value), |parser| { + parser.parse_as::>() + })? + .into_iter() + .map(ComponentValue::DeclarationOrAtRule) + .collect(), + _ => self + .parse_according_to_grammar(&self.create_locv(block.value), |parser| { + parser.parse_as::>() + })? + .into_iter() + .map(ComponentValue::StyleBlock) + .collect(), + }; return Ok(QualifiedRule { span: span!(self, span.lo), @@ -255,7 +463,6 @@ where 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() { @@ -273,13 +480,14 @@ where // Reconsume the current input token. Consume an at-rule, and append the result to // rules. tok!("@") => { - rules.push(StyleBlock::AtRule(Box::new( - self.with_ctx(Ctx { + let at_rule = self + .with_ctx(Ctx { block_contents_grammar: BlockContentsGrammar::StyleBlock, ..self.ctx }) - .parse_as::()?, - ))); + .parse_as::()?; + + rules.push(StyleBlock::AtRule(Box::new(at_rule))); } // // Initialize a temporary list initially filled with the current input token. As @@ -289,24 +497,11 @@ where // it to decls. tok!("ident") => { if self.config.legacy_nesting { - let state = self.input.state(); - let legacy_nested = self - .with_ctx(Ctx { - is_trying_legacy_nesting: true, - ..self.ctx - }) - .parse_as::(); - - match legacy_nested { - Ok(legacy_nested) => { - rules.push(StyleBlock::QualifiedRule(Box::new(legacy_nested))); + if let Some(legacy_nested) = self.try_to_parse_legacy_nesting() { + rules.push(StyleBlock::QualifiedRule(Box::new(legacy_nested))); - continue; - } - _ => { - self.input.reset(&state); - } - }; + continue; + } } let span = self.input.cur_span(); @@ -326,21 +521,22 @@ where temporary_list.children.push(component_value); } - let decl_or_list_of_component_values = - match self.parse_according_to_grammar::(&temporary_list) { - Ok(decl) => StyleBlock::Declaration(Box::new(decl)), - Err(err) => { - self.errors.push(err); + let decl_or_list_of_component_values = match self + .parse_according_to_grammar::(&temporary_list, |parser| { + parser.parse_as() + }) { + Ok(decl) => StyleBlock::Declaration(Box::new(decl)), + Err(err) => { + self.errors.push(err); - temporary_list.span = span!(self, span.lo); + temporary_list.span = span!(self, span.lo); - StyleBlock::ListOfComponentValues(temporary_list) - } - }; + StyleBlock::ListOfComponentValues(temporary_list) + } + }; declarations.push(decl_or_list_of_component_values); } - // with a value of "&" (U+0026 AMPERSAND) // Reconsume the current input token. Consume a qualified rule. If anything was // returned, append it to rules. @@ -380,34 +576,17 @@ where rules.push(qualified_rule); } - // TODO refactor me - tok!("}") => { - break; - } - // anything else // This is a parse error. Reconsume the current input token. As long as the next // input token is anything other than a or , consume a // component value and throw away the returned value. _ => { 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::(); - - match legacy_nested { - Ok(legacy_nested) => { - rules.push(StyleBlock::QualifiedRule(Box::new(legacy_nested))); + if let Some(legacy_nested) = self.try_to_parse_legacy_nesting() { + rules.push(StyleBlock::QualifiedRule(Box::new(legacy_nested))); - continue; - } - _ => { - self.input.reset(&state); - } - }; + continue; + } } let span = self.input.cur_span(); @@ -415,357 +594,123 @@ where self.errors.push(Error::new( span, ErrorKind::Expected( - "whitespace, semicolon, EOF, at-keyword or ident token", + "whitespace, semicolon, EOF, at-keyword, '&' or ident token", ), )); - let mut children = vec![]; + // For recovery mode + let mut list_of_component_values = ListOfComponentValues { + span: Default::default(), + children: vec![], + }; - // TODO fix me - while !is_one_of!(self, EOF, "}") { - if let Some(token_and_span) = self.input.bump() { - children.push(ComponentValue::PreservedToken(token_and_span)); - } + while !is_one_of!(self, ";", EOF) { + let ctx = Ctx { + block_contents_grammar: BlockContentsGrammar::NoGrammar, + ..self.ctx + }; - if is!(self, ";") { - 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::()?; - break; - } + list_of_component_values.children.push(component_value); } - declarations.push(StyleBlock::ListOfComponentValues(ListOfComponentValues { - span: span!(self, span.lo), - children, - })); + list_of_component_values.span = span!(self, span.lo); + + declarations.push(StyleBlock::ListOfComponentValues(list_of_component_values)); } } } - - declarations.extend(rules); - - Ok(declarations) } } -impl Parse for Parser +impl Parse> for Parser where I: ParserInput, { - fn parse(&mut self) -> PResult { - let span = self.input.cur_span(); - let name = match cur!(self) { - tok!("{") | tok!("(") | tok!("[") => self.input.bump().unwrap(), - _ => { - return Err(Error::new( - span, - ErrorKind::Expected("'{', '(' or '[' token"), - )); - } - }; - // Create a simple block with its associated token set to the current input - // token and with its value initially set to an empty list. - let mut simple_block = SimpleBlock { - span: Default::default(), - name, - value: vec![], - }; - - // TODO refactor me - if self.ctx.block_contents_grammar != BlockContentsGrammar::NoGrammar { - self.input.skip_ws(); - } + fn parse(&mut self) -> PResult> { + // Create an initially empty list of declarations. + let mut declarations = vec![]; - // Repeatedly consume the next input token and process it as follows: + // Repeatedly consume the next input token: loop { // - // This is a parse error. Return the block. + // Return the list of declarations. if is!(self, EOF) { - let span = self.input.cur_span(); - - self.errors.push(Error::new(span, ErrorKind::Eof)); - - break; + return Ok(declarations); } match cur!(self) { - // ending token - // Return the block. - tok!("]") if simple_block.name.token == Token::LBracket => { - bump!(self); - - break; + // + // Do nothing. + tok!(" ") => { + self.input.skip_ws(); } - tok!(")") if simple_block.name.token == Token::LParen => { - bump!(self); + // + // Do nothing. + tok!(";") => { + let token_and_span = self.input.bump().unwrap(); - break; + // For recovery mode + if let Some(DeclarationOrAtRule::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)); + } } - tok!("}") if simple_block.name.token == Token::LBrace => { - bump!(self); - - break; + // + // Reconsume the current input token. Consume an at-rule. Append the returned rule + // to the list of declarations. + tok!("@") => { + declarations.push(DeclarationOrAtRule::AtRule(self.parse()?)); } - // anything else - // Reconsume the current input token. Consume a component value and append it to the - // value of the block. - _ => match self.ctx.block_contents_grammar { - BlockContentsGrammar::NoGrammar => { - let component_value = self.parse()?; - - simple_block.value.push(component_value); - } - BlockContentsGrammar::StyleBlock => { - let style_blocks: Vec = self.parse()?; - let style_blocks: Vec = style_blocks - .into_iter() - .map(ComponentValue::StyleBlock) - .collect(); + // + // Initialize a temporary list initially filled with the current input token. As + // long as the next input token is anything other than a or + // , consume a component value and append it to the temporary list. + // Consume a declaration from the temporary list. If anything was returned, append + // it to the list of declarations. + tok!("ident") => { + let span = self.input.cur_span(); + let mut temporary_list = ListOfComponentValues { + span: Default::default(), + children: vec![], + }; - simple_block.value.extend(style_blocks); - } - // TODO improve grammar validation - BlockContentsGrammar::RuleList | BlockContentsGrammar::Stylesheet => { + while !is_one_of!(self, ";", EOF) { let ctx = Ctx { - is_top_level: false, + block_contents_grammar: BlockContentsGrammar::NoGrammar, ..self.ctx }; - let rule_list = self.with_ctx(ctx).parse_as::>()?; - let rule_list: Vec = - rule_list.into_iter().map(ComponentValue::Rule).collect(); - simple_block.value.extend(rule_list); - } - BlockContentsGrammar::DeclarationList => { - let declaration_list: Vec = self.parse()?; - let declaration_list: Vec = declaration_list - .into_iter() - .map(ComponentValue::DeclarationOrAtRule) - .collect(); + let component_value = self.with_ctx(ctx).parse_as::()?; - simple_block.value.extend(declaration_list); + temporary_list.children.push(component_value); } - BlockContentsGrammar::DeclarationValue => { - let state = self.input.state(); - let parsed = self.parse(); - let value = match parsed { - Ok(value) => { - self.input.skip_ws(); - value - } - Err(err) => { - self.errors.push(err); - self.input.reset(&state); - - let ctx = Ctx { - block_contents_grammar: BlockContentsGrammar::NoGrammar, - ..self.ctx - }; - - self.with_ctx(ctx).parse_as::()? - } - }; - - simple_block.value.push(value); - } - }, - } - } - - simple_block.span = span!(self, span.lo); - - Ok(simple_block) - } -} - -impl Parse for Parser -where - I: ParserInput, -{ - fn parse(&mut self) -> PResult { - match self.ctx.block_contents_grammar { - BlockContentsGrammar::NoGrammar => { - // Consume the next input token. - match cur!(self) { - // If the current input token is a <{-token>, <[-token>, or <(-token>, consume a - // simple block and return it. - tok!("[") | tok!("(") | tok!("{") => { - let block = self.parse()?; - - Ok(ComponentValue::SimpleBlock(block)) - } - // Otherwise, if the current input token is a , consume a - // function and return it. - tok!("function") => Ok(ComponentValue::Function(self.parse()?)), - // Otherwise, return the current input token. - _ => { - let token = self.input.bump(); - - match token { - Some(t) => Ok(ComponentValue::PreservedToken(t)), - _ => { - unreachable!(); - } - } - } - } - } - _ => { - // TODO refactor me - self.input.skip_ws(); - - let span = self.input.cur_span(); - - match cur!(self) { - tok!(",") | tok!("/") | tok!(";") => { - return Ok(ComponentValue::Delimiter(self.parse()?)); - } - - tok!("string") => { - return Ok(ComponentValue::Str(self.parse()?)); - } - - tok!("url") => { - return Ok(ComponentValue::Url(self.parse()?)); - } - - Token::Function { value, .. } => match &*value.to_ascii_lowercase() { - "url" | "src" => { - return Ok(ComponentValue::Url(self.parse()?)); - } - "rgb" | "rgba" | "hsl" | "hsla" | "hwb" | "lab" | "lch" | "oklab" - | "oklch" | "color" | "device-cmyk" | "color-mix" | "color-contrast" => { - return Ok(ComponentValue::Color(self.parse()?)); - } - _ => { - return Ok(ComponentValue::Function(self.parse()?)); - } - }, - - tok!("percentage") => { - return Ok(ComponentValue::Percentage(self.parse()?)); - } - - tok!("dimension") => return Ok(ComponentValue::Dimension(self.parse()?)), - - Token::Number { type_flag, .. } => { - if *type_flag == NumberType::Integer { - return Ok(ComponentValue::Integer(self.parse()?)); - } - - return Ok(ComponentValue::Number(self.parse()?)); - } - - Token::Ident { value, .. } => { - if value.starts_with("--") { - return Ok(ComponentValue::DashedIdent(self.parse()?)); - } else if &*value.to_ascii_lowercase() == "u" - && peeked_is_one_of!(self, "+", "number", "dimension") - { - return Ok(ComponentValue::UnicodeRange(self.parse()?)); - } - - return Ok(ComponentValue::Ident(self.parse()?)); - } - - tok!("[") | tok!("(") | tok!("{") => { - let ctx = Ctx { - block_contents_grammar: BlockContentsGrammar::DeclarationValue, - ..self.ctx - }; - let block = self.with_ctx(ctx).parse_as::()?; - - return Ok(ComponentValue::SimpleBlock(block)); - } - - tok!("#") => { - return Ok(ComponentValue::Color(self.parse()?)); - } - - _ => {} - } - - Err(Error::new(span, ErrorKind::Expected("Declaration value"))) - } - } - } -} - -impl Parse> for Parser -where - I: ParserInput, -{ - fn parse(&mut self) -> PResult> { - // Create an initially empty list of declarations. - let mut declarations = vec![]; - - // Repeatedly consume the next input token: - loop { - // TODO: remove `}` - if is_one_of!(self, EOF, "}") { - return Ok(declarations); - } - - match cur!(self) { - // - // Do nothing. - tok!(" ") => { - self.input.skip_ws(); - } - // - // Do nothing. - tok!(";") => { - bump!(self); - } - // - // Reconsume the current input token. Consume an at-rule. Append the returned rule - // to the list of declarations. - tok!("@") => { - declarations.push(DeclarationOrAtRule::AtRule(self.parse()?)); - } - // - // Initialize a temporary list initially filled with the current input token. As - // long as the next input token is anything other than a or - // , consume a component value and append it to the temporary list. - // Consume a declaration from the temporary list. If anything was returned, append - // it to the list of declarations. - tok!("ident") => { - let state = self.input.state(); - let span = self.input.cur_span(); - let prop = match self.parse() { - Ok(v) => DeclarationOrAtRule::Declaration(v), + let decl_or_list_of_component_values = match self + .parse_according_to_grammar::(&temporary_list, |parser| { + parser.parse_as() + }) { + Ok(decl) => DeclarationOrAtRule::Declaration(Box::new(decl)), Err(err) => { self.errors.push(err); - self.input.reset(&state); - let mut children = vec![]; + temporary_list.span = span!(self, span.lo); - while !is_one_of!(self, EOF, "}") { - if let Some(token_and_span) = self.input.bump() { - children.push(ComponentValue::PreservedToken(token_and_span)); - } - - if is!(self, ";") { - if let Some(token_and_span) = self.input.bump() { - children - .push(ComponentValue::PreservedToken(token_and_span)); - } - - break; - } - } - - DeclarationOrAtRule::ListOfComponentValues(ListOfComponentValues { - span: span!(self, span.lo), - children, - }) + DeclarationOrAtRule::ListOfComponentValues(temporary_list) } }; - declarations.push(prop); + declarations.push(decl_or_list_of_component_values); } // anything else // This is a parse error. Reconsume the current input token. As long as the next @@ -784,27 +729,27 @@ where ), )); - let mut children = vec![]; + // For recovery mode + let mut list_of_component_values = ListOfComponentValues { + span: Default::default(), + children: vec![], + }; - while !is_one_of!(self, EOF, "}") { - if let Some(token_and_span) = self.input.bump() { - children.push(ComponentValue::PreservedToken(token_and_span)); - } + while !is_one_of!(self, ";", EOF) { + let ctx = Ctx { + block_contents_grammar: BlockContentsGrammar::NoGrammar, + ..self.ctx + }; - if is!(self, ";") { - 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::()?; - break; - } + list_of_component_values.children.push(component_value); } + list_of_component_values.span = span!(self, span.lo); + declarations.push(DeclarationOrAtRule::ListOfComponentValues( - ListOfComponentValues { - span: span!(self, span.lo), - children, - }, + list_of_component_values, )); } } @@ -968,6 +913,217 @@ where } } +impl Parse for Parser +where + I: ParserInput, +{ + fn parse(&mut self) -> PResult { + match self.ctx.block_contents_grammar { + BlockContentsGrammar::NoGrammar => { + // Consume the next input token. + match cur!(self) { + // If the current input token is a <{-token>, <[-token>, or <(-token>, consume a + // simple block and return it. + tok!("[") | tok!("(") | tok!("{") => { + let block = self.parse()?; + + Ok(ComponentValue::SimpleBlock(block)) + } + // Otherwise, if the current input token is a , consume a + // function and return it. + tok!("function") => Ok(ComponentValue::Function(self.parse()?)), + // Otherwise, return the current input token. + _ => { + let token = self.input.bump(); + + match token { + Some(t) => Ok(ComponentValue::PreservedToken(t)), + _ => { + unreachable!(); + } + } + } + } + } + _ => { + // TODO refactor me + self.input.skip_ws(); + + let span = self.input.cur_span(); + + match cur!(self) { + tok!(",") | tok!("/") | tok!(";") => { + return Ok(ComponentValue::Delimiter(self.parse()?)); + } + + tok!("string") => { + return Ok(ComponentValue::Str(self.parse()?)); + } + + tok!("url") => { + return Ok(ComponentValue::Url(self.parse()?)); + } + + Token::Function { value, .. } => match &*value.to_ascii_lowercase() { + "url" | "src" => { + return Ok(ComponentValue::Url(self.parse()?)); + } + "rgb" | "rgba" | "hsl" | "hsla" | "hwb" | "lab" | "lch" | "oklab" + | "oklch" | "color" | "device-cmyk" | "color-mix" | "color-contrast" => { + return Ok(ComponentValue::Color(self.parse()?)); + } + _ => { + return Ok(ComponentValue::Function(self.parse()?)); + } + }, + + tok!("percentage") => { + return Ok(ComponentValue::Percentage(self.parse()?)); + } + + tok!("dimension") => return Ok(ComponentValue::Dimension(self.parse()?)), + + Token::Number { type_flag, .. } => { + if *type_flag == NumberType::Integer { + return Ok(ComponentValue::Integer(self.parse()?)); + } + + return Ok(ComponentValue::Number(self.parse()?)); + } + + Token::Ident { value, .. } => { + if value.starts_with("--") { + return Ok(ComponentValue::DashedIdent(self.parse()?)); + } else if &*value.to_ascii_lowercase() == "u" + && peeked_is_one_of!(self, "+", "number", "dimension") + { + return Ok(ComponentValue::UnicodeRange(self.parse()?)); + } + + return Ok(ComponentValue::Ident(self.parse()?)); + } + + tok!("[") | tok!("(") | tok!("{") => { + let ctx = Ctx { + block_contents_grammar: BlockContentsGrammar::NoGrammar, + ..self.ctx + }; + let mut block = self.with_ctx(ctx).parse_as::()?; + let locv = self.create_locv(block.value); + + block.value = match self.parse_according_to_grammar(&locv, |parser| { + let mut values = vec![]; + + loop { + parser.input.skip_ws(); + + if is!(parser, EOF) { + break; + } + + let component_value = parser.parse()?; + + values.push(component_value); + } + + Ok(values) + }) { + Ok(values) => values, + Err(err) => { + if *err.kind() != ErrorKind::Ignore { + self.errors.push(err); + } + + locv.children + } + }; + + return Ok(ComponentValue::SimpleBlock(block)); + } + + tok!("#") => { + return Ok(ComponentValue::Color(self.parse()?)); + } + + _ => {} + } + + Err(Error::new(span, ErrorKind::Expected("Declaration value"))) + } + } + } +} + +impl Parse for Parser +where + I: ParserInput, +{ + fn parse(&mut self) -> PResult { + let span = self.input.cur_span(); + let name = match cur!(self) { + tok!("{") | tok!("(") | tok!("[") => self.input.bump().unwrap(), + _ => { + return Err(Error::new( + span, + ErrorKind::Expected("'{', '(' or '[' token"), + )); + } + }; + // Create a simple block with its associated token set to the current input + // token and with its value initially set to an empty list. + let mut simple_block = SimpleBlock { + span: Default::default(), + name, + value: vec![], + }; + + // Repeatedly consume the next input token and process it as follows: + loop { + // + // This is a parse error. Return the block. + if is!(self, EOF) { + let span = self.input.cur_span(); + + self.errors.push(Error::new(span, ErrorKind::Eof)); + + break; + } + + match cur!(self) { + // ending token + // Return the block. + tok!("]") if simple_block.name.token == Token::LBracket => { + bump!(self); + + break; + } + tok!(")") if simple_block.name.token == Token::LParen => { + bump!(self); + + break; + } + tok!("}") if simple_block.name.token == Token::LBrace => { + bump!(self); + + break; + } + // anything else + // Reconsume the current input token. Consume a component value and append it to the + // value of the block. + _ => { + let component_value = self.parse()?; + + simple_block.value.push(component_value); + } + } + } + + simple_block.span = span!(self, span.lo); + + Ok(simple_block) + } +} + impl Parse for Parser where I: ParserInput, diff --git a/crates/swc_css_parser/src/parser/util.rs b/crates/swc_css_parser/src/parser/util.rs index 2dc672c8f2f6..804917ed5aa9 100644 --- a/crates/swc_css_parser/src/parser/util.rs +++ b/crates/swc_css_parser/src/parser/util.rs @@ -57,22 +57,38 @@ where ListOfComponentValues { span, children } } - pub(super) fn parse_according_to_grammar<'a, T>( + pub(super) fn parse_according_to_grammar( &mut self, - list_of_component_values: &'a ListOfComponentValues, - ) -> PResult - where - Parser>: Parse, - { + list_of_component_values: &ListOfComponentValues, + op: impl FnOnce(&mut Parser) -> PResult, + ) -> PResult { let lexer = ListOfComponentValuesInput::new(list_of_component_values); let mut parser = Parser::new(lexer, self.config); - let res = parser.with_ctx(self.ctx).parse_as(); + let res = op(&mut parser.with_ctx(self.ctx)); self.errors.extend(parser.take_errors()); res } + pub(super) fn try_to_parse_legacy_nesting(&mut self) -> Option { + let state = self.input.state(); + let ctx = Ctx { + is_trying_legacy_nesting: true, + ..self.ctx + }; + let qualified_rule = self.with_ctx(ctx).parse_as::(); + + match qualified_rule { + Ok(qualified_rule) => Some(qualified_rule), + _ => { + self.input.reset(&state); + + None + } + } + } + pub(super) fn legacy_nested_selector_list_to_modern_selector_list( &mut self, mut selector_list: SelectorList, diff --git a/crates/swc_css_parser/src/parser/values_and_units/mod.rs b/crates/swc_css_parser/src/parser/values_and_units/mod.rs index 484e3267e674..fa92c1058363 100644 --- a/crates/swc_css_parser/src/parser/values_and_units/mod.rs +++ b/crates/swc_css_parser/src/parser/values_and_units/mod.rs @@ -2520,22 +2520,9 @@ where unicode_range.push_str(&number); - match cur!(self) { - tok!("?") => { - let question = match bump!(self) { - Token::Delim { value } => value, - _ => { - unreachable!(); - } - }; - - unicode_range.push(question); - - loop { - if !is!(self, "?") { - break; - } - + if !is!(self, EOF) { + match cur!(self) { + tok!("?") => { let question = match bump!(self) { Token::Delim { value } => value, _ => { @@ -2544,34 +2531,49 @@ where }; unicode_range.push(question); - } - } - tok!("dimension") => { - let dimension = match bump!(self) { - Token::Dimension { - raw_value, - raw_unit, - .. - } => (raw_value, raw_unit), - _ => { - unreachable!(); - } - }; - unicode_range.push_str(&dimension.0); - unicode_range.push_str(&dimension.1); - } - tok!("number") => { - let number = match bump!(self) { - Token::Number { raw, .. } => raw, - _ => { - unreachable!(); + loop { + if !is!(self, "?") { + break; + } + + let question = match bump!(self) { + Token::Delim { value } => value, + _ => { + unreachable!(); + } + }; + + unicode_range.push(question); } - }; + } + tok!("dimension") => { + let dimension = match bump!(self) { + Token::Dimension { + raw_value, + raw_unit, + .. + } => (raw_value, raw_unit), + _ => { + unreachable!(); + } + }; + + unicode_range.push_str(&dimension.0); + unicode_range.push_str(&dimension.1); + } + tok!("number") => { + let number = match bump!(self) { + Token::Number { raw, .. } => raw, + _ => { + unreachable!(); + } + }; - unicode_range.push_str(&number); + unicode_range.push_str(&number); + } + _ => {} } - _ => {} } } // u '?'* diff --git a/crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/span.rust-debug b/crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/span.rust-debug deleted file mode 100644 index a636e16eaf5d..000000000000 --- a/crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/span.rust-debug +++ /dev/null @@ -1,30 +0,0 @@ - - x Stylesheet - ,-[$DIR/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css:1:1] - 1 | @unknown - : ^^^^^^^^ - `---- - - x Rule - ,-[$DIR/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css:1:1] - 1 | @unknown - : ^^^^^^^^ - `---- - - x AtRule - ,-[$DIR/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css:1:1] - 1 | @unknown - : ^^^^^^^^ - `---- - - x AtRuleName - ,-[$DIR/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css:1:1] - 1 | @unknown - : ^^^^^^^ - `---- - - x Ident - ,-[$DIR/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css:1:1] - 1 | @unknown - : ^^^^^^^ - `---- diff --git a/crates/swc_css_parser/tests/fixture/only/1/input.css b/crates/swc_css_parser/tests/fixture/only/1/input.css index da42033d8678..cc6ef241ec39 100644 --- a/crates/swc_css_parser/tests/fixture/only/1/input.css +++ b/crates/swc_css_parser/tests/fixture/only/1/input.css @@ -1,4 +1,4 @@ -@media screen and(-webkit-min-device-pixel-ratio:0) { +@media screen and (-webkit-min-device-pixel-ratio:0) { .gradientWrapper { -chrome-: only(; z-index: 10;); } diff --git a/crates/swc_css_parser/tests/fixture/only/1/output.json b/crates/swc_css_parser/tests/fixture/only/1/output.json index c6aad501f196..cc0952d3be99 100644 --- a/crates/swc_css_parser/tests/fixture/only/1/output.json +++ b/crates/swc_css_parser/tests/fixture/only/1/output.json @@ -2,7 +2,7 @@ "type": "Stylesheet", "span": { "start": 1, - "end": 123, + "end": 124, "ctxt": 0 }, "rules": [ @@ -10,7 +10,7 @@ "type": "AtRule", "span": { "start": 1, - "end": 123, + "end": 124, "ctxt": 0 }, "name": { @@ -26,86 +26,74 @@ "prelude": { "type": "MediaQueryList", "span": { - "start": 15, - "end": 52, + "start": 8, + "end": 53, "ctxt": 0 }, "queries": [ { "type": "MediaQuery", "span": { - "start": 15, - "end": 52, + "start": 8, + "end": 53, "ctxt": 0 }, "modifier": null, - "mediaType": null, - "keyword": null, - "condition": { - "type": "MediaCondition", + "mediaType": { + "type": "Ident", + "span": { + "start": 8, + "end": 14, + "ctxt": 0 + }, + "value": "screen", + "raw": "screen" + }, + "keyword": { + "type": "Ident", "span": { "start": 15, - "end": 52, + "end": 18, + "ctxt": 0 + }, + "value": "and", + "raw": "and" + }, + "condition": { + "type": "MediaConditionWithoutOr", + "span": { + "start": 19, + "end": 53, "ctxt": 0 }, "conditions": [ { - "type": "Function", + "type": "MediaFeaturePlain", "span": { - "start": 15, - "end": 52, + "start": 19, + "end": 53, "ctxt": 0 }, "name": { "type": "Ident", "span": { - "start": 15, - "end": 18, + "start": 20, + "end": 50, "ctxt": 0 }, - "value": "and", - "raw": "and" + "value": "-webkit-min-device-pixel-ratio", + "raw": "-webkit-min-device-pixel-ratio" }, - "value": [ - { - "type": "PreservedToken", - "span": { - "start": 19, - "end": 49, - "ctxt": 0 - }, - "token": { - "Ident": { - "value": "-webkit-min-device-pixel-ratio", - "raw": "-webkit-min-device-pixel-ratio" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 49, - "end": 50, - "ctxt": 0 - }, - "token": "Colon" + "value": { + "type": "Number", + "span": { + "start": 51, + "end": 52, + "ctxt": 0 }, - { - "type": "PreservedToken", - "span": { - "start": 50, - "end": 51, - "ctxt": 0 - }, - "token": { - "Number": { - "value": 0.0, - "raw": "0", - "type": "integer" - } - } - } - ] + "value": 0.0, + "raw": "0" + } } ] } @@ -115,15 +103,15 @@ "block": { "type": "SimpleBlock", "span": { - "start": 53, - "end": 123, + "start": 54, + "end": 124, "ctxt": 0 }, "name": { "type": "PreservedToken", "span": { - "start": 53, - "end": 54, + "start": 54, + "end": 55, "ctxt": 0 }, "token": "LBrace" @@ -132,31 +120,31 @@ { "type": "QualifiedRule", "span": { - "start": 59, - "end": 121, + "start": 60, + "end": 122, "ctxt": 0 }, "prelude": { "type": "SelectorList", "span": { - "start": 59, - "end": 75, + "start": 60, + "end": 76, "ctxt": 0 }, "children": [ { "type": "ComplexSelector", "span": { - "start": 59, - "end": 75, + "start": 60, + "end": 76, "ctxt": 0 }, "children": [ { "type": "CompoundSelector", "span": { - "start": 59, - "end": 75, + "start": 60, + "end": 76, "ctxt": 0 }, "nestingSelector": null, @@ -165,15 +153,15 @@ { "type": "ClassSelector", "span": { - "start": 59, - "end": 75, + "start": 60, + "end": 76, "ctxt": 0 }, "text": { "type": "Ident", "span": { - "start": 60, - "end": 75, + "start": 61, + "end": 76, "ctxt": 0 }, "value": "gradientWrapper", @@ -189,15 +177,15 @@ "block": { "type": "SimpleBlock", "span": { - "start": 76, - "end": 121, + "start": 77, + "end": 122, "ctxt": 0 }, "name": { "type": "PreservedToken", "span": { - "start": 76, - "end": 77, + "start": 77, + "end": 78, "ctxt": 0 }, "token": "LBrace" @@ -206,15 +194,15 @@ { "type": "Declaration", "span": { - "start": 84, - "end": 114, + "start": 85, + "end": 115, "ctxt": 0 }, "name": { "type": "Ident", "span": { - "start": 84, - "end": 92, + "start": 85, + "end": 93, "ctxt": 0 }, "value": "-chrome-", @@ -224,15 +212,15 @@ { "type": "Function", "span": { - "start": 94, - "end": 114, + "start": 95, + "end": 115, "ctxt": 0 }, "name": { "type": "Ident", "span": { - "start": 94, - "end": 98, + "start": 95, + "end": 99, "ctxt": 0 }, "value": "only", @@ -242,8 +230,8 @@ { "type": "Delimiter", "span": { - "start": 99, - "end": 100, + "start": 100, + "end": 101, "ctxt": 0 }, "value": ";" @@ -251,8 +239,8 @@ { "type": "Ident", "span": { - "start": 101, - "end": 108, + "start": 102, + "end": 109, "ctxt": 0 }, "value": "z-index", @@ -261,8 +249,8 @@ { "type": "PreservedToken", "span": { - "start": 108, - "end": 109, + "start": 109, + "end": 110, "ctxt": 0 }, "token": "Colon" @@ -270,8 +258,8 @@ { "type": "Integer", "span": { - "start": 110, - "end": 112, + "start": 111, + "end": 113, "ctxt": 0 }, "value": 10, @@ -280,8 +268,8 @@ { "type": "Delimiter", "span": { - "start": 112, - "end": 113, + "start": 113, + "end": 114, "ctxt": 0 }, "value": ";" diff --git a/crates/swc_css_parser/tests/fixture/only/1/span.rust-debug b/crates/swc_css_parser/tests/fixture/only/1/span.rust-debug index 0d5193eab57d..9d20a2bae1a2 100644 --- a/crates/swc_css_parser/tests/fixture/only/1/span.rust-debug +++ b/crates/swc_css_parser/tests/fixture/only/1/span.rust-debug @@ -1,7 +1,7 @@ x Stylesheet ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | ,-> @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | ,-> @media screen and (-webkit-min-device-pixel-ratio:0) { 2 | | .gradientWrapper { 3 | | -chrome-: only(; z-index: 10;); 4 | | } @@ -10,7 +10,7 @@ x Rule ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | ,-> @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | ,-> @media screen and (-webkit-min-device-pixel-ratio:0) { 2 | | .gradientWrapper { 3 | | -chrome-: only(; z-index: 10;); 4 | | } @@ -19,7 +19,7 @@ x AtRule ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | ,-> @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | ,-> @media screen and (-webkit-min-device-pixel-ratio:0) { 2 | | .gradientWrapper { 3 | | -chrome-: only(; z-index: 10;); 4 | | } @@ -28,97 +28,103 @@ x AtRuleName ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { : ^^^^^ `---- x Ident ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { : ^^^^^ `---- x MediaQueryList ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- x MediaQuery ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x MediaCondition + x MediaType ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^ `---- - x MediaConditionAllType + x Ident ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^ `---- - x MediaInParens + x Ident ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^ `---- - x Function + x MediaConditionWithoutOr ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x Ident + x MediaConditionWithoutOrType ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x ComponentValue + x MediaInParens ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x Ident { value: Atom('-webkit-min-device-pixel-ratio' type=dynamic), raw: Atom('-webkit-min-device-pixel-ratio' type=dynamic) } + x MediaFeature ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x ComponentValue + x MediaFeaturePlain ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x Colon + x MediaFeatureName ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- - x ComponentValue + x Ident + ,-[$DIR/tests/fixture/only/1/input.css:1:1] + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- + + x MediaFeatureValue ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^ `---- - x Number { value: 0.0, raw: Atom('0' type=inline), type_flag: Integer } + x Number ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^ `---- x SimpleBlock ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | ,-> @media screen and(-webkit-min-device-pixel-ratio:0) { + 1 | ,-> @media screen and (-webkit-min-device-pixel-ratio:0) { 2 | | .gradientWrapper { 3 | | -chrome-: only(; z-index: 10;); 4 | | } @@ -127,8 +133,8 @@ x LBrace ,-[$DIR/tests/fixture/only/1/input.css:1:1] - 1 | @media screen and(-webkit-min-device-pixel-ratio:0) { - : ^ + 1 | @media screen and (-webkit-min-device-pixel-ratio:0) { + : ^ `---- x ComponentValue diff --git a/crates/swc_css_parser/tests/recovery/at-rule/document/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/document/output.swc-stderr index cc5935090919..673df98cff9d 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/document/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/document/output.swc-stderr @@ -10,9 +10,3 @@ 1 | @document domain(http://www.example.com/) {} : ^ `---- - - x Expected url or function - ,-[$DIR/tests/recovery/at-rule/document/input.css:1:1] - 1 | @document domain(http://www.example.com/) {} - : ^ - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.json b/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.json index 4c6d8a613c00..7b385895e5ce 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.json @@ -321,7 +321,7 @@ "type": "ListOfComponentValues", "span": { "start": 117, - "end": 121, + "end": 122, "ctxt": 0 }, "children": [ @@ -351,6 +351,19 @@ "raw": "foo" } } + }, + { + "type": "PreservedToken", + "span": { + "start": 121, + "end": 122, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, @@ -446,29 +459,7 @@ "value": "font-face", "raw": "font-face" }, - "prelude": { - "type": "ListOfComponentValues", - "span": { - "start": 153, - "end": 154, - "ctxt": 0 - }, - "children": [ - { - "type": "PreservedToken", - "span": { - "start": 153, - "end": 154, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": " " - } - } - } - ] - }, + "prelude": null, "block": null } ] diff --git a/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.swc-stderr index 4e5ee52762b0..29f8c9bce3c5 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/font-face/output.swc-stderr @@ -23,12 +23,6 @@ : ^^^ `---- - x Expected '{' token - ,-[$DIR/tests/recovery/at-rule/font-face/input.css:21:1] - 21 | @font-face ; - : ^ - `---- - x Expected whitespace, semicolon, EOF, at-keyword or ident token ,-[$DIR/tests/recovery/at-rule/font-face/input.css:10:5] 10 | 123 diff --git a/crates/swc_css_parser/tests/recovery/at-rule/font-face/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/font-face/span.rust-debug index c2af8c1fd2a2..bb0ff861b51e 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/font-face/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/font-face/span.rust-debug @@ -356,6 +356,18 @@ : ^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/font-face/input.css:17:1] + 17 | @font-face foo {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/font-face/input.css:17:1] + 17 | @font-face foo {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/font-face/input.css:17:1] 17 | @font-face foo {} @@ -439,15 +451,3 @@ 21 | @font-face ; : ^^^^^^^^^ `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/font-face/input.css:21:1] - 21 | @font-face ; - : ^ - `---- - - x WhiteSpace { value: Atom(' ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/font-face/input.css:21:1] - 21 | @font-face ; - : ^ - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/empty/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/import/empty/output.swc-stderr index 1c83135d96b6..3522dd8e55fe 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/empty/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/empty/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected string, url or function token + x Unexpected end of file ,-[$DIR/tests/recovery/at-rule/import/empty/input.css:1:1] 1 | @import ; : ^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.json b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.json index 78eee8ccf408..5747a71ac4fd 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.json @@ -24,25 +24,73 @@ "raw": "import" }, "prelude": { - "type": "ImportPrelude", + "type": "ListOfComponentValues", "span": { - "start": 9, + "start": 8, "end": 26, "ctxt": 0 }, - "href": { - "type": "String", - "span": { - "start": 9, - "end": 18, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 9, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } }, - "value": "foo.css", - "raw": "\"foo.css\"" - }, - "layerName": null, - "supports": null, - "media": null + { + "type": "PreservedToken", + "span": { + "start": 9, + "end": 18, + "ctxt": 0 + }, + "token": { + "String": { + "value": "foo.css", + "raw": "\"foo.css\"" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "Function", + "span": { + "start": 19, + "end": 26, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 19, + "end": 24, + "ctxt": 0 + }, + "value": "layer", + "raw": "layer" + }, + "value": [] + } + ] }, "block": null }, @@ -64,25 +112,88 @@ "raw": "import" }, "prelude": { - "type": "ImportPrelude", + "type": "ListOfComponentValues", "span": { - "start": 36, + "start": 35, "end": 62, "ctxt": 0 }, - "href": { - "type": "String", - "span": { - "start": 36, - "end": 45, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 35, + "end": 36, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } }, - "value": "foo.css", - "raw": "\"foo.css\"" - }, - "layerName": null, - "supports": null, - "media": null + { + "type": "PreservedToken", + "span": { + "start": 36, + "end": 45, + "ctxt": 0 + }, + "token": { + "String": { + "value": "foo.css", + "raw": "\"foo.css\"" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 45, + "end": 46, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "Function", + "span": { + "start": 46, + "end": 62, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 46, + "end": 51, + "ctxt": 0 + }, + "value": "layer", + "raw": "layer" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 52, + "end": 61, + "ctxt": 0 + }, + "token": { + "String": { + "value": "invalid", + "raw": "\"invalid\"" + } + } + } + ] + } + ] }, "block": null }, @@ -104,25 +215,124 @@ "raw": "import" }, "prelude": { - "type": "ImportPrelude", + "type": "ListOfComponentValues", "span": { - "start": 72, + "start": 71, "end": 97, "ctxt": 0 }, - "href": { - "type": "String", - "span": { - "start": 72, - "end": 81, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 71, + "end": 72, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } }, - "value": "foo.css", - "raw": "\"foo.css\"" - }, - "layerName": null, - "supports": null, - "media": null + { + "type": "PreservedToken", + "span": { + "start": 72, + "end": 81, + "ctxt": 0 + }, + "token": { + "String": { + "value": "foo.css", + "raw": "\"foo.css\"" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 81, + "end": 82, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "Function", + "span": { + "start": 82, + "end": 97, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 82, + "end": 87, + "ctxt": 0 + }, + "value": "layer", + "raw": "layer" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 88, + "end": 91, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "foo", + "raw": "foo" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 91, + "end": 92, + "ctxt": 0 + }, + "token": "Comma" + }, + { + "type": "PreservedToken", + "span": { + "start": 92, + "end": 93, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 93, + "end": 96, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "bar", + "raw": "bar" + } + } + } + ] + } + ] }, "block": null } diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.swc-stderr index 74c222e8a776..2d5514c9de83 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/output.swc-stderr @@ -2,17 +2,17 @@ x Expected layer function inside @import expected to have exactly one ident argument ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] 1 | @import "foo.css" layer(); - : ^^^^^^^ + : ^^^^^^ `---- x Expected layer function inside @import expected to have exactly one ident argument ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] 2 | @import "foo.css" layer("invalid"); - : ^^^^^^^^^^^^^^^^ + : ^^^^^^ `---- x Expected layer function inside @import expected to have exactly one ident argument ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] 3 | @import "foo.css" layer(foo, bar); - : ^^^^^^^^^^^^^^^ + : ^^^^^^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/span.rust-debug index b26845fc3067..44786da5c34f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/invalid-layer/span.rust-debug @@ -30,12 +30,60 @@ : ^^^^^^ `---- - x Str + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^^^^^^^^^ + `---- + + x String { value: Atom('foo.css' type=inline), raw: Atom('"foo.css"' type=dynamic) } ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] 1 | @import "foo.css" layer(); : ^^^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^^^^^^^ + `---- + + x Function + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^^^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:1:1] + 1 | @import "foo.css" layer(); + : ^^^^^ + `---- + x Rule ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] 2 | @import "foo.css" layer("invalid"); @@ -60,12 +108,72 @@ : ^^^^^^ `---- - x Str + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^^^^^ + `---- + + x String { value: Atom('foo.css' type=inline), raw: Atom('"foo.css"' type=dynamic) } ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] 2 | @import "foo.css" layer("invalid"); : ^^^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^^^^^^^^^^^^ + `---- + + x Function + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^^^^^^^^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^^^^^ + `---- + + x String { value: Atom('invalid' type=inline), raw: Atom('"invalid"' type=dynamic) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:2:1] + 2 | @import "foo.css" layer("invalid"); + : ^^^^^^^^^ + `---- + x Rule ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] 3 | @import "foo.css" layer(foo, bar); @@ -90,8 +198,104 @@ : ^^^^^^ `---- - x Str + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^^^^^^^ + `---- + + x String { value: Atom('foo.css' type=inline), raw: Atom('"foo.css"' type=dynamic) } ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] 3 | @import "foo.css" layer(foo, bar); : ^^^^^^^^^ `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^^^^^^^^^^^^^ + `---- + + x Function + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^^^^^^^^^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^ + `---- + + x Ident { value: Atom('foo' type=inline), raw: Atom('foo' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x Comma + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^ + `---- + + x Ident { value: Atom('bar' type=inline), raw: Atom('bar' type=inline) } + ,-[$DIR/tests/recovery/at-rule/import/invalid-layer/input.css:3:1] + 3 | @import "foo.css" layer(foo, bar); + : ^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/no-semi/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/import/no-semi/output.swc-stderr index a95bc65a930a..905d7c23e8ff 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/no-semi/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/no-semi/output.swc-stderr @@ -5,20 +5,4 @@ : ^ `---- - x Expected string, url or function token - ,-[$DIR/tests/recovery/at-rule/import/no-semi/input.css:1:1] - 1 | @import url('http://') :root {} - : ^ - `---- - - x Expected string, url or function token - ,-[$DIR/tests/recovery/at-rule/import/no-semi/input.css:1:1] - 1 | @import url('http://') :root {} - : ^^^^ - `---- - - x Expected string, url or function token - ,-[$DIR/tests/recovery/at-rule/import/no-semi/input.css:1:1] - 1 | @import url('http://') :root {} - : ^ - `---- + x Unexpected '{' token diff --git a/crates/swc_css_parser/tests/recovery/at-rule/import/no-url/output.json b/crates/swc_css_parser/tests/recovery/at-rule/import/no-url/output.json index 58401db49d1f..804ca668c152 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/import/no-url/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/import/no-url/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 8, - "end": 15, + "end": 20, "ctxt": 0 }, "children": [ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-1/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-1/output.swc-stderr index acd962ac8039..c745e1822a2f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-1/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-1/output.swc-stderr @@ -1,10 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-1/input.css:1:1] - 1 | @keyframes None {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'None' ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-1/input.css:1:1] 1 | @keyframes None {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-2/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-2/output.swc-stderr index 59038a12ed40..2b747425ba28 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-2/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-2/output.swc-stderr @@ -1,10 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-2/input.css:1:1] - 1 | @keyframes inherit {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'inherit' ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-2/input.css:1:1] 1 | @keyframes inherit {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-3/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-3/output.swc-stderr index 792d33fe0abe..4d87af6ced09 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-3/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-3/output.swc-stderr @@ -1,10 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-3/input.css:1:1] - 1 | @keyframes unset {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'unset' ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-3/input.css:1:1] 1 | @keyframes unset {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-4/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-4/output.swc-stderr index 3ed0a03bd2f6..215a18fb614d 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-4/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident-4/output.swc-stderr @@ -1,10 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-4/input.css:1:1] - 1 | @keyframes default {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'default' ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident-4/input.css:1:1] 1 | @keyframes default {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident/output.swc-stderr index acdd83fe73ae..bc8daa278a63 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/custom-ident/output.swc-stderr @@ -1,10 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident/input.css:1:1] - 1 | @keyframes initial {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'initial' ,-[$DIR/tests/recovery/at-rule/keyframes/custom-ident/input.css:1:1] 1 | @keyframes initial {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/empty-name/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/empty-name/output.swc-stderr index b4a862900236..02e016a7f899 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/empty-name/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/empty-name/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected ident or string + x Unexpected end of file ,-[$DIR/tests/recovery/at-rule/keyframes/empty-name/input.css:1:1] 1 | @keyframes {} : ^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css new file mode 100644 index 000000000000..11f7b689a019 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css @@ -0,0 +1,9 @@ +@keyframes foo { + 10 { + + } + + from { + color: red; + } +} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.json b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.json new file mode 100644 index 000000000000..b53b26cb32ca --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.json @@ -0,0 +1,165 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 74, + "ctxt": 0 + }, + "rules": [ + { + "type": "AtRule", + "span": { + "start": 1, + "end": 73, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 2, + "end": 11, + "ctxt": 0 + }, + "value": "keyframes", + "raw": "keyframes" + }, + "prelude": { + "type": "CustomIdent", + "span": { + "start": 12, + "end": 15, + "ctxt": 0 + }, + "value": "foo", + "raw": "foo" + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 16, + "end": 73, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 16, + "end": 17, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "ListOfComponentValues", + "span": { + "start": 22, + "end": 25, + "ctxt": 0 + }, + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 22, + "end": 24, + "ctxt": 0 + }, + "token": { + "Number": { + "value": 10.0, + "raw": "10", + "type": "integer" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 24, + "end": 25, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + } + ] + }, + { + "type": "KeyframeBlock", + "span": { + "start": 39, + "end": 71, + "ctxt": 0 + }, + "prelude": [ + { + "type": "Ident", + "span": { + "start": 39, + "end": 43, + "ctxt": 0 + }, + "value": "from", + "raw": "from" + } + ], + "block": { + "type": "SimpleBlock", + "span": { + "start": 44, + "end": 71, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 44, + "end": 45, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 54, + "end": 64, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 54, + "end": 59, + "ctxt": 0 + }, + "value": "color", + "raw": "color" + }, + "value": [ + { + "type": "Ident", + "span": { + "start": 61, + "end": 64, + "ctxt": 0 + }, + "value": "red", + "raw": "red" + } + ], + "important": null + } + ] + } + } + ] + } + } + ] +} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.swc-stderr new file mode 100644 index 000000000000..5a1a67da99be --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/output.swc-stderr @@ -0,0 +1,6 @@ + + x Expected ident or percentage token + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/span.rust-debug new file mode 100644 index 000000000000..96eb80058454 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/span.rust-debug @@ -0,0 +1,174 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | ,-> @keyframes foo { + 2 | | 10 { + 3 | | + 4 | | } + 5 | | + 6 | | from { + 7 | | color: red; + 8 | | } + 9 | `-> } + `---- + + x Rule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | ,-> @keyframes foo { + 2 | | 10 { + 3 | | + 4 | | } + 5 | | + 6 | | from { + 7 | | color: red; + 8 | | } + 9 | `-> } + `---- + + x AtRule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | ,-> @keyframes foo { + 2 | | 10 { + 3 | | + 4 | | } + 5 | | + 6 | | from { + 7 | | color: red; + 8 | | } + 9 | `-> } + `---- + + x AtRuleName + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | @keyframes foo { + : ^^^^^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | @keyframes foo { + : ^^^^^^^^^ + `---- + + x CustomIdent + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | @keyframes foo { + : ^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | ,-> @keyframes foo { + 2 | | 10 { + 3 | | + 4 | | } + 5 | | + 6 | | from { + 7 | | color: red; + 8 | | } + 9 | `-> } + `---- + + x LBrace + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:1:1] + 1 | @keyframes foo { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^^^ + `---- + + x Rule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^^ + `---- + + x Number { value: 10.0, raw: Atom('10' type=inline), type_flag: Integer } + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:2:5] + 2 | 10 { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:6:5] + 6 | ,-> from { + 7 | | color: red; + 8 | `-> } + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:6:5] + 6 | from { + : ^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:6:5] + 6 | ,-> from { + 7 | | color: red; + 8 | `-> } + `---- + + x LBrace + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:6:5] + 6 | from { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^^^^^^^^ + `---- + + x Declaration + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^^^^^^^^ + `---- + + x DeclarationName + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-broke-and-normal/input.css:7:9] + 7 | color: red; + : ^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/output.swc-stderr index d3f22670dff9..01d61bd0b834 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/output.swc-stderr @@ -1,34 +1,4 @@ - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:1:1] - 1 | @keyframes initial {} - : ^ - `---- - - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:2:1] - 2 | @keyframes inherit {} - : ^ - `---- - - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:3:1] - 3 | @keyframes unset {} - : ^ - `---- - - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:4:1] - 4 | @keyframes none {} - : ^ - `---- - - x Expected ident or string - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:5:1] - 5 | @keyframes iNiTiAl {} - : ^ - `---- - x The CSS-wide keywords are not valid custom ident, found 'iNiTiAl' ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-css-wide-keywords/input.css:5:1] 5 | @keyframes iNiTiAl {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/output.json b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/output.json index a95b7bb55d6c..5cb04ca78098 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/output.json @@ -51,75 +51,41 @@ }, "value": [ { - "type": "PreservedToken", - "span": { - "start": 17, - "end": 19, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n\t" - } - } - }, - { - "type": "PreservedToken", + "type": "ListOfComponentValues", "span": { "start": 19, - "end": 23, - "ctxt": 0 - }, - "token": { - "Ident": { - "value": "form", - "raw": "form" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 23, "end": 24, "ctxt": 0 }, - "token": { - "WhiteSpace": { - "value": " " - } - } - }, - { - "type": "SimpleBlock", - "span": { - "start": 24, - "end": 26, - "ctxt": 0 - }, - "name": { - "type": "PreservedToken", - "span": { - "start": 24, - "end": 25, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 19, + "end": 23, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "form", + "raw": "form" + } + } }, - "token": "LBrace" - }, - "value": [] - }, - { - "type": "PreservedToken", - "span": { - "start": 26, - "end": 27, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n" + { + "type": "PreservedToken", + "span": { + "start": 23, + "end": 24, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } - } + ] } ] } @@ -169,75 +135,41 @@ }, "value": [ { - "type": "PreservedToken", - "span": { - "start": 46, - "end": 48, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n\t" - } - } - }, - { - "type": "PreservedToken", + "type": "ListOfComponentValues", "span": { "start": 48, - "end": 50, - "ctxt": 0 - }, - "token": { - "Ident": { - "value": "ot", - "raw": "ot" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 50, "end": 51, "ctxt": 0 }, - "token": { - "WhiteSpace": { - "value": " " - } - } - }, - { - "type": "SimpleBlock", - "span": { - "start": 51, - "end": 53, - "ctxt": 0 - }, - "name": { - "type": "PreservedToken", - "span": { - "start": 51, - "end": 52, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 48, + "end": 50, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "ot", + "raw": "ot" + } + } }, - "token": "LBrace" - }, - "value": [] - }, - { - "type": "PreservedToken", - "span": { - "start": 53, - "end": 54, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n" + { + "type": "PreservedToken", + "span": { + "start": 50, + "end": 51, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } - } + ] } ] } diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/span.rust-debug index 18970b40ba25..81a1b312c975 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-keyword/span.rust-debug @@ -56,16 +56,15 @@ `---- x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:1:1] - 1 | ,-> @keyframes foo { - 2 | `-> form {} + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] + 2 | form {} + : ^^^^^ `---- - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:1:1] - 1 | ,-> @keyframes foo { - 2 | `-> form {} + x Rule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] + 2 | form {} + : ^^^^^ `---- x ComponentValue @@ -92,39 +91,6 @@ : ^ `---- - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] - 2 | form {} - : ^^ - `---- - - x SimpleBlock - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] - 2 | form {} - : ^^ - `---- - - x LBrace - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] - 2 | form {} - : ^ - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] - 2 | form {} - : ^ - 3 | } - `---- - - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:2:5] - 2 | form {} - : ^ - 3 | } - `---- - x Rule ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:5:1] 5 | ,-> @keyframes foo { @@ -171,16 +137,15 @@ `---- x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:5:1] - 5 | ,-> @keyframes foo { - 6 | `-> ot {} + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] + 6 | ot {} + : ^^^ `---- - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:5:1] - 5 | ,-> @keyframes foo { - 6 | `-> ot {} + x Rule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] + 6 | ot {} + : ^^^ `---- x ComponentValue @@ -206,36 +171,3 @@ 6 | ot {} : ^ `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] - 6 | ot {} - : ^^ - `---- - - x SimpleBlock - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] - 6 | ot {} - : ^^ - `---- - - x LBrace - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] - 6 | ot {} - : ^ - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] - 6 | ot {} - : ^ - 7 | } - `---- - - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-keyword/input.css:6:5] - 6 | ot {} - : ^ - 7 | } - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/output.json b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/output.json index 78404b075a77..8b043f74bc5d 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/output.json @@ -51,90 +51,42 @@ }, "value": [ { - "type": "PreservedToken", - "span": { - "start": 17, - "end": 19, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n\t" - } - } - }, - { - "type": "PreservedToken", + "type": "ListOfComponentValues", "span": { "start": 19, - "end": 21, - "ctxt": 0 - }, - "token": { - "Number": { - "value": 10.0, - "raw": "10", - "type": "integer" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 21, "end": 22, "ctxt": 0 }, - "token": { - "WhiteSpace": { - "value": " " - } - } - }, - { - "type": "SimpleBlock", - "span": { - "start": 22, - "end": 27, - "ctxt": 0 - }, - "name": { - "type": "PreservedToken", - "span": { - "start": 22, - "end": 23, - "ctxt": 0 + "children": [ + { + "type": "PreservedToken", + "span": { + "start": 19, + "end": 21, + "ctxt": 0 + }, + "token": { + "Number": { + "value": 10.0, + "raw": "10", + "type": "integer" + } + } }, - "token": "LBrace" - }, - "value": [ { "type": "PreservedToken", "span": { - "start": 23, - "end": 26, + "start": 21, + "end": 22, "ctxt": 0 }, "token": { "WhiteSpace": { - "value": "\n\n\t" + "value": " " } } } ] - }, - { - "type": "PreservedToken", - "span": { - "start": 27, - "end": 28, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n" - } - } } ] } diff --git a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/span.rust-debug index 8906e56be509..741a8ca841b0 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/keyframes/keyframe-number/span.rust-debug @@ -60,16 +60,15 @@ `---- x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:1:1] - 1 | ,-> @keyframes foo { - 2 | `-> 10 { + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] + 2 | 10 { + : ^^^ `---- - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:1:1] - 1 | ,-> @keyframes foo { - 2 | `-> 10 { + x Rule + ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] + 2 | 10 { + : ^^^ `---- x ComponentValue @@ -95,54 +94,3 @@ 2 | 10 { : ^ `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] - 2 | ,-> 10 { - 3 | | - 4 | `-> } - `---- - - x SimpleBlock - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] - 2 | ,-> 10 { - 3 | | - 4 | `-> } - `---- - - x LBrace - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] - 2 | 10 { - : ^ - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] - 2 | ,-> 10 { - 3 | | - 4 | `-> } - `---- - - x WhiteSpace { value: Atom(' - | - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:2:5] - 2 | ,-> 10 { - 3 | | - 4 | `-> } - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:4:5] - 4 | } - : ^ - 5 | } - `---- - - x WhiteSpace { value: Atom(' - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/keyframes/keyframe-number/input.css:4:5] - 4 | } - : ^ - 5 | } - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.json b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.json index a49102c8809e..cca1e3fa3d5f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.json @@ -24,22 +24,137 @@ "raw": "layer" }, "prelude": { - "type": "LayerName", + "type": "ListOfComponentValues", "span": { - "start": 35, - "end": 38, + "start": 7, + "end": 41, "ctxt": 0 }, - "name": [ + "children": [ { - "type": "Ident", + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 17, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "framework", + "raw": "framework" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 17, + "end": 18, + "ctxt": 0 + }, + "token": "Comma" + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 19, + "end": 27, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "override", + "raw": "override" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 27, + "end": 30, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 30, + "end": 31, + "ctxt": 0 + }, + "token": "Comma" + }, + { + "type": "PreservedToken", + "span": { + "start": 31, + "end": 35, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", "span": { "start": 35, "end": 38, "ctxt": 0 }, - "value": "foo", - "raw": "foo" + "token": { + "Ident": { + "value": "foo", + "raw": "foo" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 38, + "end": 41, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.swc-stderr index 50cfaebb4e27..bce417377dfe 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/output.swc-stderr @@ -1,18 +1,6 @@ - x Expected ';' token + x Expected only one name ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] 1 | @layer framework, override , foo { - : ^ - `---- - - x Expected '{' token - ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] - 1 | @layer framework, override , foo { - : ^ - `---- - - x Expected '{' token - ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] - 1 | @layer framework, override , foo { - : ^ + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/span.rust-debug index b4d9cd27b742..c216a144aabb 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/block/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/block/span.rust-debug @@ -38,24 +38,126 @@ : ^^^^^ `---- - x LayerPrelude + x ComponentValue ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] 1 | @layer framework, override , foo { - : ^^^ + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^^^^^^ + `---- + + x Ident { value: Atom('framework' type=dynamic), raw: Atom('framework' type=dynamic) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x Comma + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^^^^^ + `---- + + x Ident { value: Atom('override' type=static), raw: Atom('override' type=static) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ + `---- + + x Comma + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^ `---- - x LayerName + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] 1 | @layer framework, override , foo { : ^^^ `---- - x Ident + x Ident { value: Atom('foo' type=inline), raw: Atom('foo' type=inline) } ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] 1 | @layer framework, override , foo { : ^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] + 1 | @layer framework, override , foo { + : ^^^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/layer/block/input.css:1:1] 1 | ,-> @layer framework, override , foo { diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/empty/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/layer/empty/output.swc-stderr index 9a676814279d..c749e494a9ff 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/empty/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/empty/output.swc-stderr @@ -1,6 +1,6 @@ - x Expected '{' token + x Expected at least one name ,-[$DIR/tests/recovery/at-rule/layer/empty/input.css:1:1] 1 | @layer ; - : ^ + : ^^^^^^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.json b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.json index cc28c8fcd896..cb75e70ce7c2 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 19, + "end": 20, "ctxt": 0 }, "children": [ @@ -57,6 +57,19 @@ "raw": "\"framework\"" } } + }, + { + "type": "PreservedToken", + "span": { + "start": 19, + "end": 20, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.swc-stderr index ff414aa2f63f..c0c5e2f1d7cb 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected '{' token + x Unexpected tokens in at-rule prelude ,-[$DIR/tests/recovery/at-rule/layer/string-name-block/input.css:1:1] 1 | @layer "framework" { : ^^^^^^^^^^^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/span.rust-debug index a2b18a46d6f5..54ee4cb8bf4e 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-block/span.rust-debug @@ -68,6 +68,18 @@ : ^^^^^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/layer/string-name-block/input.css:1:1] + 1 | @layer "framework" { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/layer/string-name-block/input.css:1:1] + 1 | @layer "framework" { + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/layer/string-name-block/input.css:1:1] 1 | ,-> @layer "framework" { diff --git a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-statement/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-statement/output.swc-stderr index d959bc14c9c1..943ec7539f55 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-statement/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/layer/string-name-statement/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected '{' token + x Unexpected tokens in at-rule prelude ,-[$DIR/tests/recovery/at-rule/layer/string-name-statement/input.css:1:1] 1 | @layer "default"; : ^^^^^^^^^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-1/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-1/span.rust-debug index d0512dc638b1..fc181579c81e 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-1/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-1/span.rust-debug @@ -29,72 +29,300 @@ : ^^^^^ `---- - x MediaQueryList + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} - : ^^^^^^^^^^ + : ^ `---- - x MediaQuery + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} - : ^^^^^^^^^^ + : ^ `---- - x MediaCondition + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} - : ^^^^^^^^^^ + : ^^^^^^^^^^^^^^ `---- - x MediaConditionAllType + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} - : ^^^^^^^^^^ + : ^^^^^^^^^^^^^^ `---- - x MediaInParens + x LParen ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} - : ^^^^^^^^^^ + : ^ `---- - x MediaFeature + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^ + `---- + + x Ident { value: Atom('update' type=inline), raw: Atom('update' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^ + `---- + + x Ident { value: Atom('slow' type=inline), raw: Atom('slow' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^ + `---- + + x Ident { value: Atom('and' type=static), raw: Atom('and' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^^^^^^^^ + `---- + + x LParen + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^ + `---- + + x Ident { value: Atom('hover' type=inline), raw: Atom('hover' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^ + `---- + + x Ident { value: Atom('none' type=static), raw: Atom('none' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^^ + `---- + + x Ident { value: Atom('unknown' type=static), raw: Atom('unknown' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^^^^^^^^^^ `---- - x MediaFeaturePlain + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^^^^^^^^^^ `---- - x MediaFeatureName + x LParen + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^^^^^ `---- - x Ident + x Ident { value: Atom('color' type=static), raw: Atom('color' type=static) } ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^^^^^ `---- - x MediaFeatureValue + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^ `---- - x Number + x Number { value: 1.0, raw: Atom('1' type=inline), type_flag: Integer } ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} : ^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] + 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition-1/input.css:1:1] 1 | @media (update: slow) and (hover: none) unknown (color: 1) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.json index 19b048d3e7fc..d9e2a7bbcee8 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.json @@ -24,78 +24,275 @@ "raw": "media" }, "prelude": { - "type": "MediaQueryList", + "type": "ListOfComponentValues", "span": { - "start": 41, - "end": 60, + "start": 7, + "end": 61, "ctxt": 0 }, - "queries": [ + "children": [ { - "type": "MediaQuery", + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 8, + "end": 14, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "screen", + "raw": "screen" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 14, + "end": 15, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 15, + "end": 18, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "and", + "raw": "and" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 19, + "end": 37, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 19, + "end": 20, + "ctxt": 0 + }, + "token": "LParen" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 20, + "end": 29, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "min-width", + "raw": "min-width" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 29, + "end": 30, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 30, + "end": 31, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 31, + "end": 36, + "ctxt": 0 + }, + "token": { + "Dimension": { + "value": 900.0, + "raw_value": "900", + "unit": "px", + "raw_unit": "px", + "type": "integer" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 37, + "end": 38, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 38, + "end": 40, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "or", + "raw": "or" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 40, + "end": 41, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", "span": { "start": 41, "end": 60, "ctxt": 0 }, - "modifier": null, - "mediaType": null, - "keyword": null, - "condition": { - "type": "MediaCondition", + "name": { + "type": "PreservedToken", "span": { "start": 41, - "end": 60, + "end": 42, "ctxt": 0 }, - "conditions": [ - { - "type": "MediaFeaturePlain", - "span": { - "start": 41, - "end": 60, - "ctxt": 0 - }, - "name": { - "type": "Ident", - "span": { - "start": 42, - "end": 51, - "ctxt": 0 - }, + "token": "LParen" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 42, + "end": 51, + "ctxt": 0 + }, + "token": { + "Ident": { "value": "min-width", "raw": "min-width" - }, - "value": { - "type": "Length", - "span": { - "start": 53, - "end": 59, - "ctxt": 0 - }, - "value": { - "type": "Number", - "span": { - "start": 53, - "end": 57, - "ctxt": 0 - }, - "value": 1200.0, - "raw": "1200" - }, - "unit": { - "type": "Ident", - "span": { - "start": 57, - "end": 59, - "ctxt": 0 - }, - "value": "px", - "raw": "px" - } } } - ] + }, + { + "type": "PreservedToken", + "span": { + "start": 51, + "end": 52, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 52, + "end": 53, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 53, + "end": 59, + "ctxt": 0 + }, + "token": { + "Dimension": { + "value": 1200.0, + "raw_value": "1200", + "unit": "px", + "raw_unit": "px", + "type": "integer" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 60, + "end": 61, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } } } ] diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.swc-stderr index 80dafd1d719d..314b086f4399 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer') + x Unexpected tokens in at-rule prelude ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/span.rust-debug index c0419cd338f2..45d4c1a8da42 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/condition-and-or/span.rust-debug @@ -29,88 +29,244 @@ : ^^^^^ `---- - x MediaQueryList + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^^^^^^^^^^^^^^ + : ^ `---- - x MediaQuery + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^^^^^^^^^^^^^^ + : ^ `---- - x MediaCondition + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^^^^^^^^^^^^^^ + : ^^^^^^ `---- - x MediaConditionAllType + x Ident { value: Atom('screen' type=inline), raw: Atom('screen' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^^^^^^^^^^^^^^ + : ^^^^^^ `---- - x MediaInParens + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^^^^^^^^^^^^^^ + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^ + `---- + + x Ident { value: Atom('and' type=static), raw: Atom('and' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^^^^^^^^^^^^^^ + `---- + + x LParen + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^^^^^ + `---- + + x Ident { value: Atom('min-width' type=dynamic), raw: Atom('min-width' type=dynamic) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^ + `---- + + x Dimension { value: 900.0, raw_value: Atom('900' type=inline), unit: Atom('px' type=static), raw_unit: Atom('px' type=static), type_flag: Integer } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^ + `---- + + x Ident { value: Atom('or' type=static), raw: Atom('or' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^^ `---- - x MediaFeature + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^^^^^^^^^^^^^^ `---- - x MediaFeaturePlain + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^^^^^^^^^^^^^^ `---- - x MediaFeatureName + x LParen + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^^^^ `---- - x Ident + x Ident { value: Atom('min-width' type=dynamic), raw: Atom('min-width' type=dynamic) } ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^^^^ `---- - x MediaFeatureValue + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^^^ + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ `---- - x Dimension + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] + 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^ `---- - x Length + x Dimension { value: 1200.0, raw_value: Atom('1200' type=inline), unit: Atom('px' type=static), raw_unit: Atom('px' type=static), type_flag: Integer } ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} : ^^^^^^ `---- - x Number + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^^^ + : ^ `---- - x Ident + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition-and-or/input.css:1:1] 1 | @media screen and (min-width: 900px) or (min-width: 1200px) {} - : ^^ + : ^ `---- x SimpleBlock diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/condition/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/condition/span.rust-debug index 336eac629870..fc7b3a004524 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/condition/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/condition/span.rust-debug @@ -29,72 +29,198 @@ : ^^^^^ `---- - x MediaQueryList + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} - : ^^^^^^^^^^^^^ + : ^ `---- - x MediaQuery + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} - : ^^^^^^^^^^^^^ + : ^ `---- - x MediaCondition + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} - : ^^^^^^^^^^^^^ + : ^^^^^^^^^^^^^^ `---- - x MediaConditionAllType + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} - : ^^^^^^^^^^^^^ + : ^^^^^^^^^^^^^^ `---- - x MediaInParens + x LParen ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} - : ^^^^^^^^^^^^^ + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^^^ + `---- + + x Ident { value: Atom('update' type=inline), raw: Atom('update' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ `---- - x MediaFeature + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^ + `---- + + x Ident { value: Atom('slow' type=inline), raw: Atom('slow' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^^^^ + `---- + + x Ident { value: Atom('unknown' type=static), raw: Atom('unknown' type=static) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^^^^^^^^^^ `---- - x MediaFeaturePlain + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^^^^^^^^^^ `---- - x MediaFeatureName + x LParen + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^^ `---- - x Ident + x Ident { value: Atom('hover' type=inline), raw: Atom('hover' type=inline) } ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^^ `---- - x MediaFeatureValue + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^ `---- - x Ident + x Ident { value: Atom('none' type=static), raw: Atom('none' type=static) } ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} : ^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] + 1 | @media (update: slow) unknown (hover: none) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/condition/input.css:1:1] 1 | @media (update: slow) unknown (hover: none) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/output.json index 1a18ffee636f..7ecfa37e4b24 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 21, "ctxt": 0 }, "children": [ @@ -118,6 +118,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 20, + "end": 21, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/span.rust-debug index b7b7bc9ad715..41d930437efc 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-1/span.rust-debug @@ -107,6 +107,18 @@ : ^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-name-1/input.css:1:1] + 1 | @media (20px: 20px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-name-1/input.css:1:1] + 1 | @media (20px: 20px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-name-1/input.css:1:1] 1 | @media (20px: 20px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/output.json index a7d7ace544b8..0d0d71805abe 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 19, "ctxt": 0 }, "children": [ @@ -76,6 +76,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/span.rust-debug index ae50691ebabc..b58ca92e43aa 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name-2/span.rust-debug @@ -71,6 +71,18 @@ : ^^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-name-2/input.css:1:1] + 1 | @media ("string") {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-name-2/input.css:1:1] + 1 | @media ("string") {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-name-2/input.css:1:1] 1 | @media ("string") {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/output.json index e265ed875de5..f53122a49a9f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 28, "ctxt": 0 }, "children": [ @@ -115,6 +115,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 27, + "end": 28, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/span.rust-debug index be876362c721..5dedb00b376a 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-name/span.rust-debug @@ -107,6 +107,18 @@ : ^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-name/input.css:1:1] + 1 | @media ("min-width": 20px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-name/input.css:1:1] + 1 | @media ("min-width": 20px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-name/input.css:1:1] 1 | @media ("min-width": 20px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/output.json index 8332ba0ad32f..57392c3f68a7 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 34, "ctxt": 0 }, "children": [ @@ -188,6 +188,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 34, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/span.rust-debug index fe424ccc9061..c70861c16a35 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-2/span.rust-debug @@ -167,6 +167,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-range-2/input.css:1:1] + 1 | @media (400px > "width" > 700px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-range-2/input.css:1:1] + 1 | @media (400px > "width" > 700px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-range-2/input.css:1:1] 1 | @media (400px > "width" > 700px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/output.json index 5012c5af303e..d8b94af14edc 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 36, "ctxt": 0 }, "children": [ @@ -240,6 +240,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 35, + "end": 36, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/span.rust-debug index ad1c0de4caa6..c1a438bed29a 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-3/span.rust-debug @@ -215,6 +215,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-range-3/input.css:1:1] + 1 | @media (400px > = width > = 700px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-range-3/input.css:1:1] + 1 | @media (400px > = width > = 700px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-range-3/input.css:1:1] 1 | @media (400px > = width > = 700px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/output.json index 4db1a4c9d3a6..ca3cb63c644f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 33, "ctxt": 0 }, "children": [ @@ -201,6 +201,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 32, + "end": 33, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/span.rust-debug index d6ef22c57992..188bd5293d80 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-4/span.rust-debug @@ -179,6 +179,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-range-4/input.css:1:1] + 1 | @media (400px >= width ! 700px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-range-4/input.css:1:1] + 1 | @media (400px >= width ! 700px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-range-4/input.css:1:1] 1 | @media (400px >= width ! 700px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/output.json index 009b2ece2612..e836aed452ae 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 34, "ctxt": 0 }, "children": [ @@ -214,6 +214,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 34, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/span.rust-debug index 64b7e3e77c04..e05754d86174 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-5/span.rust-debug @@ -191,6 +191,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-range-5/input.css:1:1] + 1 | @media (400px <= width >= 700px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-range-5/input.css:1:1] + 1 | @media (400px <= width >= 700px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-range-5/input.css:1:1] 1 | @media (400px <= width >= 700px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/output.json index 898af0ca52b5..b30bbb9507a2 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 9, + "end": 34, "ctxt": 0 }, "children": [ @@ -214,6 +214,19 @@ } } ] + }, + { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 34, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/span.rust-debug index d2774421b67d..c55dce15d553 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature-range-6/span.rust-debug @@ -191,6 +191,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature-range-6/input.css:1:1] + 1 | @media (400px >= width <= 700px) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature-range-6/input.css:1:1] + 1 | @media (400px >= width <= 700px) {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature-range-6/input.css:1:1] 1 | @media (400px >= width <= 700px) {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.json index 1eb4b16fe34e..2517d2effd5b 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 18, + "end": 19, "ctxt": 0 }, "children": [ @@ -84,6 +84,19 @@ "raw": "and" } } + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.swc-stderr index efb1a3655452..e06c3af604de 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/output.swc-stderr @@ -1,12 +1,6 @@ - x Expected function or '(' token + x Unexpected end of file ,-[$DIR/tests/recovery/at-rule/media/feature/input.css:1:1] 1 | @media screen and {} : ^ `---- - - x Expected ident (exclude the keywords 'only', 'not', 'and', 'or' and 'layer') - ,-[$DIR/tests/recovery/at-rule/media/feature/input.css:1:1] - 1 | @media screen and {} - : ^^^ - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/span.rust-debug index b1b26def5a9d..9f81306bf4b8 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/feature/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/feature/span.rust-debug @@ -77,6 +77,18 @@ : ^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/feature/input.css:1:1] + 1 | @media screen and {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/feature/input.css:1:1] + 1 | @media screen and {} + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/feature/input.css:1:1] 1 | @media screen and {} diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.swc-stderr index b939d3ebbea3..e7e00b1d1c03 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/invalid-nesting/output.swc-stderr @@ -1,6 +1,6 @@ x Unexpected end of file - ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:3:3] - 3 | + ,-[$DIR/tests/recovery/at-rule/media/invalid-nesting/input.css:3:1] + 3 | } : ^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/output.json b/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/output.json index 853c25d3a1c8..d1ac533bfa50 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/output.json @@ -27,7 +27,7 @@ "type": "ListOfComponentValues", "span": { "start": 7, - "end": 18, + "end": 19, "ctxt": 0 }, "children": [ @@ -84,6 +84,19 @@ "raw": "layer" } } + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/span.rust-debug index a38f6ff6249d..714bbf9bc024 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/media/media-type/span.rust-debug @@ -86,6 +86,18 @@ : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/media/media-type/input.css:1:1] + 1 | @media only layer { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/media/media-type/input.css:1:1] + 1 | @media only layer { + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/media/media-type/input.css:1:1] 1 | ,-> @media only layer { diff --git a/crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css b/crates/swc_css_parser/tests/recovery/at-rule/no-end/input.css similarity index 100% rename from crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/input.css rename to crates/swc_css_parser/tests/recovery/at-rule/no-end/input.css diff --git a/crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/output.json b/crates/swc_css_parser/tests/recovery/at-rule/no-end/output.json similarity index 100% rename from crates/swc_css_parser/tests/fixture/esbuild/misc/_5pJ5Q6EBxzG4SOkB9Qoow/output.json rename to crates/swc_css_parser/tests/recovery/at-rule/no-end/output.json diff --git a/crates/swc_css_parser/tests/recovery/at-rule/no-end/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/no-end/output.swc-stderr new file mode 100644 index 000000000000..bac790c800f0 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/no-end/output.swc-stderr @@ -0,0 +1,6 @@ + + x Unexpected end of file, but expected semicolon or curly block + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/no-end/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/no-end/span.rust-debug new file mode 100644 index 000000000000..df709c988c45 --- /dev/null +++ b/crates/swc_css_parser/tests/recovery/at-rule/no-end/span.rust-debug @@ -0,0 +1,30 @@ + + x Stylesheet + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^^ + `---- + + x Rule + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^^ + `---- + + x AtRule + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^^ + `---- + + x AtRuleName + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^ + `---- + + x Ident + ,-[$DIR/tests/recovery/at-rule/no-end/input.css:1:1] + 1 | @unknown + : ^^^^^^^ + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.json b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.json index 4657f8f18b21..4add2106a92f 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.json @@ -10,7 +10,7 @@ "type": "AtRule", "span": { "start": 1, - "end": 44, + "end": 25, "ctxt": 0 }, "name": { @@ -58,7 +58,7 @@ "type": "SimpleBlock", "span": { "start": 15, - "end": 44, + "end": 25, "ctxt": 0 }, "name": { @@ -75,7 +75,7 @@ "type": "AtRule", "span": { "start": 16, - "end": 44, + "end": 24, "ctxt": 0 }, "name": { @@ -88,96 +88,31 @@ "value": "content", "raw": "content" }, - "prelude": { - "type": "ListOfComponentValues", - "span": { - "start": 24, - "end": 44, - "ctxt": 0 - }, - "children": [ - { - "type": "PreservedToken", - "span": { - "start": 24, - "end": 25, - "ctxt": 0 - }, - "token": "RBrace" - }, - { - "type": "PreservedToken", - "span": { - "start": 25, - "end": 27, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n\n" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 27, - "end": 35, - "ctxt": 0 - }, - "token": { - "AtKeyword": { - "value": "charset", - "raw": "charset" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 35, - "end": 36, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": " " - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 36, - "end": 43, - "ctxt": 0 - }, - "token": { - "String": { - "value": "UTF-8", - "raw": "\"UTF-8\"" - } - } - }, - { - "type": "PreservedToken", - "span": { - "start": 43, - "end": 44, - "ctxt": 0 - }, - "token": { - "WhiteSpace": { - "value": "\n" - } - } - } - ] - }, + "prelude": null, "block": null } ] } + }, + { + "type": "AtRule", + "span": { + "start": 27, + "end": 44, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 28, + "end": 35, + "ctxt": 0 + }, + "value": "charset", + "raw": "charset" + }, + "prelude": null, + "block": null } ] } diff --git a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.swc-stderr index b4fcd007a6df..5b3c24f80267 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/output.swc-stderr @@ -1,6 +1,12 @@ - x Unexpected end of file - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:18] - 3 | - : ^ + x Unexpected end of file, but expected semicolon or curly block + ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] + 1 | @media screen {@content} + : ^^^^^^^^ + `---- + + x Unexpected end of file, but expected semicolon or curly block + ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] + 3 | @charset "UTF-8" + : ^^^^^^^^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/span.rust-debug index e6c13ed36720..e345dccfc274 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/no-semi/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/no-semi/span.rust-debug @@ -8,16 +8,14 @@ x Rule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^^^^^^^^^^^^^^^^^ `---- x AtRule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^^^^^^^^^^^^^^^^^ `---- x AtRuleName @@ -58,9 +56,8 @@ x SimpleBlock ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^^^ `---- x LBrace @@ -71,23 +68,20 @@ x ComponentValue ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^ `---- x Rule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^ `---- x AtRule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | | - 3 | `-> @charset "UTF-8" + 1 | @media screen {@content} + : ^^^^^^^^ `---- x AtRuleName @@ -102,79 +96,26 @@ : ^^^^^^^ `---- - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | @media screen {@content} - : ^ - `---- - - x RBrace - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | @media screen {@content} - : ^ - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | `-> - 3 | @charset "UTF-8" - `---- - - x WhiteSpace { value: Atom(' - | - | ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:1:1] - 1 | ,-> @media screen {@content} - 2 | `-> - 3 | @charset "UTF-8" - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] - 3 | @charset "UTF-8" - : ^^^^^^^^ - `---- - - x AtKeyword { value: Atom('charset' type=static), raw: Atom('charset' type=static) } - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] - 3 | @charset "UTF-8" - : ^^^^^^^^ - `---- - - x ComponentValue - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] - 3 | @charset "UTF-8" - : ^ - `---- - - x WhiteSpace { value: Atom(' ' type=inline) } - ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] - 3 | @charset "UTF-8" - : ^ - `---- - - x ComponentValue + x Rule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] 3 | @charset "UTF-8" - : ^^^^^^^ + : ^^^^^^^^^^^^^^^^^ `---- - x String { value: Atom('UTF-8' type=inline), raw: Atom('"UTF-8"' type=inline) } + x AtRule ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] 3 | @charset "UTF-8" - : ^^^^^^^ + : ^^^^^^^^^^^^^^^^^ `---- - x ComponentValue + x AtRuleName ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] 3 | @charset "UTF-8" - : ^ + : ^^^^^^^ `---- - x WhiteSpace { value: Atom(' - | ' type=inline) } + x Ident ,-[$DIR/tests/recovery/at-rule/no-semi/input.css:3:1] 3 | @charset "UTF-8" - : ^ + : ^^^^^^^ `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/output.json b/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/output.json index 93e165c25aee..566395096431 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/output.json @@ -24,39 +24,61 @@ "raw": "page" }, "prelude": { - "type": "PageSelectorList", + "type": "ListOfComponentValues", "span": { - "start": 8, - "end": 15, + "start": 6, + "end": 16, "ctxt": 0 }, - "selectors": [ + "children": [ { - "type": "PageSelector", + "type": "PreservedToken", + "span": { + "start": 6, + "end": 7, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", "span": { "start": 8, "end": 15, "ctxt": 0 }, - "pageType": { - "type": "PageSelectorType", - "span": { - "start": 8, - "end": 15, - "ctxt": 0 - }, - "value": { - "type": "Ident", - "span": { - "start": 8, - "end": 15, - "ctxt": 0 - }, + "token": { + "Ident": { "value": "unknown", "raw": "unknown" } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 15, + "end": 16, + "ctxt": 0 }, - "pseudos": null + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/span.rust-debug index a920693d8d62..79b64c9b820e 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/page/invalid-pseudo/span.rust-debug @@ -32,30 +32,54 @@ : ^^^^ `---- - x PageSelectorList + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] 1 | @page :unknown { - : ^^^^^^^ + : ^ `---- - x PageSelector + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] 1 | @page :unknown { - : ^^^^^^^ + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] + 1 | @page :unknown { + : ^ `---- - x PageSelectorType + x Colon + ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] + 1 | @page :unknown { + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] 1 | @page :unknown { : ^^^^^^^ `---- - x Ident + x Ident { value: Atom('unknown' type=static), raw: Atom('unknown' type=static) } ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] 1 | @page :unknown { : ^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] + 1 | @page :unknown { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] + 1 | @page :unknown { + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/page/invalid-pseudo/input.css:1:1] 1 | ,-> @page :unknown { diff --git a/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/output.json b/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/output.json index f8fc3eafe9f6..18de731c674b 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/output.json @@ -24,39 +24,88 @@ "raw": "page" }, "prelude": { - "type": "PageSelectorList", + "type": "ListOfComponentValues", "span": { - "start": 13, - "end": 18, + "start": 6, + "end": 19, "ctxt": 0 }, - "selectors": [ + "children": [ { - "type": "PageSelector", + "type": "PreservedToken", + "span": { + "start": 6, + "end": 7, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 11, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "Page", + "raw": "Page" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 11, + "end": 12, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 12, + "end": 13, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", "span": { "start": 13, "end": 18, "ctxt": 0 }, - "pageType": { - "type": "PageSelectorType", - "span": { - "start": 13, - "end": 18, - "ctxt": 0 - }, - "value": { - "type": "Ident", - "span": { - "start": 13, - "end": 18, - "ctxt": 0 - }, + "token": { + "Ident": { "value": "blank", "raw": "blank" } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 18, + "end": 19, + "ctxt": 0 }, - "pseudos": null + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/span.rust-debug index 8cf149f859e4..fbd1b3ac1958 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/page/no-space/span.rust-debug @@ -35,30 +35,78 @@ : ^^^^ `---- - x PageSelectorList + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] 1 | @page Page: blank { - : ^^^^^ + : ^ `---- - x PageSelector + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] 1 | @page Page: blank { - : ^^^^^ + : ^ `---- - x PageSelectorType + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^^^^ + `---- + + x Ident { value: Atom('Page' type=inline), raw: Atom('Page' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] 1 | @page Page: blank { : ^^^^^ `---- - x Ident + x Ident { value: Atom('blank' type=inline), raw: Atom('blank' type=inline) } ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] 1 | @page Page: blank { : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] + 1 | @page Page: blank { + : ^ + `---- + x SimpleBlock ,-[$DIR/tests/recovery/at-rule/page/no-space/input.css:1:1] 1 | ,-> @page Page: blank { diff --git a/crates/swc_css_parser/tests/recovery/at-rule/page/without-page/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/page/without-page/span.rust-debug index 13403c5c2c00..140506ccae78 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/page/without-page/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/page/without-page/span.rust-debug @@ -61,28 +61,53 @@ : ^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:1:1] + 1 | ,-> @top-left { + 2 | `-> content: "foo"; + `---- + + x WhiteSpace { value: Atom(' + | ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:1:1] + 1 | ,-> @top-left { + 2 | `-> content: "foo"; + `---- + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] 2 | content: "foo"; - : ^^^^^^^^^^^^^^ + : ^^^^^^^ `---- - x Declaration + x Ident { value: Atom('content' type=static), raw: Atom('content' type=static) } ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] 2 | content: "foo"; - : ^^^^^^^^^^^^^^ + : ^^^^^^^ `---- - x DeclarationName + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] 2 | content: "foo"; - : ^^^^^^^ + : ^ `---- - x Ident + x Colon ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] 2 | content: "foo"; - : ^^^^^^^ + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | content: "foo"; + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | content: "foo"; + : ^ `---- x ComponentValue @@ -91,34 +116,71 @@ : ^^^^^ `---- - x Str + x String { value: Atom('foo' type=inline), raw: Atom('"foo"' type=inline) } ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] 2 | content: "foo"; : ^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | content: "foo"; + : ^ + `---- + + x Semi + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | content: "foo"; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | ,-> content: "foo"; + 3 | `-> color: blue; + `---- + + x WhiteSpace { value: Atom(' + | ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:2:5] + 2 | ,-> content: "foo"; + 3 | `-> color: blue; + `---- + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] 3 | color: blue; - : ^^^^^^^^^^^ + : ^^^^^ `---- - x Declaration + x Ident { value: Atom('color' type=static), raw: Atom('color' type=static) } ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] 3 | color: blue; - : ^^^^^^^^^^^ + : ^^^^^ `---- - x DeclarationName + x ComponentValue ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] 3 | color: blue; - : ^^^^^ + : ^ `---- - x Ident + x Colon ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] 3 | color: blue; - : ^^^^^ + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ `---- x ComponentValue @@ -127,8 +189,35 @@ : ^^^^ `---- - x Ident + x Ident { value: Atom('blue' type=inline), raw: Atom('blue' type=inline) } ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] 3 | color: blue; : ^^^^ `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ + `---- + + x Semi + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ + 4 | } + `---- + + x WhiteSpace { value: Atom(' + | ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/page/without-page/input.css:3:5] + 3 | color: blue; + : ^ + 4 | } + `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/supports/no-parens/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/supports/no-parens/output.swc-stderr index 31c3415713ee..71f3810d8967 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/supports/no-parens/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/supports/no-parens/output.swc-stderr @@ -4,21 +4,3 @@ 1 | @supports display: flex {} : ^^^^^^^ `---- - - x Expected function or '(' token - ,-[$DIR/tests/recovery/at-rule/supports/no-parens/input.css:1:1] - 1 | @supports display: flex {} - : ^ - `---- - - x Expected function or '(' token - ,-[$DIR/tests/recovery/at-rule/supports/no-parens/input.css:1:1] - 1 | @supports display: flex {} - : ^^^^ - `---- - - x Expected function or '(' token - ,-[$DIR/tests/recovery/at-rule/supports/no-parens/input.css:1:1] - 1 | @supports display: flex {} - : ^ - `---- diff --git a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.json b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.json index 2df1422f2526..a5b9b95669cf 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.json +++ b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.json @@ -24,31 +24,297 @@ "raw": "supports" }, "prelude": { - "type": "SupportsCondition", + "type": "ListOfComponentValues", "span": { - "start": 69, - "end": 95, + "start": 10, + "end": 96, "ctxt": 0 }, - "conditions": [ + "children": [ { - "type": "Declaration", + "type": "PreservedToken", "span": { - "start": 70, - "end": 94, + "start": 10, + "end": 11, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 11, + "end": 39, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 11, + "end": 12, + "ctxt": 0 + }, + "token": "LParen" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 12, + "end": 31, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "transition-property", + "raw": "transition-property" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 31, + "end": 32, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 32, + "end": 33, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 33, + "end": 38, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "color", + "raw": "color" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 39, + "end": 40, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 40, + "end": 42, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "or", + "raw": "or" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 42, + "end": 43, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 43, + "end": 64, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 43, + "end": 44, + "ctxt": 0 + }, + "token": "LParen" + }, + "value": [ + { + "type": "PreservedToken", + "span": { + "start": 44, + "end": 58, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "animation-name", + "raw": "animation-name" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 58, + "end": 59, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 59, + "end": 60, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 60, + "end": 63, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "foo", + "raw": "foo" + } + } + } + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 64, + "end": 65, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 65, + "end": 68, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "and", + "raw": "and" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 68, + "end": 69, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, + { + "type": "SimpleBlock", + "span": { + "start": 69, + "end": 95, "ctxt": 0 }, "name": { - "type": "Ident", + "type": "PreservedToken", "span": { - "start": 70, - "end": 79, + "start": 69, + "end": 70, "ctxt": 0 }, - "value": "transform", - "raw": "transform" + "token": "LParen" }, "value": [ + { + "type": "PreservedToken", + "span": { + "start": 70, + "end": 79, + "ctxt": 0 + }, + "token": { + "Ident": { + "value": "transform", + "raw": "transform" + } + } + }, + { + "type": "PreservedToken", + "span": { + "start": 79, + "end": 80, + "ctxt": 0 + }, + "token": "Colon" + }, + { + "type": "PreservedToken", + "span": { + "start": 80, + "end": 81, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } + }, { "type": "Function", "span": { @@ -68,37 +334,38 @@ }, "value": [ { - "type": "Angle", + "type": "PreservedToken", "span": { "start": 88, "end": 93, "ctxt": 0 }, - "value": { - "type": "Number", - "span": { - "start": 88, - "end": 90, - "ctxt": 0 - }, - "value": 10.0, - "raw": "10" - }, - "unit": { - "type": "Ident", - "span": { - "start": 90, - "end": 93, - "ctxt": 0 - }, - "value": "deg", - "raw": "deg" + "token": { + "Dimension": { + "value": 10.0, + "raw_value": "10", + "unit": "deg", + "raw_unit": "deg", + "type": "integer" + } } } ] } - ], - "important": null + ] + }, + { + "type": "PreservedToken", + "span": { + "start": 95, + "end": 96, + "ctxt": 0 + }, + "token": { + "WhiteSpace": { + "value": " " + } + } } ] }, diff --git a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.swc-stderr b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.swc-stderr index 4b969ee59f66..883cd79f3301 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/output.swc-stderr @@ -1,5 +1,5 @@ - x Expected function or '(' token + x Unexpected tokens in at-rule prelude ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} : ^^^ diff --git a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/span.rust-debug b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/span.rust-debug index 0c9df2bce2d3..360075ba4a0b 100644 --- a/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/span.rust-debug +++ b/crates/swc_css_parser/tests/recovery/at-rule/supports/wrong-or-and/span.rust-debug @@ -29,48 +29,276 @@ : ^^^^^^^^ `---- - x SupportsCondition + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- + + x LParen + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^ + `---- + + x Ident { value: Atom('transition-property' type=dynamic), raw: Atom('transition-property' type=dynamic) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ `---- - x SupportsConditionType + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^ + `---- + + x Ident { value: Atom('color' type=static), raw: Atom('color' type=static) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^^ `---- - x SupportsInParens + x Ident { value: Atom('or' type=static), raw: Atom('or' type=static) } ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^^ `---- - x SupportsFeature + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^ `---- - x Declaration + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^^^^^^^^^^^^^^^^^^^^ + : ^ `---- - x DeclarationName + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^ + `---- + + x LParen + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^ + `---- + + x Ident { value: Atom('animation-name' type=static), raw: Atom('animation-name' type=static) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^ + `---- + + x Ident { value: Atom('foo' type=inline), raw: Atom('foo' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^ + `---- + + x Ident { value: Atom('and' type=static), raw: Atom('and' type=static) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- + + x SimpleBlock + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- + + x LParen + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} : ^^^^^^^^^ `---- - x Ident + x Ident { value: Atom('transform' type=static), raw: Atom('transform' type=static) } ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} : ^^^^^^^^^ `---- + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x Colon + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x ComponentValue + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + + x WhiteSpace { value: Atom(' ' type=inline) } + ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] + 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} + : ^ + `---- + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} @@ -95,28 +323,22 @@ : ^^^^^ `---- - x Dimension + x Dimension { value: 10.0, raw_value: Atom('10' type=inline), unit: Atom('deg' type=static), raw_unit: Atom('deg' type=static), type_flag: Integer } ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} : ^^^^^ `---- - x Angle - ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] - 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^^^ - `---- - - x Number + x ComponentValue ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^ + : ^ `---- - x Ident + x WhiteSpace { value: Atom(' ' type=inline) } ,-[$DIR/tests/recovery/at-rule/supports/wrong-or-and/input.css:1:1] 1 | @supports (transition-property: color) or (animation-name: foo) and (transform: rotate(10deg)) {} - : ^^^ + : ^ `---- x SimpleBlock diff --git a/crates/swc_css_parser/tests/recovery/cdo-and-cdc/output.swc-stderr b/crates/swc_css_parser/tests/recovery/cdo-and-cdc/output.swc-stderr index b0a7e86a89f9..03f9e26b938e 100644 --- a/crates/swc_css_parser/tests/recovery/cdo-and-cdc/output.swc-stderr +++ b/crates/swc_css_parser/tests/recovery/cdo-and-cdc/output.swc-stderr @@ -1,17 +1,17 @@ - x Expected whitespace, semicolon, EOF, at-keyword or ident token + x Expected whitespace, semicolon, EOF, at-keyword, '&' or ident token ,-[$DIR/tests/recovery/cdo-and-cdc/input.css:5:1] 5 |