From 46db25116d33e920893feb9188020897697f4b5a Mon Sep 17 00:00:00 2001 From: likui <2218301630@qq.com> Date: Fri, 10 Jan 2020 14:55:38 +0800 Subject: [PATCH] fix(compiler-core): fix v-if parent with fragment root (#604) --- .../transforms/__snapshots__/vIf.spec.ts.snap | 19 +++++++ .../__tests__/transforms/vIf.spec.ts | 27 ++++++--- packages/compiler-core/src/ast.ts | 20 ++++--- .../src/transforms/transformElement.ts | 55 ++++++++++++------- 4 files changed, 85 insertions(+), 36 deletions(-) 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),