From 6f0f944d8326463be97610096c4730ddaa7e3178 Mon Sep 17 00:00:00 2001
From: daiwei <daiwei521@126.com>
Date: Sat, 5 Apr 2025 10:27:27 +0800
Subject: [PATCH 1/2] fix(compile-sfc): auto add nesting combinators for
 ::v-deep in scoped CSS

---
 .../__tests__/compileStyle.spec.ts            | 12 ++++++++++
 .../compiler-sfc/src/style/pluginScoped.ts    | 23 +++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/packages/compiler-sfc/__tests__/compileStyle.spec.ts b/packages/compiler-sfc/__tests__/compileStyle.spec.ts
index b76414364dc..ff5ca2a952d 100644
--- a/packages/compiler-sfc/__tests__/compileStyle.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileStyle.spec.ts
@@ -140,6 +140,18 @@ color: red
       }
       }"
     `)
+    expect(compileScoped(`.foo { :deep(.bar) { color: red; }}`))
+      .toMatchInlineSnapshot(`
+        ".foo {
+        &[data-v-test] .bar { color: red;
+        }}"
+      `)
+    expect(compileScoped(`.foo { & :deep(.bar) { color: red; }}`))
+      .toMatchInlineSnapshot(`
+        ".foo {
+        &[data-v-test] .bar { color: red;
+        }}"
+      `)
   })
 
   test('::v-slotted', () => {
diff --git a/packages/compiler-sfc/src/style/pluginScoped.ts b/packages/compiler-sfc/src/style/pluginScoped.ts
index d0aaddd7676..b0854a22e42 100644
--- a/packages/compiler-sfc/src/style/pluginScoped.ts
+++ b/packages/compiler-sfc/src/style/pluginScoped.ts
@@ -133,6 +133,29 @@ function rewriteSelector(
             selector.insertAfter(last, ss)
             last = ss
           })
+
+          // if css nesting is used, we need to insert a nesting combinator
+          // before the ::v-deep node
+          // .foo { ::v-deep(.bar) } -> .foo { &[xxxxxxx] .bar }
+          const isNestedRule = rule.parent && rule.parent.type === 'rule'
+          if (isNestedRule && n.parent) {
+            let hasNestingCombinator = false
+            let index = n.parent.index(n) - 1
+            while (index >= 0) {
+              const prev = n.parent.at(index)
+              if (!prev) break
+              if (prev.type === 'nesting') {
+                hasNestingCombinator = true
+                break
+              }
+              index--
+            }
+            if (!hasNestingCombinator) {
+              node = selectorParser.nesting()
+              selector.insertBefore(n, node)
+            }
+          }
+
           // insert a space combinator before if it doesn't already have one
           const prev = selector.at(selector.index(n) - 1)
           if (!prev || !isSpaceCombinator(prev)) {

From bfd11af47410359644d3528e11a4e1b38bb33fb1 Mon Sep 17 00:00:00 2001
From: daiwei <daiwei521@126.com>
Date: Sat, 5 Apr 2025 10:32:02 +0800
Subject: [PATCH 2/2] chore: update

---
 .../__tests__/compileStyle.spec.ts            |  6 ++++++
 .../compiler-sfc/src/style/pluginScoped.ts    | 21 +++++++------------
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/packages/compiler-sfc/__tests__/compileStyle.spec.ts b/packages/compiler-sfc/__tests__/compileStyle.spec.ts
index ff5ca2a952d..48e6ea8c3e9 100644
--- a/packages/compiler-sfc/__tests__/compileStyle.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileStyle.spec.ts
@@ -146,6 +146,12 @@ color: red
         &[data-v-test] .bar { color: red;
         }}"
       `)
+    expect(compileScoped(`.foo { :deep(.bar),:deep(.baz) { color: red; }}`))
+      .toMatchInlineSnapshot(`
+        ".foo {
+        &[data-v-test] .bar,&[data-v-test] .baz { color: red;
+        }}"
+      `)
     expect(compileScoped(`.foo { & :deep(.bar) { color: red; }}`))
       .toMatchInlineSnapshot(`
         ".foo {
diff --git a/packages/compiler-sfc/src/style/pluginScoped.ts b/packages/compiler-sfc/src/style/pluginScoped.ts
index b0854a22e42..0c7f700e133 100644
--- a/packages/compiler-sfc/src/style/pluginScoped.ts
+++ b/packages/compiler-sfc/src/style/pluginScoped.ts
@@ -134,23 +134,16 @@ function rewriteSelector(
             last = ss
           })
 
-          // if css nesting is used, we need to insert a nesting combinator
-          // before the ::v-deep node
+          // if css nesting is used, we need to insert a nesting selector
+          // before the ::v-deep's inner selector.
           // .foo { ::v-deep(.bar) } -> .foo { &[xxxxxxx] .bar }
           const isNestedRule = rule.parent && rule.parent.type === 'rule'
           if (isNestedRule && n.parent) {
-            let hasNestingCombinator = false
-            let index = n.parent.index(n) - 1
-            while (index >= 0) {
-              const prev = n.parent.at(index)
-              if (!prev) break
-              if (prev.type === 'nesting') {
-                hasNestingCombinator = true
-                break
-              }
-              index--
-            }
-            if (!hasNestingCombinator) {
+            const hasNestingSelector = n.parent.nodes
+              .slice(0, n.parent.index(n))
+              .some(node => node.type === 'nesting')
+
+            if (!hasNestingSelector) {
               node = selectorParser.nesting()
               selector.insertBefore(n, node)
             }