fix(compiler-core): fix v-if key injection with v-on object syntax (#2368)

fix #2366
This commit is contained in:
ᴜɴвʏтᴇ 2020-10-14 00:04:52 +08:00 committed by GitHub
parent 6ba7ba47d5
commit 692197be33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 15 deletions

View File

@ -4,25 +4,25 @@ import { transformIf } from '../../src/transforms/vIf'
import { transformElement } from '../../src/transforms/transformElement' import { transformElement } from '../../src/transforms/transformElement'
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet' import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
import { import {
CommentNode,
ConditionalExpression,
ElementNode,
ElementTypes,
IfBranchNode,
IfConditionalExpression,
IfNode, IfNode,
NodeTypes, NodeTypes,
ElementNode,
TextNode,
CommentNode,
SimpleExpressionNode, SimpleExpressionNode,
ConditionalExpression, TextNode,
IfConditionalExpression, VNodeCall
VNodeCall,
ElementTypes,
IfBranchNode
} from '../../src/ast' } from '../../src/ast'
import { ErrorCodes } from '../../src/errors' import { ErrorCodes } from '../../src/errors'
import { CompilerOptions, generate } from '../../src' import { CompilerOptions, generate, TO_HANDLERS } from '../../src'
import { import {
CREATE_COMMENT,
FRAGMENT, FRAGMENT,
MERGE_PROPS, MERGE_PROPS,
RENDER_SLOT, RENDER_SLOT
CREATE_COMMENT
} from '../../src/runtimeHelpers' } from '../../src/runtimeHelpers'
import { createObjectMatcher } from '../testUtils' import { createObjectMatcher } from '../testUtils'
@ -673,4 +673,24 @@ describe('compiler: v-if', () => {
expect((b1.children[3] as ElementNode).tag).toBe(`p`) expect((b1.children[3] as ElementNode).tag).toBe(`p`)
}) })
}) })
test('v-on with v-if', () => {
const {
node: { codegenNode }
} = parseWithIfTransform(
`<button v-on="{ click: clickEvent }" v-if="true">w/ v-if</button>`
)
expect((codegenNode.consequent as any).props.type).toBe(
NodeTypes.JS_CALL_EXPRESSION
)
expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)
expect(
(codegenNode.consequent as any).props.arguments[0].properties[0].value
.content
).toBe('0')
expect((codegenNode.consequent as any).props.arguments[1].callee).toBe(
TO_HANDLERS
)
})
}) })

View File

@ -29,7 +29,8 @@ import {
TELEPORT, TELEPORT,
SUSPENSE, SUSPENSE,
KEEP_ALIVE, KEEP_ALIVE,
BASE_TRANSITION BASE_TRANSITION,
TO_HANDLERS
} from './runtimeHelpers' } from './runtimeHelpers'
import { isString, isObject, hyphenate, extend } from '@vue/shared' import { isString, isObject, hyphenate, extend } from '@vue/shared'
@ -215,7 +216,7 @@ export function injectProp(
prop: Property, prop: Property,
context: TransformContext context: TransformContext
) { ) {
let propsWithInjection: ObjectExpression | CallExpression let propsWithInjection: ObjectExpression | CallExpression | undefined
const props = const props =
node.type === NodeTypes.VNODE_CALL ? node.props : node.arguments[2] node.type === NodeTypes.VNODE_CALL ? node.props : node.arguments[2]
if (props == null || isString(props)) { if (props == null || isString(props)) {
@ -228,9 +229,17 @@ export function injectProp(
if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) { if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {
first.properties.unshift(prop) first.properties.unshift(prop)
} else { } else {
props.arguments.unshift(createObjectExpression([prop])) if (props.callee === TO_HANDLERS) {
// #2366
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
createObjectExpression([prop]),
props
])
} else {
props.arguments.unshift(createObjectExpression([prop]))
}
} }
propsWithInjection = props !propsWithInjection && (propsWithInjection = props)
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) { } else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
let alreadyExists = false let alreadyExists = false
// check existing key to avoid overriding user provided keys // check existing key to avoid overriding user provided keys