From 640cfce4ff808fdfc419058f39a2ff4874a25899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E6=B0=94=28Rairn=29?= <958414905@qq.com> Date: Tue, 8 Nov 2022 11:04:31 +0800 Subject: [PATCH] fix(compiler-core): avoid duplicate keys in codegen with `v-if` (#6689) fix #6641 --- .../__tests__/transforms/vIf.spec.ts | 18 +++++++++++ packages/compiler-core/src/utils.ts | 31 ++++++++++++------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts index 5c36885670f..9ccce811486 100644 --- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts @@ -628,6 +628,24 @@ describe('compiler: v-if', () => { expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` })) }) + // #6631 + test('avoid duplicate keys', () => { + const { + node: { codegenNode } + } = parseWithIfTransform(`
`) + 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 } diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index c9e310fe089..6a6b03a2ead 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -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'