]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(compiler-core): emit error on v-if key usage
authorEvan You <yyx990803@gmail.com>
Tue, 28 Jul 2020 19:18:41 +0000 (15:18 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 28 Jul 2020 19:18:41 +0000 (15:18 -0400)
packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap
packages/compiler-core/__tests__/transforms/vIf.spec.ts
packages/compiler-core/src/errors.ts
packages/compiler-core/src/transforms/vIf.ts

index 7a4b904137070866bd272cfb3e91fc3c26d019c8..def7f945a517e897c3eab44c1d6d39d321e19190 100644 (file)
@@ -145,17 +145,3 @@ return function render(_ctx, _cache) {
   }
 }"
 `;
-
-exports[`compiler: v-if codegen v-if with key 1`] = `
-"const _Vue = Vue
-
-return function render(_ctx, _cache) {
-  with (_ctx) {
-    const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = _Vue
-
-    return ok
-      ? (_openBlock(), _createBlock(\\"div\\", { key: \\"some-key\\" }))
-      : _createCommentVNode(\\"v-if\\", true)
-  }
-}"
-`;
index 44433d84d8cb5c871b0dca74c9fb1b296b5e83e0..9d4619aa8ee753069a81f8d2ed82512a9eb7288e 100644 (file)
@@ -282,6 +282,16 @@ describe('compiler: v-if', () => {
         }
       ])
     })
+
+    test('error on user key', () => {
+      const onError = jest.fn()
+      parseWithIfTransform(`<div v-if="ok" :key="1" />`, { onError })
+      expect(onError.mock.calls[0]).toMatchObject([
+        {
+          code: ErrorCodes.X_V_IF_KEY
+        }
+      ])
+    })
   })
 
   describe('codegen', () => {
@@ -581,18 +591,6 @@ describe('compiler: v-if', () => {
       expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))
     })
 
-    test('v-if with key', () => {
-      const {
-        root,
-        node: { codegenNode }
-      } = parseWithIfTransform(`<div v-if="ok" key="some-key"/>`)
-      expect(codegenNode.consequent).toMatchObject({
-        tag: `"div"`,
-        props: createObjectMatcher({ key: 'some-key' })
-      })
-      expect(generate(root).code).toMatchSnapshot()
-    })
-
     test('with comments', () => {
       const { node } = parseWithIfTransform(`
           <template v-if="ok">
index 63c0bb0951618d71e4043176c145c7e67f8116c0..4af23216335f68a28cfa3f9de06cc003d4e9ade2 100644 (file)
@@ -63,6 +63,7 @@ export const enum ErrorCodes {
 
   // transform errors
   X_V_IF_NO_EXPRESSION,
+  X_V_IF_KEY,
   X_V_ELSE_NO_ADJACENT_IF,
   X_V_FOR_NO_EXPRESSION,
   X_V_FOR_MALFORMED_EXPRESSION,
@@ -135,6 +136,7 @@ export const errorMessages: { [code: number]: string } = {
 
   // transform errors
   [ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
+  [ErrorCodes.X_V_IF_KEY]: `v-if branches must use compiler generated keys.`,
   [ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if.`,
   [ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,
   [ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,
index 491772fca9213cd839b38181321905d90aa7df7c..f22accb303394202708c82b0f55f31a29cba84d1 100644 (file)
@@ -30,7 +30,7 @@ import {
   OPEN_BLOCK,
   TELEPORT
 } from '../runtimeHelpers'
-import { injectProp, findDir } from '../utils'
+import { injectProp, findDir, findProp } from '../utils'
 import { PatchFlags, PatchFlagNames } from '@vue/shared'
 
 export const transformIf = createStructuralDirectiveTransform(
@@ -111,6 +111,11 @@ export function processIf(
     validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
   }
 
+  const userKey = /*#__PURE__*/ findProp(node, 'key')
+  if (userKey) {
+    context.onError(createCompilerError(ErrorCodes.X_V_IF_KEY, userKey.loc))
+  }
+
   if (dir.name === 'if') {
     const branch = createIfBranch(node, dir)
     const ifNode: IfNode = {
@@ -175,13 +180,13 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
 
 function createCodegenNodeForBranch(
   branch: IfBranchNode,
-  index: number,
+  keyIndex: number,
   context: TransformContext
 ): IfConditionalExpression | BlockCodegenNode {
   if (branch.condition) {
     return createConditionalExpression(
       branch.condition,
-      createChildrenCodegenNode(branch, index, context),
+      createChildrenCodegenNode(branch, keyIndex, context),
       // make sure to pass in asBlock: true so that the comment node call
       // closes the current block.
       createCallExpression(context.helper(CREATE_COMMENT), [
@@ -190,19 +195,19 @@ function createCodegenNodeForBranch(
       ])
     ) as IfConditionalExpression
   } else {
-    return createChildrenCodegenNode(branch, index, context)
+    return createChildrenCodegenNode(branch, keyIndex, context)
   }
 }
 
 function createChildrenCodegenNode(
   branch: IfBranchNode,
-  index: number,
+  keyIndex: number,
   context: TransformContext
 ): BlockCodegenNode {
   const { helper } = context
   const keyProperty = createObjectProperty(
     `key`,
-    createSimpleExpression(index + '', false)
+    createSimpleExpression(`${keyIndex}`, false)
   )
   const { children } = branch
   const firstChild = children[0]