diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
index fead2476a..b80bd9c20 100644
--- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
@@ -17,7 +17,7 @@ import {
type SimpleExpressionNode,
} from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
-import { type CompilerOptions, generate } from '../../src'
+import { BindingTypes, type CompilerOptions, generate } from '../../src'
import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
import { PatchFlags } from '@vue/shared'
import { createObjectMatcher } from '../testUtils'
@@ -320,6 +320,51 @@ describe('compiler: v-for', () => {
)
expect(onError).toHaveBeenCalledTimes(1)
})
+
+ test('v-for + the parameter name is the same as the component name.', () => {
+ const onError1 = vi.fn()
+ parseWithForTransform('', {
+ onError: onError1,
+ bindingMetadata: {
+ Comp: BindingTypes.SETUP_CONST,
+ },
+ })
+ expect(onError1).toHaveBeenCalledTimes(1)
+ expect(onError1).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_INVALID_PARAMETER_NAME,
+ }),
+ )
+
+ const onError2 = vi.fn()
+ parseWithForTransform('', {
+ onError: onError2,
+ })
+ expect(onError2).toHaveBeenCalledTimes(1)
+ expect(onError2).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_INVALID_PARAMETER_NAME,
+ }),
+ )
+
+ const onError3 = vi.fn()
+ parseWithForTransform(
+ `
`,
+ {
+ onError: onError3,
+ },
+ )
+ expect(onError3).toHaveBeenCalledTimes(1)
+ expect(onError3).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_INVALID_PARAMETER_NAME,
+ }),
+ )
+ })
})
describe('source location', () => {
diff --git a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts
index 4766c2ca9..c02e81686 100644
--- a/packages/compiler-core/__tests__/transforms/vSlot.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vSlot.spec.ts
@@ -928,6 +928,45 @@ describe('compiler: transform component slots', () => {
},
})
})
+
+ test('v-slot + the parameter name is the same as the component name.', () => {
+ const onError1 = vi.fn()
+ parseWithSlots(
+ `
+
+ {{Comp1}}
+
+ `,
+ {
+ onError: onError1,
+ },
+ )
+ expect(onError1).toHaveBeenCalledTimes(1)
+ expect(onError1).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_INVALID_PARAMETER_NAME,
+ }),
+ )
+
+ const onError2 = vi.fn()
+ parseWithSlots(
+ `
+
+ {{Comp1}}
+
+ `,
+ {
+ onError: onError2,
+ prefixIdentifiers: true,
+ },
+ )
+ expect(onError2).toHaveBeenCalledTimes(1)
+ expect(onError2).toHaveBeenCalledWith(
+ expect.objectContaining({
+ code: ErrorCodes.X_INVALID_PARAMETER_NAME,
+ }),
+ )
+ })
})
describe(`with whitespace: 'preserve'`, () => {
diff --git a/packages/compiler-core/src/errors.ts b/packages/compiler-core/src/errors.ts
index 58e113ab1..1c60dfe42 100644
--- a/packages/compiler-core/src/errors.ts
+++ b/packages/compiler-core/src/errors.ts
@@ -69,6 +69,7 @@ export enum ErrorCodes {
X_MISSING_INTERPOLATION_END,
X_MISSING_DIRECTIVE_NAME,
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
+ X_INVALID_PARAMETER_NAME,
// transform errors
X_V_IF_NO_EXPRESSION,
@@ -151,6 +152,7 @@ export const errorMessages: Record = {
'End bracket for dynamic directive argument was not found. ' +
'Note that dynamic directive argument cannot contain spaces.',
[ErrorCodes.X_MISSING_DIRECTIVE_NAME]: 'Legal directive name was expected.',
+ [ErrorCodes.X_INVALID_PARAMETER_NAME]: `avoid using component name as parameter name.`,
// transform errors
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts
index 0dca0ba9a..c82f45370 100644
--- a/packages/compiler-core/src/transforms/vFor.ts
+++ b/packages/compiler-core/src/transforms/vFor.ts
@@ -33,6 +33,7 @@ import {
} from '../ast'
import { ErrorCodes, createCompilerError } from '../errors'
import {
+ checkParameterName,
findDir,
findProp,
injectProp,
@@ -217,6 +218,14 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
}
}
+ if (__DEV__ || !__BROWSER__) {
+ checkParameterName(
+ forNode.parseResult.value,
+ childBlock as VNodeCall,
+ context,
+ )
+ }
+
if (memo) {
const loop = createFunctionExpression(
createForLoopParams(forNode.parseResult, [
diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts
index 28625439a..8549d87fd 100644
--- a/packages/compiler-core/src/transforms/vSlot.ts
+++ b/packages/compiler-core/src/transforms/vSlot.ts
@@ -24,6 +24,7 @@ import type { NodeTransform, TransformContext } from '../transform'
import { ErrorCodes, createCompilerError } from '../errors'
import {
assert,
+ checkParameterName,
findDir,
hasScopeRef,
isStaticExp,
@@ -175,6 +176,10 @@ export function buildSlots(
continue
}
+ if (__DEV__ || !__BROWSER__) {
+ checkParameterName(slotDir.exp, slotElement, context)
+ }
+
if (onComponentSlot) {
// already has on-component slot - this is incorrect usage.
context.onError(
diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts
index b49d70bb2..2ca6cdf32 100644
--- a/packages/compiler-core/src/utils.ts
+++ b/packages/compiler-core/src/utils.ts
@@ -2,6 +2,7 @@ import {
type BlockCodegenNode,
type CacheExpression,
type CallExpression,
+ type CompoundExpressionNode,
type DirectiveNode,
type ElementNode,
ElementTypes,
@@ -42,6 +43,7 @@ import type { PropsExpression } from './transforms/transformElement'
import { parseExpression } from '@babel/parser'
import type { Expression, Node } from '@babel/types'
import { unwrapTSNode } from './babelUtils'
+import { ErrorCodes, createCompilerError } from './errors'
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic
@@ -564,3 +566,51 @@ export function getMemoedVNodeCall(
}
export const forAliasRE: RegExp = /([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/
+
+export function findComponentTagNode(
+ node: VNodeCall | ElementNode,
+ name: string,
+): VNodeCall | ElementNode | undefined {
+ if (
+ node.tag === name ||
+ node.tag === `$setup["${name}"]` ||
+ node.tag === `_component_${name}`
+ )
+ return node
+ if (node.children) {
+ const children = node.children as TemplateChildNode[]
+ for (let i = 0; i < children.length; i++) {
+ const child = children[i]
+ if ((child as ElementNode).tag) {
+ const targetTag = findComponentTagNode(child as ElementNode, name)
+ if (targetTag) return targetTag
+ }
+ }
+ }
+}
+
+export function checkParameterName(
+ exp: ExpressionNode | undefined,
+ blockNode: VNodeCall | ElementNode,
+ context: TransformContext,
+): void {
+ if (
+ exp &&
+ findComponentTagNode(blockNode, (exp as SimpleExpressionNode).content)
+ ) {
+ context.onError(
+ createCompilerError(ErrorCodes.X_INVALID_PARAMETER_NAME, exp.loc),
+ )
+ }
+
+ let identifiers: CompoundExpressionNode['identifiers'] = []
+ if (exp && (exp as CompoundExpressionNode).identifiers) {
+ identifiers = (exp as CompoundExpressionNode).identifiers
+ }
+
+ if (identifiers!.some(i => !!findComponentTagNode(blockNode, i))) {
+ context.onError(
+ createCompilerError(ErrorCodes.X_INVALID_PARAMETER_NAME, exp!.loc),
+ )
+ }
+}
diff --git a/packages/compiler-dom/src/errors.ts b/packages/compiler-dom/src/errors.ts
index b47624840..5bffa4e53 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,