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 498c03d35c6..427c0795cc4 100644
--- a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
+++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
@@ -14,6 +14,25 @@ return function render() {
}"
`;
+exports[`compiler: v-if codegen parent is element with fragment root 1`] = `
+"const _Vue = Vue
+
+return function render() {
+ with (this) {
+ const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Fragment: _Fragment } = _Vue
+
+ return (_openBlock(), _createBlock(_Fragment, null, [
+ _createVNode(\\"span\\"),
+ (_openBlock(), _createBlock(\\"div\\", null, [
+ (_openBlock(), ok
+ ? _createBlock(\\"div\\", { key: 0 })
+ : _createCommentVNode(\\"v-if\\", true))
+ ]))
+ ], 64 /* STABLE_FRAGMENT */))
+ }
+}"
+`;
+
exports[`compiler: v-if codegen template v-if 1`] = `
"const _Vue = Vue
diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
index f50ad66297d..a62654b77f1 100644
--- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
@@ -4,26 +4,26 @@ import { transformIf } from '../../src/transforms/vIf'
import { transformElement } from '../../src/transforms/transformElement'
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
import {
+ CallExpression,
+ CommentNode,
+ ConditionalExpression,
+ ElementNode,
IfNode,
NodeTypes,
- ElementNode,
- TextNode,
- CommentNode,
- SimpleExpressionNode,
SequenceExpression,
- ConditionalExpression,
- CallExpression
+ SimpleExpressionNode,
+ TextNode
} from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
import { CompilerOptions, generate } from '../../src'
import {
- OPEN_BLOCK,
CREATE_BLOCK,
+ CREATE_COMMENT,
FRAGMENT,
MERGE_PROPS,
- WITH_DIRECTIVES,
+ OPEN_BLOCK,
RENDER_SLOT,
- CREATE_COMMENT
+ WITH_DIRECTIVES
} from '../../src/runtimeHelpers'
import { createObjectMatcher } from '../testUtils'
@@ -530,6 +530,15 @@ describe('compiler: v-if', () => {
)
})
+ // #604
+ test('parent is element with fragment root', () => {
+ const { root } = parseWithIfTransform(
+ `
`,
+ { onError: jest.fn() }
+ )
+ expect(generate(root).code).toMatchSnapshot()
+ })
+
test.todo('with comments')
})
})
diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts
index 4261e738345..959b1e8b5cc 100644
--- a/packages/compiler-core/src/ast.ts
+++ b/packages/compiler-core/src/ast.ts
@@ -1,14 +1,14 @@
import { isString } from '@vue/shared'
import { ForParseResult } from './transforms/vFor'
import {
- CREATE_VNODE,
- WITH_DIRECTIVES,
- RENDER_SLOT,
+ CREATE_BLOCK,
CREATE_SLOTS,
- RENDER_LIST,
+ CREATE_VNODE,
+ FRAGMENT,
OPEN_BLOCK,
- CREATE_BLOCK,
- FRAGMENT
+ RENDER_LIST,
+ RENDER_SLOT,
+ WITH_DIRECTIVES
} from './runtimeHelpers'
import { PropsExpression } from './transforms/transformElement'
import { ImportItem } from './transform'
@@ -115,6 +115,7 @@ export interface BaseElementNode extends Node {
props: Array
children: TemplateChildNode[]
codegenNode:
+ | SequenceExpression
| CallExpression
| SimpleExpressionNode
| CacheExpression
@@ -124,6 +125,7 @@ export interface BaseElementNode extends Node {
export interface PlainElementNode extends BaseElementNode {
tagType: ElementTypes.ELEMENT
codegenNode:
+ | SequenceExpression
| ElementCodegenNode
| undefined
| SimpleExpressionNode // when hoisted
@@ -132,7 +134,11 @@ export interface PlainElementNode extends BaseElementNode {
export interface ComponentNode extends BaseElementNode {
tagType: ElementTypes.COMPONENT
- codegenNode: ComponentCodegenNode | undefined | CacheExpression // when cached by v-once
+ codegenNode:
+ | SequenceExpression
+ | ComponentCodegenNode
+ | undefined
+ | CacheExpression // when cached by v-once
}
export interface SlotOutletNode extends BaseElementNode {
diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts
index c13e9e4ce09..abf37519800 100644
--- a/packages/compiler-core/src/transforms/transformElement.ts
+++ b/packages/compiler-core/src/transforms/transformElement.ts
@@ -1,39 +1,42 @@
import { NodeTransform, TransformContext } from '../transform'
import {
- NodeTypes,
- ElementTypes,
- CallExpression,
- ObjectExpression,
- ElementNode,
- DirectiveNode,
- ExpressionNode,
ArrayExpression,
- createCallExpression,
+ CallExpression,
createArrayExpression,
+ createCallExpression,
+ createObjectExpression,
createObjectProperty,
+ createSequenceExpression,
createSimpleExpression,
- createObjectExpression,
+ DirectiveNode,
+ ElementNode,
+ ElementTypes,
+ ExpressionNode,
+ NodeTypes,
+ ObjectExpression,
Property
} from '../ast'
-import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
+import { isSymbol, PatchFlagNames, PatchFlags } from '@vue/shared'
import { createCompilerError, ErrorCodes } from '../errors'
import {
+ CREATE_BLOCK,
CREATE_VNODE,
- WITH_DIRECTIVES,
- RESOLVE_DIRECTIVE,
+ KEEP_ALIVE,
+ MERGE_PROPS,
+ OPEN_BLOCK,
+ PORTAL,
RESOLVE_COMPONENT,
+ RESOLVE_DIRECTIVE,
RESOLVE_DYNAMIC_COMPONENT,
- MERGE_PROPS,
TO_HANDLERS,
- PORTAL,
- KEEP_ALIVE
+ WITH_DIRECTIVES
} from '../runtimeHelpers'
import {
+ findProp,
getInnerRange,
+ isCoreComponent,
isVSlot,
- toValidAssetId,
- findProp,
- isCoreComponent
+ toValidAssetId
} from '../utils'
import { buildSlots } from './vSlot'
import { isStaticNode } from './hoistStatic'
@@ -190,8 +193,20 @@ export const transformElement: NodeTransform = (node, context) => {
}
const { loc } = node
- const vnode = createCallExpression(context.helper(CREATE_VNODE), args, loc)
-
+ let vnode: ElementNode['codegenNode'] = createCallExpression(
+ context.helper(CREATE_VNODE),
+ args,
+ loc
+ )
+ if (
+ context.root.children[0] !== node &&
+ node.children.find(c => c.type === NodeTypes.IF)
+ ) {
+ vnode = createSequenceExpression([
+ createCallExpression(context.helper(OPEN_BLOCK)),
+ createCallExpression(context.helper(CREATE_BLOCK), args, loc)
+ ])
+ }
if (runtimeDirectives && runtimeDirectives.length) {
node.codegenNode = createCallExpression(
context.helper(WITH_DIRECTIVES),