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,
|
type SimpleExpressionNode,
|
||||||
} from '../../src/ast'
|
} from '../../src/ast'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
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 { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { createObjectMatcher } from '../testUtils'
|
import { createObjectMatcher } from '../testUtils'
|
||||||
|
@ -320,6 +320,51 @@ describe('compiler: v-for', () => {
|
||||||
)
|
)
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
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', () => {
|
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'`, () => {
|
describe(`with whitespace: 'preserve'`, () => {
|
||||||
|
|
|
@ -69,6 +69,7 @@ export enum ErrorCodes {
|
||||||
X_MISSING_INTERPOLATION_END,
|
X_MISSING_INTERPOLATION_END,
|
||||||
X_MISSING_DIRECTIVE_NAME,
|
X_MISSING_DIRECTIVE_NAME,
|
||||||
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
|
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
|
||||||
|
X_INVALID_PARAMETER_NAME,
|
||||||
|
|
||||||
// transform errors
|
// transform errors
|
||||||
X_V_IF_NO_EXPRESSION,
|
X_V_IF_NO_EXPRESSION,
|
||||||
|
@ -151,6 +152,7 @@ export const errorMessages: Record<ErrorCodes, string> = {
|
||||||
'End bracket for dynamic directive argument was not found. ' +
|
'End bracket for dynamic directive argument was not found. ' +
|
||||||
'Note that dynamic directive argument cannot contain spaces.',
|
'Note that dynamic directive argument cannot contain spaces.',
|
||||||
[ErrorCodes.X_MISSING_DIRECTIVE_NAME]: 'Legal directive name was expected.',
|
[ErrorCodes.X_MISSING_DIRECTIVE_NAME]: 'Legal directive name was expected.',
|
||||||
|
[ErrorCodes.X_INVALID_PARAMETER_NAME]: `avoid using component name as parameter name.`,
|
||||||
|
|
||||||
// transform errors
|
// transform errors
|
||||||
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
|
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { ErrorCodes, createCompilerError } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
|
checkParameterName,
|
||||||
findDir,
|
findDir,
|
||||||
findProp,
|
findProp,
|
||||||
injectProp,
|
injectProp,
|
||||||
|
@ -217,6 +218,14 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__DEV__ || !__BROWSER__) {
|
||||||
|
checkParameterName(
|
||||||
|
forNode.parseResult.value,
|
||||||
|
childBlock as VNodeCall,
|
||||||
|
context,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (memo) {
|
if (memo) {
|
||||||
const loop = createFunctionExpression(
|
const loop = createFunctionExpression(
|
||||||
createForLoopParams(forNode.parseResult, [
|
createForLoopParams(forNode.parseResult, [
|
||||||
|
|
|
@ -24,6 +24,7 @@ import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import { ErrorCodes, createCompilerError } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
assert,
|
assert,
|
||||||
|
checkParameterName,
|
||||||
findDir,
|
findDir,
|
||||||
hasScopeRef,
|
hasScopeRef,
|
||||||
isStaticExp,
|
isStaticExp,
|
||||||
|
@ -175,6 +176,10 @@ export function buildSlots(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__DEV__ || !__BROWSER__) {
|
||||||
|
checkParameterName(slotDir.exp, slotElement, context)
|
||||||
|
}
|
||||||
|
|
||||||
if (onComponentSlot) {
|
if (onComponentSlot) {
|
||||||
// already has on-component slot - this is incorrect usage.
|
// already has on-component slot - this is incorrect usage.
|
||||||
context.onError(
|
context.onError(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
type BlockCodegenNode,
|
type BlockCodegenNode,
|
||||||
type CacheExpression,
|
type CacheExpression,
|
||||||
type CallExpression,
|
type CallExpression,
|
||||||
|
type CompoundExpressionNode,
|
||||||
type DirectiveNode,
|
type DirectiveNode,
|
||||||
type ElementNode,
|
type ElementNode,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
|
@ -42,6 +43,7 @@ import type { PropsExpression } from './transforms/transformElement'
|
||||||
import { parseExpression } from '@babel/parser'
|
import { parseExpression } from '@babel/parser'
|
||||||
import type { Expression, Node } from '@babel/types'
|
import type { Expression, Node } from '@babel/types'
|
||||||
import { unwrapTSNode } from './babelUtils'
|
import { unwrapTSNode } from './babelUtils'
|
||||||
|
import { ErrorCodes, createCompilerError } from './errors'
|
||||||
|
|
||||||
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||||
p.type === NodeTypes.SIMPLE_EXPRESSION && p.isStatic
|
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 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 {
|
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_HTML_WITH_CHILDREN,
|
||||||
X_V_TEXT_NO_EXPRESSION,
|
X_V_TEXT_NO_EXPRESSION,
|
||||||
X_V_TEXT_WITH_CHILDREN,
|
X_V_TEXT_WITH_CHILDREN,
|
||||||
|
|
Loading…
Reference in New Issue