fix(compiler-core): avoid duplicate keys in codegen with `v-if` (#6689)

fix #6641
This commit is contained in:
被雨水过滤的空气(Rairn) 2022-11-08 11:04:31 +08:00 committed by GitHub
parent 2a9996cba9
commit 640cfce4ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 12 deletions

View File

@ -628,6 +628,24 @@ describe('compiler: v-if', () => {
expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))
})
// #6631
test('avoid duplicate keys', () => {
const {
node: { codegenNode }
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
const branch1 = codegenNode.consequent as VNodeCall
expect(branch1.props).toMatchObject({
type: NodeTypes.JS_CALL_EXPRESSION,
callee: MERGE_PROPS,
arguments: [
createObjectMatcher({
key: 'custom_key'
}),
{ content: `obj` }
]
})
})
test('with spaces between branches', () => {
const {
node: { codegenNode }

View File

@ -397,7 +397,10 @@ export function injectProp(
// if doesn't override user provided keys
const first = props.arguments[0] as string | JSChildNode
if (!isString(first) && first.type === NodeTypes.JS_OBJECT_EXPRESSION) {
first.properties.unshift(prop)
// #6631
if (!hasProp(prop, first)) {
first.properties.unshift(prop)
}
} else {
if (props.callee === TO_HANDLERS) {
// #2366
@ -411,17 +414,7 @@ export function injectProp(
}
!propsWithInjection && (propsWithInjection = props)
} else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
let alreadyExists = false
// check existing key to avoid overriding user provided keys
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
const propKeyName = prop.key.content
alreadyExists = props.properties.some(
p =>
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
p.key.content === propKeyName
)
}
if (!alreadyExists) {
if (!hasProp(prop, props)) {
props.properties.unshift(prop)
}
propsWithInjection = props
@ -453,6 +446,20 @@ export function injectProp(
}
}
// check existing key to avoid overriding user provided keys
function hasProp(prop: Property, props: ObjectExpression) {
let result = false
if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) {
const propKeyName = prop.key.content
result = props.properties.some(
p =>
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
p.key.content === propKeyName
)
}
return result
}
export function toValidAssetId(
name: string,
type: 'component' | 'directive' | 'filter'