]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip(compiler): adjust renderSlot() signature
authorEvan You <yyx990803@gmail.com>
Thu, 3 Oct 2019 18:29:12 +0000 (14:29 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 3 Oct 2019 18:29:12 +0000 (14:29 -0400)
packages/compiler-core/__tests__/transform.spec.ts
packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts
packages/compiler-core/__tests__/transforms/vIf.spec.ts
packages/compiler-core/src/transforms/transfromSlotOutlet.ts
packages/compiler-core/src/transforms/vFor.ts
packages/compiler-core/src/transforms/vIf.ts
packages/runtime-core/src/helpers/renderSlot.ts

index 44b88c9324f89b9d30cdd9b2ff609854e26df797..e2d52fe441f1352662035f9cc2abc35e6195ece2 100644 (file)
@@ -277,8 +277,7 @@ describe('compiler: transform', () => {
       expect(ast.codegenNode).toMatchObject({
         codegenNode: {
           type: NodeTypes.JS_CALL_EXPRESSION,
-          callee: `_${RENDER_SLOT}`,
-          arguments: ['$slots.default']
+          callee: `_${RENDER_SLOT}`
         }
       })
     })
index d40121beab6f73757e985fd064c4195afc2d37d4..02bbbcbb88c2035c0f562a202ea409661d3df859 100644 (file)
@@ -112,7 +112,7 @@ return function render() {
     const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
     
     return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
-      return _renderSlot($slots.default)
+      return _renderSlot($slots, \\"default\\")
     }), 128 /* UNKEYED_FRAGMENT */))
   }
 }"
@@ -126,7 +126,7 @@ return function render() {
     const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
     
     return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
-      return _renderSlot($slots.default)
+      return _renderSlot($slots, \\"default\\")
     }), 128 /* UNKEYED_FRAGMENT */))
   }
 }"
index 8fd747609ca342fc4d33cf67f930f41ce61beb76..f2959952c77881573d450f604496909fda86c766 100644 (file)
@@ -40,7 +40,7 @@ return function render() {
     const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue
     
     return (_openBlock(), ok
-      ? _renderSlot($slots.default, { key: 0 })
+      ? _renderSlot($slots, \\"default\\", { key: 0 })
       : _createBlock(_Empty))
   }
 }"
@@ -91,3 +91,17 @@ return function render() {
   }
 }"
 `;
+
+exports[`compiler: v-if codegen v-if on <slot/> 1`] = `
+"const _Vue = Vue
+
+return function render() {
+  with (this) {
+    const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue
+    
+    return (_openBlock(), ok
+      ? _renderSlot($slots, \\"default\\", { key: 0 })
+      : _createBlock(_Empty))
+  }
+}"
+`;
index 5b16c27b6170dc4c60ad74fdc050bb6862c30115..bad59c460962242634f0b3ceb51b9c1293874b64 100644 (file)
@@ -36,7 +36,7 @@ describe('compiler: transform <slot> outlets', () => {
     expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
-      arguments: [`$slots.default`]
+      arguments: [`$slots`, `"default"`]
     })
   })
 
@@ -45,16 +45,7 @@ describe('compiler: transform <slot> outlets', () => {
     expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
-      arguments: [`$slots.foo`]
-    })
-  })
-
-  test('statically named slot outlet w/ name that needs quotes', () => {
-    const ast = parseWithSlots(`<slot name="foo-bar" />`)
-    expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
-      type: NodeTypes.JS_CALL_EXPRESSION,
-      callee: `_${RENDER_SLOT}`,
-      arguments: [`$slots["foo-bar"]`]
+      arguments: [`$slots`, `"foo"`]
     })
   })
 
@@ -64,17 +55,11 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
+        `$slots`,
         {
-          type: NodeTypes.COMPOUND_EXPRESSION,
-          children: [
-            `$slots[`,
-            {
-              type: NodeTypes.SIMPLE_EXPRESSION,
-              content: `foo`,
-              isStatic: false
-            },
-            `]`
-          ]
+          type: NodeTypes.SIMPLE_EXPRESSION,
+          content: `foo`,
+          isStatic: false
         }
       ]
     })
@@ -88,10 +73,10 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: RENDER_SLOT,
       arguments: [
+        `_ctx.$slots`,
         {
           type: NodeTypes.COMPOUND_EXPRESSION,
           children: [
-            `_ctx.$slots[`,
             {
               type: NodeTypes.SIMPLE_EXPRESSION,
               content: `_ctx.foo`,
@@ -102,8 +87,7 @@ describe('compiler: transform <slot> outlets', () => {
               type: NodeTypes.SIMPLE_EXPRESSION,
               content: `_ctx.bar`,
               isStatic: false
-            },
-            `]`
+            }
           ]
         }
       ]
@@ -116,7 +100,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.default`,
+        `$slots`,
+        `"default"`,
         {
           type: NodeTypes.JS_OBJECT_EXPRESSION,
           properties: [
@@ -152,7 +137,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.foo`,
+        `$slots`,
+        `"foo"`,
         {
           type: NodeTypes.JS_OBJECT_EXPRESSION,
           // props should not include name
@@ -189,10 +175,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        {
-          type: NodeTypes.COMPOUND_EXPRESSION,
-          children: [`$slots[`, { content: `foo` }, `]`]
-        },
+        `$slots`,
+        { content: `foo`, isStatic: false },
         {
           type: NodeTypes.JS_OBJECT_EXPRESSION,
           // props should not include name
@@ -229,7 +213,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.default`,
+        `$slots`,
+        `"default"`,
         `{}`,
         [
           {
@@ -247,7 +232,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.foo`,
+        `$slots`,
+        `"foo"`,
         `{}`,
         [
           {
@@ -265,7 +251,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.default`,
+        `$slots`,
+        `"default"`,
         {
           type: NodeTypes.JS_OBJECT_EXPRESSION,
           properties: [
@@ -297,7 +284,8 @@ describe('compiler: transform <slot> outlets', () => {
       type: NodeTypes.JS_CALL_EXPRESSION,
       callee: `_${RENDER_SLOT}`,
       arguments: [
-        `$slots.foo`,
+        `$slots`,
+        `"foo"`,
         {
           type: NodeTypes.JS_OBJECT_EXPRESSION,
           properties: [
index 930313c304941ca357ba28e3892e4682a55a8c39..c9d8c551ffbfe3a911c976dccc2deeb3cd3d5997 100644 (file)
@@ -360,7 +360,23 @@ describe('compiler: v-if', () => {
       expect(branch1).toMatchObject({
         type: NodeTypes.JS_CALL_EXPRESSION,
         callee: `_${RENDER_SLOT}`,
-        arguments: ['$slots.default', createObjectMatcher({ key: `[0]` })]
+        arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
+      })
+      expect(generate(root).code).toMatchSnapshot()
+    })
+
+    test('v-if on <slot/>', () => {
+      const {
+        root,
+        node: { codegenNode }
+      } = parseWithIfTransform(`<slot v-if="ok"></slot>`)
+      // assertSharedCodegen(codegenNode)
+      const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
+        .consequent as CallExpression
+      expect(branch1).toMatchObject({
+        type: NodeTypes.JS_CALL_EXPRESSION,
+        callee: `_${RENDER_SLOT}`,
+        arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
       })
       expect(generate(root).code).toMatchSnapshot()
     })
index 3ed95a4eeba04d3c6b87ddcb5adaec9124d75f2a..f897aa8cfb2a1cea6f9d9367c8e9fb417b0879b1 100644 (file)
@@ -1,12 +1,11 @@
 import { NodeTransform } from '../transform'
 import {
   NodeTypes,
-  CompoundExpressionNode,
-  createCompoundExpression,
   CallExpression,
-  createCallExpression
+  createCallExpression,
+  ExpressionNode
 } from '../ast'
-import { isSimpleIdentifier, isSlotOutlet } from '../utils'
+import { isSlotOutlet } from '../utils'
 import { buildProps } from './transformElement'
 import { createCompilerError, ErrorCodes } from '../errors'
 import { RENDER_SLOT } from '../runtimeConstants'
@@ -15,7 +14,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
   if (isSlotOutlet(node)) {
     const { props, children, loc } = node
     const $slots = context.prefixIdentifiers ? `_ctx.$slots` : `$slots`
-    let slot: string | CompoundExpressionNode = $slots + `.default`
+    let slotName: string | ExpressionNode = `"default"`
 
     // check for <slot name="xxx" OR :name="xxx" />
     let nameIndex: number = -1
@@ -24,11 +23,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
       if (prop.type === NodeTypes.ATTRIBUTE) {
         if (prop.name === `name` && prop.value) {
           // static name="xxx"
-          const name = prop.value.content
-          const accessor = isSimpleIdentifier(name)
-            ? `.${name}`
-            : `[${JSON.stringify(name)}]`
-          slot = `${$slots}${accessor}`
+          slotName = JSON.stringify(prop.value.content)
           nameIndex = i
           break
         }
@@ -42,20 +37,14 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
           arg.content === `name`
         ) {
           // dynamic :name="xxx"
-          slot = createCompoundExpression([
-            $slots + `[`,
-            ...(exp.type === NodeTypes.SIMPLE_EXPRESSION
-              ? [exp]
-              : exp.children),
-            `]`
-          ])
+          slotName = exp
           nameIndex = i
           break
         }
       }
     }
 
-    const slotArgs: CallExpression['arguments'] = [slot]
+    const slotArgs: CallExpression['arguments'] = [$slots, slotName]
     const propsWithoutName =
       nameIndex > -1
         ? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1))
index 6ae47d3eb11b3f27545d84b8969faeb27c1ea1a6..c54e957852b4e406ead0b8a931e2a788607e2ef4 100644 (file)
@@ -118,11 +118,12 @@ export const transformFor = createStructuralDirectiveTransform(
             if (isTemplate && keyProperty) {
               // <template v-for="..." :key="..."><slot/></template>
               // we need to inject the key to the renderSlot() call.
-              const existingProps = childBlock.arguments[1] as
+              // the props for renderSlot is passed as the 3rd argument.
+              const existingProps = childBlock.arguments[2] as
                 | PropsExpression
                 | undefined
                 | 'null'
-              childBlock.arguments[1] = injectProp(
+              childBlock.arguments[2] = injectProp(
                 existingProps,
                 keyProperty,
                 context
index 9dd27e1fad816590b25c9cb408712f908ef04488..47eda2812311428d954130859867b942bb4e1d2c 100644 (file)
@@ -27,7 +27,8 @@ import {
   EMPTY,
   FRAGMENT,
   APPLY_DIRECTIVES,
-  CREATE_VNODE
+  CREATE_VNODE,
+  RENDER_SLOT
 } from '../runtimeConstants'
 import { injectProp } from '../utils'
 import { PropsExpression } from './transformElement'
@@ -185,18 +186,24 @@ function createChildrenCodegenNode(
       vnodeCall = vnodeCall.arguments[0] as CallExpression
     }
     // Change createVNode to createBlock.
-    // It's possible to have renderSlot() here as well - which already produces
-    // a block, so no need to change the callee. renderSlot() also accepts props
-    // as the 2nd argument, so the key injection logic below works for it too.
     if (vnodeCall.callee.includes(CREATE_VNODE)) {
       vnodeCall.callee = helper(CREATE_BLOCK)
     }
+    // It's possible to have renderSlot() here as well - which already produces
+    // a block, so no need to change the callee. However it accepts props at
+    // a different arg index so make sure to check for so that the key injection
+    // logic below works for it too.
+    const propsIndex = vnodeCall.callee.includes(RENDER_SLOT) ? 2 : 1
     // inject branch key
-    const existingProps = vnodeCall.arguments[1] as
+    const existingProps = vnodeCall.arguments[propsIndex] as
       | PropsExpression
       | undefined
       | 'null'
-    vnodeCall.arguments[1] = injectProp(existingProps, keyProperty, context)
+    vnodeCall.arguments[propsIndex] = injectProp(
+      existingProps,
+      keyProperty,
+      context
+    )
     return childCodegen
   }
 }
index 5e14df25ef55387150b753c45692c048509d3434..c5a84aad9ebdcc7b1baa23ed4ec258f4eb3292b1 100644 (file)
@@ -8,12 +8,14 @@ import {
 } from '../vnode'
 
 export function renderSlot(
-  slot: Slot | undefined,
+  slots: Record<string, Slot>,
+  key: string,
   props: any = {},
   // this is not a user-facing function, so the fallback is always generated by
   // the compiler and gurunteed to be an array
   fallback?: VNodeChildren
 ): VNode {
+  const slot = slots[key]
   return (
     openBlock(),
     createBlock(