fix(compiler): v-for fragments should be blocks
This commit is contained in:
parent
191db785bd
commit
bec01c93bd
@ -17,11 +17,11 @@ return function render() {
|
||||
: _createBlock(_Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
_createVNode(_Fragment, null, _renderList(list, (value, index) => {
|
||||
(_openBlock(), _createBlock(_Fragment, null, _renderList(list, (value, index) => {
|
||||
return (_openBlock(), _createBlock(\\"div\\", null, [
|
||||
_createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
|
||||
]))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
], 2 /* CLASS */)
|
||||
}
|
||||
}"
|
||||
@ -42,11 +42,11 @@ return function render() {
|
||||
: createBlock(Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
createVNode(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
(openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
return (openBlock(), createBlock(\\"div\\", null, [
|
||||
createVNode(\\"span\\", null, toString(value + index), 1 /* TEXT */)
|
||||
]))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
], 2 /* CLASS */)
|
||||
}"
|
||||
`;
|
||||
@ -66,11 +66,11 @@ export default function render() {
|
||||
: createBlock(Fragment, { key: 1 }, [
|
||||
\\"no\\"
|
||||
])),
|
||||
createVNode(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
(openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => {
|
||||
return (openBlock(), createBlock(\\"div\\", null, [
|
||||
createVNode(\\"span\\", null, _toString(value + index), 1 /* TEXT */)
|
||||
]))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
], 2 /* CLASS */)
|
||||
}"
|
||||
`;
|
||||
|
@ -5,11 +5,11 @@ exports[`compiler: v-for codegen basic v-for 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\"))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -19,14 +19,14 @@ exports[`compiler: v-for codegen keyed template v-for 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, { key: item }, [
|
||||
\\"hello\\",
|
||||
_createVNode(\\"span\\")
|
||||
]))
|
||||
}), 64 /* KEYED_FRAGMENT */)
|
||||
}), 64 /* KEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -36,11 +36,11 @@ exports[`compiler: v-for codegen keyed v-for 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\", { key: item }))
|
||||
}), 64 /* KEYED_FRAGMENT */)
|
||||
}), 64 /* KEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -50,11 +50,11 @@ exports[`compiler: v-for codegen skipped key 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item, __, index) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item, __, index) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\"))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -64,11 +64,11 @@ exports[`compiler: v-for codegen skipped value & key 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (_, __, index) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, __, index) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\"))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -78,11 +78,11 @@ exports[`compiler: v-for codegen skipped value 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (_, key, index) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, key, index) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\"))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -92,14 +92,14 @@ exports[`compiler: v-for codegen template v-for 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, [
|
||||
\\"hello\\",
|
||||
_createVNode(\\"span\\")
|
||||
]))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -109,11 +109,11 @@ exports[`compiler: v-for codegen template v-for w/ <slot/> 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, renderSlot: _renderSlot, openBlock: _openBlock, createBlock: _createBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, renderSlot: _renderSlot } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderSlot($slots.default)))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
@ -123,7 +123,7 @@ exports[`compiler: v-for codegen v-if + v-for 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { openBlock: _openBlock, renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, Empty: _Empty } = _Vue
|
||||
const { openBlock: _openBlock, renderList: _renderList, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode, Empty: _Empty } = _Vue
|
||||
|
||||
return (_openBlock(), ok
|
||||
? _createBlock(_Fragment, { key: 0 }, _renderList(list, (i) => {
|
||||
@ -139,11 +139,11 @@ exports[`compiler: v-for codegen value + key + index 1`] = `
|
||||
|
||||
return function render() {
|
||||
with (this) {
|
||||
const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue
|
||||
const { renderList: _renderList, openBlock: _openBlock, createBlock: _createBlock, Fragment: _Fragment, createVNode: _createVNode } = _Vue
|
||||
|
||||
return _createVNode(_Fragment, null, _renderList(items, (item, key, index) => {
|
||||
return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item, key, index) => {
|
||||
return (_openBlock(), _createBlock(\\"span\\"))
|
||||
}), 128 /* UNKEYED_FRAGMENT */)
|
||||
}), 128 /* UNKEYED_FRAGMENT */))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
@ -12,7 +12,8 @@ import {
|
||||
SimpleExpressionNode,
|
||||
ElementNode,
|
||||
InterpolationNode,
|
||||
CallExpression
|
||||
CallExpression,
|
||||
SequenceExpression
|
||||
} from '../../src/ast'
|
||||
import { ErrorCodes } from '../../src/errors'
|
||||
import { CompilerOptions, generate } from '../../src'
|
||||
@ -21,7 +22,6 @@ import {
|
||||
CREATE_BLOCK,
|
||||
FRAGMENT,
|
||||
RENDER_LIST,
|
||||
CREATE_VNODE,
|
||||
RENDER_SLOT
|
||||
} from '../../src/runtimeConstants'
|
||||
import { PatchFlags } from '@vue/runtime-dom'
|
||||
@ -565,10 +565,20 @@ describe('compiler: v-for', () => {
|
||||
})
|
||||
|
||||
describe('codegen', () => {
|
||||
function assertSharedCodegen(node: CallExpression, keyed: boolean = false) {
|
||||
function assertSharedCodegen(
|
||||
node: SequenceExpression,
|
||||
keyed: boolean = false
|
||||
) {
|
||||
expect(node).toMatchObject({
|
||||
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_VNODE}`,
|
||||
callee: `_${OPEN_BLOCK}`
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: `_${CREATE_BLOCK}`,
|
||||
arguments: [
|
||||
`_${FRAGMENT}`,
|
||||
`null`,
|
||||
@ -603,8 +613,11 @@ describe('compiler: v-for', () => {
|
||||
PatchFlagNames[PatchFlags.UNKEYED_FRAGMENT]
|
||||
} */`
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
const renderListArgs = (node.arguments[2] as CallExpression).arguments
|
||||
const renderListArgs = ((node.expressions[1] as CallExpression)
|
||||
.arguments[2] as CallExpression).arguments
|
||||
return {
|
||||
source: renderListArgs[0] as SimpleExpressionNode,
|
||||
params: (renderListArgs[1] as any).params,
|
||||
|
@ -158,7 +158,7 @@ export interface ForNode extends Node {
|
||||
keyAlias: ExpressionNode | undefined
|
||||
objectIndexAlias: ExpressionNode | undefined
|
||||
children: TemplateChildNode[]
|
||||
codegenNode: CallExpression
|
||||
codegenNode: SequenceExpression
|
||||
}
|
||||
|
||||
// We also include a number of JavaScript AST nodes for code generation.
|
||||
|
@ -24,8 +24,7 @@ import {
|
||||
RENDER_LIST,
|
||||
OPEN_BLOCK,
|
||||
CREATE_BLOCK,
|
||||
FRAGMENT,
|
||||
CREATE_VNODE
|
||||
FRAGMENT
|
||||
} from '../runtimeConstants'
|
||||
import { processExpression } from './transformExpression'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
@ -52,13 +51,16 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
const fragmentFlag = keyProp
|
||||
? PatchFlags.KEYED_FRAGMENT
|
||||
: PatchFlags.UNKEYED_FRAGMENT
|
||||
const codegenNode = createCallExpression(helper(CREATE_VNODE), [
|
||||
const codegenNode = createSequenceExpression([
|
||||
createCallExpression(helper(OPEN_BLOCK)),
|
||||
createCallExpression(helper(CREATE_BLOCK), [
|
||||
helper(FRAGMENT),
|
||||
`null`,
|
||||
renderExp,
|
||||
fragmentFlag +
|
||||
(__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``)
|
||||
])
|
||||
])
|
||||
|
||||
context.replaceNode({
|
||||
type: NodeTypes.FOR,
|
||||
|
@ -176,7 +176,8 @@ function createChildrenCodegenNode(
|
||||
if (children.length === 1) {
|
||||
// optimize away nested fragments when child is a ForNode
|
||||
if (child.type === NodeTypes.FOR) {
|
||||
const forBlockArgs = child.codegenNode.arguments
|
||||
const forBlockArgs = (child.codegenNode
|
||||
.expressions[1] as CallExpression).arguments
|
||||
// directly use the for block's children and patchFlag
|
||||
blockArgs[2] = forBlockArgs[2]
|
||||
blockArgs[3] = forBlockArgs[3]
|
||||
|
Loading…
Reference in New Issue
Block a user