Skip to content

Commit 640cfce

Browse files
authoredNov 8, 2022
fix(compiler-core): avoid duplicate keys in codegen with v-if (#6689)
fix #6641
1 parent 2a9996c commit 640cfce

File tree

2 files changed

+37
-12
lines changed

2 files changed

+37
-12
lines changed
 

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

+18
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,24 @@ describe('compiler: v-if', () => {
628628
expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))
629629
})
630630

631+
// #6631
632+
test('avoid duplicate keys', () => {
633+
const {
634+
node: { codegenNode }
635+
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
636+
const branch1 = codegenNode.consequent as VNodeCall
637+
expect(branch1.props).toMatchObject({
638+
type: NodeTypes.JS_CALL_EXPRESSION,
639+
callee: MERGE_PROPS,
640+
arguments: [
641+
createObjectMatcher({
642+
key: 'custom_key'
643+
}),
644+
{ content: `obj` }
645+
]
646+
})
647+
})
648+
631649
test('with spaces between branches', () => {
632650
const {
633651
node: { codegenNode }

‎packages/compiler-core/src/utils.ts

+19-12
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ export function injectProp(
397397
// if doesn't override user provided keys
398398
const first = props.arguments[0] as string | JSChildNode
399399
if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {
400-
first.properties.unshift(prop)
400+
// #6631
401+
if (!hasProp(prop, first)) {
402+
first.properties.unshift(prop)
403+
}
401404
} else {
402405
if (props.callee === TO_HANDLERS) {
403406
// #2366
@@ -411,17 +414,7 @@ export function injectProp(
411414
}
412415
!propsWithInjection && (propsWithInjection = props)
413416
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
414-
let alreadyExists = false
415-
// check existing key to avoid overriding user provided keys
416-
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
417-
const propKeyName = prop.key.content
418-
alreadyExists = props.properties.some(
419-
p =>
420-
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
421-
p.key.content === propKeyName
422-
)
423-
}
424-
if (!alreadyExists) {
417+
if (!hasProp(prop, props)) {
425418
props.properties.unshift(prop)
426419
}
427420
propsWithInjection = props
@@ -453,6 +446,20 @@ export function injectProp(
453446
}
454447
}
455448

449+
// check existing key to avoid overriding user provided keys
450+
function hasProp(prop: Property, props: ObjectExpression) {
451+
let result = false
452+
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
453+
const propKeyName = prop.key.content
454+
result = props.properties.some(
455+
p =>
456+
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
457+
p.key.content === propKeyName
458+
)
459+
}
460+
return result
461+
}
462+
456463
export function toValidAssetId(
457464
name: string,
458465
type: 'component' | 'directive' | 'filter'

0 commit comments

Comments
 (0)
Please sign in to comment.