wip(compiler): adjust renderSlot() signature
This commit is contained in:
parent
306c22efe1
commit
05db2a9c6c
@ -277,8 +277,7 @@ describe('compiler: transform', () => {
|
|||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`
|
||||||
arguments: ['$slots.default']
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -112,7 +112,7 @@ return function render() {
|
|||||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
|
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||||
return _renderSlot($slots.default)
|
return _renderSlot($slots, \\"default\\")
|
||||||
}), 128 /* UNKEYED_FRAGMENT */))
|
}), 128 /* UNKEYED_FRAGMENT */))
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
@ -126,7 +126,7 @@ return function render() {
|
|||||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
|
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||||
return _renderSlot($slots.default)
|
return _renderSlot($slots, \\"default\\")
|
||||||
}), 128 /* UNKEYED_FRAGMENT */))
|
}), 128 /* UNKEYED_FRAGMENT */))
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
@ -40,7 +40,7 @@ return function render() {
|
|||||||
const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue
|
const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue
|
||||||
|
|
||||||
return (_openBlock(), ok
|
return (_openBlock(), ok
|
||||||
? _renderSlot($slots.default, { key: 0 })
|
? _renderSlot($slots, \\"default\\", { key: 0 })
|
||||||
: _createBlock(_Empty))
|
: _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))
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
@ -36,7 +36,7 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
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({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [`$slots.foo`]
|
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"]`]
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -64,17 +55,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
`$slots`,
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
|
||||||
children: [
|
|
||||||
`$slots[`,
|
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: false
|
isStatic: false
|
||||||
},
|
|
||||||
`]`
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@ -88,10 +73,10 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: [
|
arguments: [
|
||||||
|
`_ctx.$slots`,
|
||||||
{
|
{
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [
|
children: [
|
||||||
`_ctx.$slots[`,
|
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.foo`,
|
content: `_ctx.foo`,
|
||||||
@ -102,8 +87,7 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.bar`,
|
content: `_ctx.bar`,
|
||||||
isStatic: false
|
isStatic: false
|
||||||
},
|
}
|
||||||
`]`
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -116,7 +100,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.default`,
|
`$slots`,
|
||||||
|
`"default"`,
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
properties: [
|
properties: [
|
||||||
@ -152,7 +137,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.foo`,
|
`$slots`,
|
||||||
|
`"foo"`,
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
// props should not include name
|
// props should not include name
|
||||||
@ -189,10 +175,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
`$slots`,
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
{ content: `foo`, isStatic: false },
|
||||||
children: [`$slots[`, { content: `foo` }, `]`]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
// props should not include name
|
// props should not include name
|
||||||
@ -229,7 +213,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.default`,
|
`$slots`,
|
||||||
|
`"default"`,
|
||||||
`{}`,
|
`{}`,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -247,7 +232,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.foo`,
|
`$slots`,
|
||||||
|
`"foo"`,
|
||||||
`{}`,
|
`{}`,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -265,7 +251,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.default`,
|
`$slots`,
|
||||||
|
`"default"`,
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
properties: [
|
properties: [
|
||||||
@ -297,7 +284,8 @@ describe('compiler: transform <slot> outlets', () => {
|
|||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
callee: `_${RENDER_SLOT}`,
|
||||||
arguments: [
|
arguments: [
|
||||||
`$slots.foo`,
|
`$slots`,
|
||||||
|
`"foo"`,
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -360,7 +360,23 @@ describe('compiler: v-if', () => {
|
|||||||
expect(branch1).toMatchObject({
|
expect(branch1).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: `_${RENDER_SLOT}`,
|
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()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import { NodeTransform } from '../transform'
|
import { NodeTransform } from '../transform'
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
CompoundExpressionNode,
|
|
||||||
createCompoundExpression,
|
|
||||||
CallExpression,
|
CallExpression,
|
||||||
createCallExpression
|
createCallExpression,
|
||||||
|
ExpressionNode
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { isSimpleIdentifier, isSlotOutlet } from '../utils'
|
import { isSlotOutlet } from '../utils'
|
||||||
import { buildProps } from './transformElement'
|
import { buildProps } from './transformElement'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
import { RENDER_SLOT } from '../runtimeConstants'
|
import { RENDER_SLOT } from '../runtimeConstants'
|
||||||
@ -15,7 +14,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||||||
if (isSlotOutlet(node)) {
|
if (isSlotOutlet(node)) {
|
||||||
const { props, children, loc } = node
|
const { props, children, loc } = node
|
||||||
const $slots = context.prefixIdentifiers ? `_ctx.$slots` : `$slots`
|
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" />
|
// check for <slot name="xxx" OR :name="xxx" />
|
||||||
let nameIndex: number = -1
|
let nameIndex: number = -1
|
||||||
@ -24,11 +23,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||||||
if (prop.type === NodeTypes.ATTRIBUTE) {
|
if (prop.type === NodeTypes.ATTRIBUTE) {
|
||||||
if (prop.name === `name` && prop.value) {
|
if (prop.name === `name` && prop.value) {
|
||||||
// static name="xxx"
|
// static name="xxx"
|
||||||
const name = prop.value.content
|
slotName = JSON.stringify(prop.value.content)
|
||||||
const accessor = isSimpleIdentifier(name)
|
|
||||||
? `.${name}`
|
|
||||||
: `[${JSON.stringify(name)}]`
|
|
||||||
slot = `${$slots}${accessor}`
|
|
||||||
nameIndex = i
|
nameIndex = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -42,20 +37,14 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||||||
arg.content === `name`
|
arg.content === `name`
|
||||||
) {
|
) {
|
||||||
// dynamic :name="xxx"
|
// dynamic :name="xxx"
|
||||||
slot = createCompoundExpression([
|
slotName = exp
|
||||||
$slots + `[`,
|
|
||||||
...(exp.type === NodeTypes.SIMPLE_EXPRESSION
|
|
||||||
? [exp]
|
|
||||||
: exp.children),
|
|
||||||
`]`
|
|
||||||
])
|
|
||||||
nameIndex = i
|
nameIndex = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const slotArgs: CallExpression['arguments'] = [slot]
|
const slotArgs: CallExpression['arguments'] = [$slots, slotName]
|
||||||
const propsWithoutName =
|
const propsWithoutName =
|
||||||
nameIndex > -1
|
nameIndex > -1
|
||||||
? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1))
|
? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1))
|
||||||
|
@ -118,11 +118,12 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||||||
if (isTemplate && keyProperty) {
|
if (isTemplate && keyProperty) {
|
||||||
// <template v-for="..." :key="..."><slot/></template>
|
// <template v-for="..." :key="..."><slot/></template>
|
||||||
// we need to inject the key to the renderSlot() call.
|
// 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
|
| PropsExpression
|
||||||
| undefined
|
| undefined
|
||||||
| 'null'
|
| 'null'
|
||||||
childBlock.arguments[1] = injectProp(
|
childBlock.arguments[2] = injectProp(
|
||||||
existingProps,
|
existingProps,
|
||||||
keyProperty,
|
keyProperty,
|
||||||
context
|
context
|
||||||
|
@ -27,7 +27,8 @@ import {
|
|||||||
EMPTY,
|
EMPTY,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
APPLY_DIRECTIVES,
|
APPLY_DIRECTIVES,
|
||||||
CREATE_VNODE
|
CREATE_VNODE,
|
||||||
|
RENDER_SLOT
|
||||||
} from '../runtimeConstants'
|
} from '../runtimeConstants'
|
||||||
import { injectProp } from '../utils'
|
import { injectProp } from '../utils'
|
||||||
import { PropsExpression } from './transformElement'
|
import { PropsExpression } from './transformElement'
|
||||||
@ -185,18 +186,24 @@ function createChildrenCodegenNode(
|
|||||||
vnodeCall = vnodeCall.arguments[0] as CallExpression
|
vnodeCall = vnodeCall.arguments[0] as CallExpression
|
||||||
}
|
}
|
||||||
// Change createVNode to createBlock.
|
// 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)) {
|
if (vnodeCall.callee.includes(CREATE_VNODE)) {
|
||||||
vnodeCall.callee = helper(CREATE_BLOCK)
|
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
|
// inject branch key
|
||||||
const existingProps = vnodeCall.arguments[1] as
|
const existingProps = vnodeCall.arguments[propsIndex] as
|
||||||
| PropsExpression
|
| PropsExpression
|
||||||
| undefined
|
| undefined
|
||||||
| 'null'
|
| 'null'
|
||||||
vnodeCall.arguments[1] = injectProp(existingProps, keyProperty, context)
|
vnodeCall.arguments[propsIndex] = injectProp(
|
||||||
|
existingProps,
|
||||||
|
keyProperty,
|
||||||
|
context
|
||||||
|
)
|
||||||
return childCodegen
|
return childCodegen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,14 @@ import {
|
|||||||
} from '../vnode'
|
} from '../vnode'
|
||||||
|
|
||||||
export function renderSlot(
|
export function renderSlot(
|
||||||
slot: Slot | undefined,
|
slots: Record<string, Slot>,
|
||||||
|
key: string,
|
||||||
props: any = {},
|
props: any = {},
|
||||||
// this is not a user-facing function, so the fallback is always generated by
|
// this is not a user-facing function, so the fallback is always generated by
|
||||||
// the compiler and gurunteed to be an array
|
// the compiler and gurunteed to be an array
|
||||||
fallback?: VNodeChildren
|
fallback?: VNodeChildren
|
||||||
): VNode {
|
): VNode {
|
||||||
|
const slot = slots[key]
|
||||||
return (
|
return (
|
||||||
openBlock(),
|
openBlock(),
|
||||||
createBlock(
|
createBlock(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user