feat(compiler): render <slot/> as block fragments

This commit is contained in:
Evan You
2019-10-03 12:03:14 -04:00
parent fc47029ed3
commit aa9245d55c
12 changed files with 268 additions and 191 deletions

View File

@@ -274,16 +274,13 @@ describe('compiler: transform', () => {
test('single <slot/>', () => {
const ast = transformWithCodegen(`<slot/>`)
expect(ast.codegenNode).toMatchObject(
createBlockMatcher([
`_${FRAGMENT}`,
`null`,
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`
}
])
)
expect(ast.codegenNode).toMatchObject({
codegenNode: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`,
arguments: ['$slots.default']
}
})
})
test('single element', () => {

View File

@@ -112,7 +112,21 @@ return function render() {
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, _renderSlot($slots.default)))
return _renderSlot($slots.default)
}), 128 /* UNKEYED_FRAGMENT */))
}
}"
`;
exports[`compiler: v-for codegen v-for on <slot/> 1`] = `
"const _Vue = Vue
return function render() {
with (this) {
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
return _renderSlot($slots.default)
}), 128 /* UNKEYED_FRAGMENT */))
}
}"

View File

@@ -37,10 +37,10 @@ exports[`compiler: v-if codegen template v-if w/ single <slot/> child 1`] = `
return function render() {
with (this) {
const { openBlock: _openBlock, renderSlot: _renderSlot, Fragment: _Fragment, createBlock: _createBlock, Empty: _Empty } = _Vue
const { openBlock: _openBlock, renderSlot: _renderSlot, createBlock: _createBlock, Empty: _Empty } = _Vue
return (_openBlock(), ok
? _createBlock(_Fragment, { key: 0 }, _renderSlot($slots.default))
? _renderSlot($slots.default, { key: 0 })
: _createBlock(_Empty))
}
}"

View File

@@ -567,7 +567,8 @@ describe('compiler: v-for', () => {
describe('codegen', () => {
function assertSharedCodegen(
node: SequenceExpression,
keyed: boolean = false
keyed: boolean = false,
customReturn: boolean = false
) {
expect(node).toMatchObject({
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
@@ -589,19 +590,21 @@ describe('compiler: v-for', () => {
{}, // to be asserted by each test
{
type: NodeTypes.JS_FUNCTION_EXPRESSION,
returns: {
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
expressions: [
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${OPEN_BLOCK}`
},
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${CREATE_BLOCK}`
returns: customReturn
? {}
: {
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
expressions: [
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${OPEN_BLOCK}`
},
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${CREATE_BLOCK}`
}
]
}
]
}
}
]
},
@@ -621,7 +624,10 @@ describe('compiler: v-for', () => {
return {
source: renderListArgs[0] as SimpleExpressionNode,
params: (renderListArgs[1] as any).params,
blockArgs: (renderListArgs[1] as any).returns.expressions[1].arguments
returns: (renderListArgs[1] as any).returns,
blockArgs: customReturn
? null
: (renderListArgs[1] as any).returns.expressions[1].arguments
}
}
@@ -715,17 +721,33 @@ describe('compiler: v-for', () => {
} = parseWithForTransform(
'<template v-for="item in items"><slot/></template>'
)
expect(assertSharedCodegen(codegenNode)).toMatchObject({
expect(
assertSharedCodegen(codegenNode, false, true /* custom return */)
).toMatchObject({
source: { content: `items` },
params: [{ content: `item` }],
blockArgs: [
`_${FRAGMENT}`,
`null`,
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`
}
]
returns: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`
}
})
expect(generate(root).code).toMatchSnapshot()
})
test('v-for on <slot/>', () => {
const {
root,
node: { codegenNode }
} = parseWithForTransform('<slot v-for="item in items"></slot>')
expect(
assertSharedCodegen(codegenNode, false, true /* custom return */)
).toMatchObject({
source: { content: `items` },
params: [{ content: `item` }],
returns: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`
}
})
expect(generate(root).code).toMatchSnapshot()
})
@@ -794,7 +816,7 @@ describe('compiler: v-for', () => {
// should optimize v-if + v-for into a single Fragment block
arguments: [
`_${FRAGMENT}`,
`{ key: 0 }`,
createObjectMatcher({ key: `[0]` }),
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_LIST}`,

View File

@@ -316,7 +316,10 @@ describe('compiler: v-if', () => {
assertSharedCodegen(codegenNode)
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([`"div"`, `{ key: 0 }`])
expect(branch1.arguments).toMatchObject([
`"div"`,
createObjectMatcher({ key: `[0]` })
])
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
.alternate as CallExpression
expect(branch2.arguments).toMatchObject([`_${EMPTY}`])
@@ -333,7 +336,7 @@ describe('compiler: v-if', () => {
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([
`_${FRAGMENT}`,
`{ key: 0 }`,
createObjectMatcher({ key: `[0]` }),
[
{ type: NodeTypes.ELEMENT, tag: 'div' },
{ type: NodeTypes.TEXT, content: `hello` },
@@ -351,17 +354,14 @@ describe('compiler: v-if', () => {
root,
node: { codegenNode }
} = parseWithIfTransform(`<template v-if="ok"><slot/></template>`)
assertSharedCodegen(codegenNode)
// assertSharedCodegen(codegenNode)
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([
`_${FRAGMENT}`,
`{ key: 0 }`,
{
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`
}
])
expect(branch1).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${RENDER_SLOT}`,
arguments: ['$slots.default', createObjectMatcher({ key: `[0]` })]
})
expect(generate(root).code).toMatchSnapshot()
})
@@ -373,10 +373,16 @@ describe('compiler: v-if', () => {
assertSharedCodegen(codegenNode)
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([`"div"`, `{ key: 0 }`])
expect(branch1.arguments).toMatchObject([
`"div"`,
createObjectMatcher({ key: `[0]` })
])
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
.alternate as CallExpression
expect(branch2.arguments).toMatchObject([`"p"`, `{ key: 1 }`])
expect(branch2.arguments).toMatchObject([
`"p"`,
createObjectMatcher({ key: `[1]` })
])
expect(generate(root).code).toMatchSnapshot()
})
@@ -388,12 +394,15 @@ describe('compiler: v-if', () => {
assertSharedCodegen(codegenNode, 1)
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([`"div"`, `{ key: 0 }`])
expect(branch1.arguments).toMatchObject([
`"div"`,
createObjectMatcher({ key: `[0]` })
])
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
.alternate as ConditionalExpression
expect((branch2.consequent as CallExpression).arguments).toMatchObject([
`"p"`,
`{ key: 1 }`
createObjectMatcher({ key: `[1]` })
])
expect(generate(root).code).toMatchSnapshot()
})
@@ -408,16 +417,19 @@ describe('compiler: v-if', () => {
assertSharedCodegen(codegenNode, 1)
const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
.consequent as CallExpression
expect(branch1.arguments).toMatchObject([`"div"`, `{ key: 0 }`])
expect(branch1.arguments).toMatchObject([
`"div"`,
createObjectMatcher({ key: `[0]` })
])
const branch2 = (codegenNode.expressions[1] as ConditionalExpression)
.alternate as ConditionalExpression
expect((branch2.consequent as CallExpression).arguments).toMatchObject([
`"p"`,
`{ key: 1 }`
createObjectMatcher({ key: `[1]` })
])
expect((branch2.alternate as CallExpression).arguments).toMatchObject([
`_${FRAGMENT}`,
`{ key: 2 }`,
createObjectMatcher({ key: `[2]` }),
[
{
type: NodeTypes.TEXT,
@@ -437,7 +449,7 @@ describe('compiler: v-if', () => {
expect(branch1.arguments[1]).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${MERGE_PROPS}`,
arguments: [`{ key: 0 }`, { content: `obj` }]
arguments: [createObjectMatcher({ key: `[0]` }), { content: `obj` }]
})
})
@@ -470,7 +482,7 @@ describe('compiler: v-if', () => {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: `_${MERGE_PROPS}`,
arguments: [
`{ key: 0 }`,
createObjectMatcher({ key: `[0]` }),
{ content: `obj` },
createObjectMatcher({
id: 'foo'
@@ -487,9 +499,11 @@ describe('compiler: v-if', () => {
.consequent as CallExpression
expect(branch1.callee).toBe(`_${APPLY_DIRECTIVES}`)
const realBranch = branch1.arguments[0] as CallExpression
expect(realBranch.arguments[1]).toBe(`{ key: 0 }`)
expect(realBranch.arguments[1]).toMatchObject(
createObjectMatcher({ key: `[0]` })
)
})
test('with comments', () => {})
test.todo('with comments')
})
})