diff --git a/packages/compiler-core/__tests__/transform.spec.ts b/packages/compiler-core/__tests__/transform.spec.ts
index 44b88c93..e2d52fe4 100644
--- a/packages/compiler-core/__tests__/transform.spec.ts
+++ b/packages/compiler-core/__tests__/transform.spec.ts
@@ -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}`
}
})
})
diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
index d40121be..02bbbcbb 100644
--- a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
+++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
@@ -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 */))
}
}"
diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
index 8fd74760..f2959952 100644
--- a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
+++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
@@ -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 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))
+ }
+}"
+`;
diff --git a/packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts b/packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts
index 5b16c27b..bad59c46 100644
--- a/packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/transformSlotOutlet.spec.ts
@@ -36,7 +36,7 @@ describe('compiler: transform 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 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(``)
- 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 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 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 outlets', () => {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `_ctx.bar`,
isStatic: false
- },
- `]`
+ }
]
}
]
@@ -116,7 +100,8 @@ describe('compiler: transform 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 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 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 outlets', () => {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`,
arguments: [
- `$slots.default`,
+ `$slots`,
+ `"default"`,
`{}`,
[
{
@@ -247,7 +232,8 @@ describe('compiler: transform outlets', () => {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`,
arguments: [
- `$slots.foo`,
+ `$slots`,
+ `"foo"`,
`{}`,
[
{
@@ -265,7 +251,8 @@ describe('compiler: transform 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 outlets', () => {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`,
arguments: [
- `$slots.foo`,
+ `$slots`,
+ `"foo"`,
{
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
index 930313c3..c9d8c551 100644
--- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
@@ -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 ', () => {
+ const {
+ root,
+ node: { codegenNode }
+ } = parseWithIfTransform(``)
+ // 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()
})
diff --git a/packages/compiler-core/src/transforms/transfromSlotOutlet.ts b/packages/compiler-core/src/transforms/transfromSlotOutlet.ts
index 3ed95a4e..f897aa8c 100644
--- a/packages/compiler-core/src/transforms/transfromSlotOutlet.ts
+++ b/packages/compiler-core/src/transforms/transfromSlotOutlet.ts
@@ -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
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))
diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts
index 6ae47d3e..c54e9578 100644
--- a/packages/compiler-core/src/transforms/vFor.ts
+++ b/packages/compiler-core/src/transforms/vFor.ts
@@ -118,11 +118,12 @@ export const transformFor = createStructuralDirectiveTransform(
if (isTemplate && keyProperty) {
//
// 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
diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts
index 9dd27e1f..47eda281 100644
--- a/packages/compiler-core/src/transforms/vIf.ts
+++ b/packages/compiler-core/src/transforms/vIf.ts
@@ -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
}
}
diff --git a/packages/runtime-core/src/helpers/renderSlot.ts b/packages/runtime-core/src/helpers/renderSlot.ts
index 5e14df25..c5a84aad 100644
--- a/packages/runtime-core/src/helpers/renderSlot.ts
+++ b/packages/runtime-core/src/helpers/renderSlot.ts
@@ -8,12 +8,14 @@ import {
} from '../vnode'
export function renderSlot(
- slot: Slot | undefined,
+ slots: Record,
+ 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(