This commit is contained in:
linzhe 2025-05-05 20:38:29 +00:00 committed by GitHub
commit 56a83193f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 152 additions and 2 deletions

View File

@ -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('<Comp v-for="Comp of list" />', {
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('<Comp v-for="Comp of list" />', {
onError: onError2,
})
expect(onError2).toHaveBeenCalledTimes(1)
expect(onError2).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_INVALID_PARAMETER_NAME,
}),
)
const onError3 = vi.fn()
parseWithForTransform(
`<div v-for="Comp of list">
<div>
<Comp>{{ Comp }}</Comp>
</div>
</div>`,
{
onError: onError3,
},
)
expect(onError3).toHaveBeenCalledTimes(1)
expect(onError3).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_INVALID_PARAMETER_NAME,
}),
)
})
})
describe('source location', () => {

View File

@ -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(
`<CompB>
<template #default="Comp">
<Comp>{{Comp1}}</Comp>
</template>
</CompB>`,
{
onError: onError1,
},
)
expect(onError1).toHaveBeenCalledTimes(1)
expect(onError1).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_INVALID_PARAMETER_NAME,
}),
)
const onError2 = vi.fn()
parseWithSlots(
`<CompB>
<template #default="{ Comp }">
<Comp>{{Comp1}}</Comp>
</template>
</CompB>`,
{
onError: onError2,
prefixIdentifiers: true,
},
)
expect(onError2).toHaveBeenCalledTimes(1)
expect(onError2).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_INVALID_PARAMETER_NAME,
}),
)
})
})
describe(`with whitespace: 'preserve'`, () => {

View File

@ -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<ErrorCodes, string> = {
'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.`,

View File

@ -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, [

View File

@ -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(

View File

@ -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),
)
}
}

View File

@ -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,