Browse Source

fix(compiler-core): avoid override user keys when injecting branch key (#630)

Ruijia Tang 6 years ago
parent
commit
aca2c2a81e

+ 14 - 0
packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap

@@ -105,3 +105,17 @@ return function render() {
   }
 }"
 `;
+
+exports[`compiler: v-if codegen v-if with key 1`] = `
+"const _Vue = Vue
+
+return function render() {
+  with (this) {
+    const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = _Vue
+    
+    return (_openBlock(), ok
+      ? _createBlock(\\"div\\", { key: \\"some-key\\" })
+      : _createCommentVNode(\\"v-if\\", true))
+  }
+}"
+`;

+ 14 - 0
packages/compiler-core/__tests__/transforms/vIf.spec.ts

@@ -530,6 +530,20 @@ describe('compiler: v-if', () => {
       )
     })
 
+    test('v-if with key', () => {
+      const {
+        root,
+        node: { codegenNode }
+      } = parseWithIfTransform(`<div v-if="ok" key="some-key"/>`)
+      const branch1 = (codegenNode.expressions[1] as ConditionalExpression)
+        .consequent as CallExpression
+      expect(branch1.arguments).toMatchObject([
+        `"div"`,
+        createObjectMatcher({ key: 'some-key' })
+      ])
+      expect(generate(root).code).toMatchSnapshot()
+    })
+
     test.todo('with comments')
   })
 })

+ 12 - 1
packages/compiler-core/src/utils.ts

@@ -253,7 +253,18 @@ export function injectProp(
     }
     propsWithInjection = props
   } else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) {
-    props.properties.unshift(prop)
+    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) {
+      props.properties.unshift(prop)
+    }
     propsWithInjection = props
   } else {
     // single v-bind with expression, return a merged replacement