]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): avoid rendering transition-group slot content as a fragment (#9961)
authoredison <daiwei521@126.com>
Wed, 3 Jan 2024 09:43:08 +0000 (17:43 +0800)
committerGitHub <noreply@github.com>
Wed, 3 Jan 2024 09:43:08 +0000 (17:43 +0800)
close #9933

packages/server-renderer/__tests__/ssrSlot.spec.ts
packages/server-renderer/src/helpers/ssrRenderSlot.ts

index 4534630879f2867752d2e6e04dcd98eed02d5d49..7e2b2247d2529981a8c0adfaaa719b0be52f44e5 100644 (file)
@@ -137,4 +137,20 @@ describe('ssr: slot', () => {
       ),
     ).toBe(`<div>foo</div>`)
   })
+
+  // #9933
+  test('transition-group slot', async () => {
+    expect(
+      await renderToString(
+        createApp({
+          components: {
+            one: {
+              template: `<TransitionGroup tag="div"><slot/></TransitionGroup>`,
+            },
+          },
+          template: `<one><p v-for="i in 2">{{i}}</p></one>`,
+        }),
+      ),
+    ).toBe(`<div><p>1</p><p>2</p></div>`)
+  })
 })
index b388e7d193604f5c2e58f0561b2de95e36d170ca..df088e8929a72a5a7cf789c02d4053c0f8262fc4 100644 (file)
@@ -82,7 +82,23 @@ export function ssrRenderSlotInner(
           fallbackRenderFn()
         }
       } else {
-        for (let i = 0; i < slotBuffer.length; i++) {
+        // #9933
+        // Although we handle Transition/TransitionGroup in the transform stage
+        // without rendering it as a fragment, the content passed into the slot
+        // may still be a fragment.
+        // Therefore, here we need to avoid rendering it as a fragment again.
+        let start = 0
+        let end = slotBuffer.length
+        if (
+          transition &&
+          slotBuffer[0] === '<!--[-->' &&
+          slotBuffer[end - 1] === '<!--]-->'
+        ) {
+          start++
+          end--
+        }
+
+        for (let i = start; i < end; i++) {
           push(slotBuffer[i])
         }
       }