diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
index 94f75f2a63b..6989dc8994d 100644
--- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
@@ -253,6 +253,20 @@ describe('compiler: v-for', () => {
)
})
+ test('key property missing expression', () => {
+ const onError = vi.fn()
+ parseWithForTransform('', {
+ onError,
+ })
+
+ expect(onError).toHaveBeenCalledTimes(1)
+ expect(onError).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_V_BIND_NO_EXPRESSION,
+ }),
+ )
+ })
+
test('missing source', () => {
const onError = vi.fn()
parseWithForTransform('', { onError })
diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
index 2c2fedab0d5..4432daec020 100644
--- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts
@@ -323,6 +323,32 @@ describe('compiler: v-if', () => {
},
])
})
+
+ test('error on template key', () => {
+ const onError = vi.fn()
+ // dynamic
+ parseWithIfTransform(
+ ``,
+ { onError },
+ )
+ expect(onError.mock.calls[0]).toMatchObject([
+ {
+ code: ErrorCodes.X_V_IF_TEMPLATE_USER_DEFINED_KEY,
+ },
+ ])
+ // static
+ parseWithIfTransform(
+ ``,
+ {
+ onError,
+ },
+ )
+ expect(onError.mock.calls[1]).toMatchObject([
+ {
+ code: ErrorCodes.X_V_IF_TEMPLATE_USER_DEFINED_KEY,
+ },
+ ])
+ })
})
describe('codegen', () => {
diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts
index a536392b9a3..b6f123b92ea 100644
--- a/packages/compiler-core/src/errors.ts
+++ b/packages/compiler-core/src/errors.ts
@@ -73,6 +73,7 @@ export enum ErrorCodes {
// transform errors
X_V_IF_NO_EXPRESSION,
X_V_IF_SAME_KEY,
+ X_V_IF_TEMPLATE_USER_DEFINED_KEY,
X_V_ELSE_NO_ADJACENT_IF,
X_V_FOR_NO_EXPRESSION,
X_V_FOR_MALFORMED_EXPRESSION,
@@ -155,6 +156,7 @@ export const errorMessages: Record = {
// transform errors
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
[ErrorCodes.X_V_IF_SAME_KEY]: `v-if/else branches must use unique keys.`,
+ [ErrorCodes.X_V_IF_TEMPLATE_USER_DEFINED_KEY]: `v-if/else the template key is internally set.`,
[ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,
[ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,
[ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,
diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts
index 16c48ede067..409f29f8b5e 100644
--- a/packages/compiler-core/src/transforms/vFor.ts
+++ b/packages/compiler-core/src/transforms/vFor.ts
@@ -93,6 +93,14 @@ export const transformFor = createStructuralDirectiveTransform(
context,
)
}
+ if (
+ keyExp &&
+ keyExp.type === NodeTypes.SIMPLE_EXPRESSION &&
+ !keyExp.content.trim()
+ )
+ context.onError(
+ createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, keyProp.loc),
+ )
}
const isStableFragment =
diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts
index a6437f89c63..abba311587d 100644
--- a/packages/compiler-core/src/transforms/vIf.ts
+++ b/packages/compiler-core/src/transforms/vIf.ts
@@ -30,13 +30,31 @@ import { ErrorCodes, createCompilerError } from '../errors'
import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression'
import { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers'
-import { findDir, findProp, getMemoedVNodeCall, injectProp } from '../utils'
+import {
+ findDir,
+ findProp,
+ getMemoedVNodeCall,
+ injectProp,
+ isTemplateNode,
+} from '../utils'
import { PatchFlagNames, PatchFlags } from '@vue/shared'
export const transformIf = createStructuralDirectiveTransform(
/^(if|else|else-if)$/,
(node, dir, context) => {
return processIf(node, dir, context, (ifNode, branch, isRoot) => {
+ const isTemplate = isTemplateNode(node)
+ if ((__DEV__ || !__BROWSER__) && isTemplate) {
+ const keyProp = findProp(node, `key`, false, true)
+ if (keyProp) {
+ context.onError(
+ createCompilerError(
+ ErrorCodes.X_V_IF_TEMPLATE_USER_DEFINED_KEY,
+ keyProp.loc,
+ ),
+ )
+ }
+ }
// #1587: We need to dynamically increment the key based on the current
// node's sibling nodes, since chained v-if/else branches are
// rendered at the same depth
diff --git a/packages/compiler-dom/src/errors.ts b/packages/compiler-dom/src/errors.ts
index b47624840ab..5bffa4e53a1 100644
--- a/packages/compiler-dom/src/errors.ts
+++ b/packages/compiler-dom/src/errors.ts
@@ -21,7 +21,7 @@ export function createDOMCompilerError(
}
export enum DOMErrorCodes {
- X_V_HTML_NO_EXPRESSION = 53 /* ErrorCodes.__EXTEND_POINT__ */,
+ X_V_HTML_NO_EXPRESSION = 54 /* ErrorCodes.__EXTEND_POINT__ */,
X_V_HTML_WITH_CHILDREN,
X_V_TEXT_NO_EXPRESSION,
X_V_TEXT_WITH_CHILDREN,