From d89b60a000e6a40a6d624ba3903743f9c80170d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sat, 23 Dec 2023 12:39:54 +0900 Subject: [PATCH] fix(css/parser): Fix parsing of `hsla(var(--foo), 1)` (#8443) **Description:** ```css .test { border-color: hsla(var(--ds-gray-200-value), 1); } ``` should be compiled as ```css .test { border-color: hsla(var(--ds-gray-200-value), 1); } ``` Previously, it was ``` .test { border-color: hsla(var(--ds-gray-200-value),); } ``` **Related issue:** - https://linear.app/vercel/issue/PACK-2175 --- .../tests/color-legacy/vercel-2175/input.css | 4 + .../color-legacy/vercel-2175/input.expect.css | 4 + .../src/parser/values_and_units/mod.rs | 6 +- .../tests/fixture/vercel-2175/input.css | 3 + .../fixture/vercel-2175/leading-comments.json | 1 + .../tests/fixture/vercel-2175/output.json | 177 ++++++++++++++ .../tests/fixture/vercel-2175/span.swc-stderr | 221 ++++++++++++++++++ .../vercel-2175/trailing-comments.json | 1 + 8 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 crates/swc_css_compat/tests/color-legacy/vercel-2175/input.css create mode 100644 crates/swc_css_compat/tests/color-legacy/vercel-2175/input.expect.css create mode 100644 crates/swc_css_parser/tests/fixture/vercel-2175/input.css create mode 100644 crates/swc_css_parser/tests/fixture/vercel-2175/leading-comments.json create mode 100644 crates/swc_css_parser/tests/fixture/vercel-2175/output.json create mode 100644 crates/swc_css_parser/tests/fixture/vercel-2175/span.swc-stderr create mode 100644 crates/swc_css_parser/tests/fixture/vercel-2175/trailing-comments.json diff --git a/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.css b/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.css new file mode 100644 index 00000000000..dee33d7f691 --- /dev/null +++ b/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.css @@ -0,0 +1,4 @@ +.test { + border-color: hsla(var(--ds-gray-200-value), 1); + --ds-gray-200: hsla(var(--ds-gray-200-value), 1); +} \ No newline at end of file diff --git a/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.expect.css b/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.expect.css new file mode 100644 index 00000000000..0537692336d --- /dev/null +++ b/crates/swc_css_compat/tests/color-legacy/vercel-2175/input.expect.css @@ -0,0 +1,4 @@ +.test { + border-color: hsla(var(--ds-gray-200-value), 1); + --ds-gray-200: hsla(var(--ds-gray-200-value), 1); +} 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 48478313c3e..f96c4c41dd7 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 @@ -726,8 +726,10 @@ where } } - if is!(self, ",") && is_legacy_syntax { - values.push(ComponentValue::Delimiter(self.parse()?)); + if (is!(self, ",") || has_variable) && is_legacy_syntax { + if is!(self, ",") { + values.push(ComponentValue::Delimiter(self.parse()?)); + } self.input.skip_ws(); diff --git a/crates/swc_css_parser/tests/fixture/vercel-2175/input.css b/crates/swc_css_parser/tests/fixture/vercel-2175/input.css new file mode 100644 index 00000000000..6599cf9ffd7 --- /dev/null +++ b/crates/swc_css_parser/tests/fixture/vercel-2175/input.css @@ -0,0 +1,3 @@ +.test { + border-color: hsla(var(--ds-gray-200-value), 1); +} \ No newline at end of file diff --git a/crates/swc_css_parser/tests/fixture/vercel-2175/leading-comments.json b/crates/swc_css_parser/tests/fixture/vercel-2175/leading-comments.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/crates/swc_css_parser/tests/fixture/vercel-2175/leading-comments.json @@ -0,0 +1 @@ +{} diff --git a/crates/swc_css_parser/tests/fixture/vercel-2175/output.json b/crates/swc_css_parser/tests/fixture/vercel-2175/output.json new file mode 100644 index 00000000000..ae5576d6ead --- /dev/null +++ b/crates/swc_css_parser/tests/fixture/vercel-2175/output.json @@ -0,0 +1,177 @@ +{ + "type": "Stylesheet", + "span": { + "start": 1, + "end": 63, + "ctxt": 0 + }, + "rules": [ + { + "type": "QualifiedRule", + "span": { + "start": 1, + "end": 63, + "ctxt": 0 + }, + "prelude": { + "type": "SelectorList", + "span": { + "start": 1, + "end": 6, + "ctxt": 0 + }, + "children": [ + { + "type": "ComplexSelector", + "span": { + "start": 1, + "end": 6, + "ctxt": 0 + }, + "children": [ + { + "type": "CompoundSelector", + "span": { + "start": 1, + "end": 6, + "ctxt": 0 + }, + "nestingSelector": null, + "typeSelector": null, + "subclassSelectors": [ + { + "type": "ClassSelector", + "span": { + "start": 1, + "end": 6, + "ctxt": 0 + }, + "text": { + "type": "Ident", + "span": { + "start": 2, + "end": 6, + "ctxt": 0 + }, + "value": "test", + "raw": "test" + } + } + ] + } + ] + } + ] + }, + "block": { + "type": "SimpleBlock", + "span": { + "start": 7, + "end": 63, + "ctxt": 0 + }, + "name": { + "type": "PreservedToken", + "span": { + "start": 7, + "end": 8, + "ctxt": 0 + }, + "token": "LBrace" + }, + "value": [ + { + "type": "Declaration", + "span": { + "start": 13, + "end": 60, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 13, + "end": 25, + "ctxt": 0 + }, + "value": "border-color", + "raw": "border-color" + }, + "value": [ + { + "type": "Function", + "span": { + "start": 27, + "end": 60, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 27, + "end": 31, + "ctxt": 0 + }, + "value": "hsla", + "raw": "hsla" + }, + "value": [ + { + "type": "Function", + "span": { + "start": 32, + "end": 56, + "ctxt": 0 + }, + "name": { + "type": "Ident", + "span": { + "start": 32, + "end": 35, + "ctxt": 0 + }, + "value": "var", + "raw": "var" + }, + "value": [ + { + "type": "DashedIdent", + "span": { + "start": 36, + "end": 55, + "ctxt": 0 + }, + "value": "ds-gray-200-value", + "raw": "--ds-gray-200-value" + } + ] + }, + { + "type": "Delimiter", + "span": { + "start": 56, + "end": 57, + "ctxt": 0 + }, + "value": "," + }, + { + "type": "Number", + "span": { + "start": 58, + "end": 59, + "ctxt": 0 + }, + "value": 1.0, + "raw": "1" + } + ] + } + ], + "important": null + } + ] + } + } + ] +} diff --git a/crates/swc_css_parser/tests/fixture/vercel-2175/span.swc-stderr b/crates/swc_css_parser/tests/fixture/vercel-2175/span.swc-stderr new file mode 100644 index 00000000000..f457b0ddb83 --- /dev/null +++ b/crates/swc_css_parser/tests/fixture/vercel-2175/span.swc-stderr @@ -0,0 +1,221 @@ + + x Stylesheet + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | ,-> .test { + 2 | | border-color: hsla(var(--ds-gray-200-value), 1); + 3 | `-> } + `---- + + x Rule + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | ,-> .test { + 2 | | border-color: hsla(var(--ds-gray-200-value), 1); + 3 | `-> } + `---- + + x QualifiedRule + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | ,-> .test { + 2 | | border-color: hsla(var(--ds-gray-200-value), 1); + 3 | `-> } + `---- + + x SelectorList + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x ComplexSelector + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x CompoundSelector + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x SubclassSelector + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x ClassSelector + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x Ident + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^^^^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x SimpleBlock + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | ,-> .test { + 2 | | border-color: hsla(var(--ds-gray-200-value), 1); + 3 | `-> } + `---- + + x LBrace + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + : ^ + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Declaration + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x DeclarationName + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^ + 3 | } + `---- + + x Ident + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^ + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Color + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Function + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Ident + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^ + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Function + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x Ident + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^ + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x DashedIdent + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^^^^^^^^^^^^^^^^^^^ + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^ + 3 | } + `---- + + x Delimiter + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^ + 3 | } + `---- + + x ComponentValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^ + 3 | } + `---- + + x AlphaValue + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^ + 3 | } + `---- + + x Number + ,-[$DIR/tests/fixture/vercel-2175/input.css:1:1] + 1 | .test { + 2 | border-color: hsla(var(--ds-gray-200-value), 1); + : ^ + 3 | } + `---- diff --git a/crates/swc_css_parser/tests/fixture/vercel-2175/trailing-comments.json b/crates/swc_css_parser/tests/fixture/vercel-2175/trailing-comments.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/crates/swc_css_parser/tests/fixture/vercel-2175/trailing-comments.json @@ -0,0 +1 @@ +{}