]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): fix the detection of forwarded slots with v-if or v-for (#3353)
authorHcySunYang <HcySunYang@outlook.com>
Mon, 22 Mar 2021 20:34:46 +0000 (04:34 +0800)
committerGitHub <noreply@github.com>
Mon, 22 Mar 2021 20:34:46 +0000 (16:34 -0400)
fix #3347

packages/compiler-core/__tests__/transforms/vSlot.spec.ts
packages/compiler-core/src/transforms/vSlot.ts

index a14198c8adc4bb110609d4b05a0fb13b4ef1ec35..99fc009b504598c955dc0536fcfd26e7e575a04d 100644 (file)
@@ -15,6 +15,7 @@ import { transformElement } from '../../src/transforms/transformElement'
 import { transformOn } from '../../src/transforms/vOn'
 import { transformBind } from '../../src/transforms/vBind'
 import { transformExpression } from '../../src/transforms/transformExpression'
+import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
 import {
   trackSlotScopes,
   trackVForSlotScopes
@@ -34,6 +35,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
       ...(options.prefixIdentifiers
         ? [trackVForSlotScopes, transformExpression]
         : []),
+      transformSlotOutlet,
       transformElement,
       trackSlotScopes
     ],
@@ -737,9 +739,8 @@ describe('compiler: transform component slots', () => {
     expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
   })
 
-  test('generate flag on forwarded slots', () => {
-    const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
-    expect(slots).toMatchObject({
+  describe('forwarded slots', () => {
+    const toMatch = {
       type: NodeTypes.JS_OBJECT_EXPRESSION,
       properties: [
         {
@@ -751,6 +752,20 @@ describe('compiler: transform component slots', () => {
           value: { content: `3 /* FORWARDED */` }
         }
       ]
+    }
+    test('<slot> tag only', () => {
+      const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
+    })
+
+    test('<slot> tag w/ v-if', () => {
+      const { slots } = parseWithSlots(`<Comp><slot v-if="ok"/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
+    })
+
+    test('<slot> tag w/ v-for', () => {
+      const { slots } = parseWithSlots(`<Comp><slot v-for="a in b"/></Comp>`)
+      expect(slots).toMatchObject(toMatch)
     })
   })
 
index 8e1596a2e9a2cdf05102b38c977b289336c8e6f9..e6387be6c33273845472bf40aad5a9d54fa90345 100644 (file)
@@ -368,14 +368,25 @@ function buildDynamicSlot(
 function hasForwardedSlots(children: TemplateChildNode[]): boolean {
   for (let i = 0; i < children.length; i++) {
     const child = children[i]
-    if (child.type === NodeTypes.ELEMENT) {
-      if (
-        child.tagType === ElementTypes.SLOT ||
-        (child.tagType === ElementTypes.ELEMENT &&
-          hasForwardedSlots(child.children))
-      ) {
-        return true
-      }
+    switch (child.type) {
+      case NodeTypes.ELEMENT:
+        if (
+          child.tagType === ElementTypes.SLOT ||
+          (child.tagType === ElementTypes.ELEMENT &&
+            hasForwardedSlots(child.children))
+        ) {
+          return true
+        }
+        break
+      case NodeTypes.IF:
+        if (hasForwardedSlots(child.branches)) return true
+        break
+      case NodeTypes.IF_BRANCH:
+      case NodeTypes.FOR:
+        if (hasForwardedSlots(child.children)) return true
+        break
+      default:
+        break
     }
   }
   return false