test(compiler): test v-slot transform
This commit is contained in:
@@ -73,6 +73,7 @@ export const enum ErrorCodes {
|
||||
X_MIXED_SLOT_USAGE,
|
||||
X_DUPLICATE_SLOT_NAMES,
|
||||
X_EXTRANEOUS_NON_SLOT_CHILDREN,
|
||||
X_MISPLACED_V_SLOT,
|
||||
|
||||
// generic errors
|
||||
X_PREFIX_ID_NOT_SUPPORTED,
|
||||
@@ -155,6 +156,8 @@ export const errorMessages: { [code: number]: string } = {
|
||||
[ErrorCodes.X_EXTRANEOUS_NON_SLOT_CHILDREN]:
|
||||
`Extraneous children found when component has explicit slots. ` +
|
||||
`These children will be ignored.`,
|
||||
[ErrorCodes.X_MISPLACED_V_SLOT]: `v-slot can only be used on components or <template> tags.`,
|
||||
|
||||
// generic errors
|
||||
[ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED]: `"prefixIdentifiers" option is not supported in this build of compiler.`,
|
||||
[ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED]: `ES module mode is not supported in this build of compiler.`
|
||||
|
||||
@@ -384,6 +384,11 @@ function parseTag(
|
||||
const props = []
|
||||
const ns = context.options.getNamespace(tag, parent)
|
||||
|
||||
let tagType = ElementTypes.ELEMENT
|
||||
if (tag === 'slot') tagType = ElementTypes.SLOT
|
||||
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
|
||||
else if (/[A-Z-]/.test(tag)) tagType = ElementTypes.COMPONENT
|
||||
|
||||
advanceBy(context, match[0].length)
|
||||
advanceSpaces(context)
|
||||
|
||||
@@ -427,12 +432,6 @@ function parseTag(
|
||||
advanceBy(context, isSelfClosing ? 2 : 1)
|
||||
}
|
||||
|
||||
let tagType = ElementTypes.ELEMENT
|
||||
|
||||
if (tag === 'slot') tagType = ElementTypes.SLOT
|
||||
else if (tag === 'template') tagType = ElementTypes.TEMPLATE
|
||||
else if (/[A-Z-]/.test(tag)) tagType = ElementTypes.COMPONENT
|
||||
|
||||
return {
|
||||
type: NodeTypes.ELEMENT,
|
||||
ns,
|
||||
|
||||
@@ -39,7 +39,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||
node.tagType === ElementTypes.COMPONENT
|
||||
) {
|
||||
const isComponent = node.tagType === ElementTypes.COMPONENT
|
||||
const hasProps = node.props.length > 0
|
||||
let hasProps = node.props.length > 0
|
||||
const hasChildren = node.children.length > 0
|
||||
let runtimeDirectives: DirectiveNode[] | undefined
|
||||
let componentIdentifier: string | undefined
|
||||
@@ -58,9 +58,18 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||
]
|
||||
// props
|
||||
if (hasProps) {
|
||||
const { props, directives } = buildProps(node.props, node.loc, context)
|
||||
args.push(props)
|
||||
const { props, directives } = buildProps(
|
||||
node.props,
|
||||
node.loc,
|
||||
context,
|
||||
isComponent
|
||||
)
|
||||
runtimeDirectives = directives
|
||||
if (!props) {
|
||||
hasProps = false
|
||||
} else {
|
||||
args.push(props)
|
||||
}
|
||||
}
|
||||
// children
|
||||
if (hasChildren) {
|
||||
@@ -104,9 +113,10 @@ type PropsExpression = ObjectExpression | CallExpression | ExpressionNode
|
||||
export function buildProps(
|
||||
props: ElementNode['props'],
|
||||
elementLoc: SourceLocation,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
isComponent: boolean = false
|
||||
): {
|
||||
props: PropsExpression
|
||||
props: PropsExpression | undefined
|
||||
directives: DirectiveNode[]
|
||||
} {
|
||||
let isStatic = true
|
||||
@@ -141,6 +151,11 @@ export function buildProps(
|
||||
|
||||
// skip v-slot - it is handled by its dedicated transform.
|
||||
if (name === 'slot') {
|
||||
if (!isComponent) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_MISPLACED_V_SLOT, loc)
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -197,7 +212,7 @@ export function buildProps(
|
||||
}
|
||||
}
|
||||
|
||||
let propsExpression: PropsExpression
|
||||
let propsExpression: PropsExpression | undefined = undefined
|
||||
|
||||
// has v-bind="object" or v-on="object", wrap with mergeProps
|
||||
if (mergeArgs.length) {
|
||||
@@ -216,7 +231,7 @@ export function buildProps(
|
||||
// single v-bind with nothing else - no need for a mergeProps call
|
||||
propsExpression = mergeArgs[0]
|
||||
}
|
||||
} else {
|
||||
} else if (properties.length) {
|
||||
propsExpression = createObjectExpression(
|
||||
dedupeProperties(properties),
|
||||
elementLoc
|
||||
@@ -224,7 +239,7 @@ export function buildProps(
|
||||
}
|
||||
|
||||
// hoist the object if it's fully static
|
||||
if (isStatic) {
|
||||
if (isStatic && propsExpression) {
|
||||
propsExpression = context.hoist(propsExpression)
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||
nameIndex > -1
|
||||
? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1))
|
||||
: props
|
||||
const hasProps = propsWithoutName.length
|
||||
let hasProps = propsWithoutName.length > 0
|
||||
if (hasProps) {
|
||||
const { props: propsExpression, directives } = buildProps(
|
||||
propsWithoutName,
|
||||
@@ -79,7 +79,11 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||
)
|
||||
)
|
||||
}
|
||||
slotArgs.push(propsExpression)
|
||||
if (propsExpression) {
|
||||
slotArgs.push(propsExpression)
|
||||
} else {
|
||||
hasProps = false
|
||||
}
|
||||
}
|
||||
|
||||
if (children.length) {
|
||||
|
||||
Reference in New Issue
Block a user