Skip to content

Commit

Permalink
fix(compiler-core): fix v-if parent with fragment root (vuejs#604)
Browse files Browse the repository at this point in the history
  • Loading branch information
underfin committed Jan 10, 2020
1 parent b9479e2 commit 46db251
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 18 additions & 9 deletions packages/compiler-core/__tests__/transforms/vIf.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -530,6 +530,15 @@ describe('compiler: v-if', () => {
)
})

// #604
test('parent is element with fragment root', () => {
const { root } = parseWithIfTransform(
`<span></span><div><div v-if="ok"/></div>`,
{ onError: jest.fn() }
)
expect(generate(root).code).toMatchSnapshot()
})

test.todo('with comments')
})
})
20 changes: 13 additions & 7 deletions packages/compiler-core/src/ast.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -115,6 +115,7 @@ export interface BaseElementNode extends Node {
props: Array<AttributeNode | DirectiveNode>
children: TemplateChildNode[]
codegenNode:
| SequenceExpression
| CallExpression
| SimpleExpressionNode
| CacheExpression
Expand All @@ -124,6 +125,7 @@ export interface BaseElementNode extends Node {
export interface PlainElementNode extends BaseElementNode {
tagType: ElementTypes.ELEMENT
codegenNode:
| SequenceExpression
| ElementCodegenNode
| undefined
| SimpleExpressionNode // when hoisted
Expand All @@ -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 {
Expand Down
55 changes: 35 additions & 20 deletions packages/compiler-core/src/transforms/transformElement.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit 46db251

Please sign in to comment.