mirror of https://github.com/vuejs/core.git
Merge bbea42f522
into 56be3dd4db
This commit is contained in:
commit
56a83193f7
|
@ -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', () => {
|
||||
|
|
|
@ -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'`, () => {
|
||||
|
|
|
@ -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.`,
|
||||
|
|
|
@ -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, [
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue