Skip to content

Commit 692197b

Browse files
authored
fix(compiler-core): fix v-if key injection with v-on object syntax (#2368)
fix #2366
1 parent 6ba7ba4 commit 692197b

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

packages/compiler-core/__tests__/transforms/vIf.spec.ts

+31-11
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@ import { transformIf } from '../../src/transforms/vIf'
44
import { transformElement } from '../../src/transforms/transformElement'
55
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
66
import {
7-
IfNode,
8-
NodeTypes,
9-
ElementNode,
10-
TextNode,
117
CommentNode,
12-
SimpleExpressionNode,
138
ConditionalExpression,
14-
IfConditionalExpression,
15-
VNodeCall,
9+
ElementNode,
1610
ElementTypes,
17-
IfBranchNode
11+
IfBranchNode,
12+
IfConditionalExpression,
13+
IfNode,
14+
NodeTypes,
15+
SimpleExpressionNode,
16+
TextNode,
17+
VNodeCall
1818
} from '../../src/ast'
1919
import { ErrorCodes } from '../../src/errors'
20-
import { CompilerOptions, generate } from '../../src'
20+
import { CompilerOptions, generate, TO_HANDLERS } from '../../src'
2121
import {
22+
CREATE_COMMENT,
2223
FRAGMENT,
2324
MERGE_PROPS,
24-
RENDER_SLOT,
25-
CREATE_COMMENT
25+
RENDER_SLOT
2626
} from '../../src/runtimeHelpers'
2727
import { createObjectMatcher } from '../testUtils'
2828

@@ -673,4 +673,24 @@ describe('compiler: v-if', () => {
673673
expect((b1.children[3] as ElementNode).tag).toBe(`p`)
674674
})
675675
})
676+
677+
test('v-on with v-if', () => {
678+
const {
679+
node: { codegenNode }
680+
} = parseWithIfTransform(
681+
`<button v-on="{ click: clickEvent }" v-if="true">w/ v-if</button>`
682+
)
683+
684+
expect((codegenNode.consequent as any).props.type).toBe(
685+
NodeTypes.JS_CALL_EXPRESSION
686+
)
687+
expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)
688+
expect(
689+
(codegenNode.consequent as any).props.arguments[0].properties[0].value
690+
.content
691+
).toBe('0')
692+
expect((codegenNode.consequent as any).props.arguments[1].callee).toBe(
693+
TO_HANDLERS
694+
)
695+
})
676696
})

packages/compiler-core/src/utils.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ import {
2929
TELEPORT,
3030
SUSPENSE,
3131
KEEP_ALIVE,
32-
BASE_TRANSITION
32+
BASE_TRANSITION,
33+
TO_HANDLERS
3334
} from './runtimeHelpers'
3435
import { isString, isObject, hyphenate, extend } from '@vue/shared'
3536

@@ -215,7 +216,7 @@ export function injectProp(
215216
prop: Property,
216217
context: TransformContext
217218
) {
218-
let propsWithInjection: ObjectExpression | CallExpression
219+
let propsWithInjection: ObjectExpression | CallExpression | undefined
219220
const props =
220221
node.type === NodeTypes.VNODE_CALL ? node.props : node.arguments[2]
221222
if (props == null || isString(props)) {
@@ -228,9 +229,17 @@ export function injectProp(
228229
if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {
229230
first.properties.unshift(prop)
230231
} else {
231-
props.arguments.unshift(createObjectExpression([prop]))
232+
if (props.callee === TO_HANDLERS) {
233+
// #2366
234+
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
235+
createObjectExpression([prop]),
236+
props
237+
])
238+
} else {
239+
props.arguments.unshift(createObjectExpression([prop]))
240+
}
232241
}
233-
propsWithInjection = props
242+
!propsWithInjection && (propsWithInjection = props)
234243
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
235244
let alreadyExists = false
236245
// check existing key to avoid overriding user provided keys

0 commit comments

Comments
 (0)