export interface ComponentNode extends BaseElementNode {
tagType: ElementTypes.COMPONENT
+ slots: SlotsExpression
+ hasDynamicSlots: boolean
codegenNode:
| VNodeCall
| CacheExpression // when cached by v-once
vnodeTag !== KEEP_ALIVE
if (shouldBuildAsSlots) {
- const { slots, hasDynamicSlots } = buildSlots(node, context)
+ const { slots, hasDynamicSlots } = buildSlots(
+ node as ComponentNode,
+ context,
+ )
vnodeChildren = slots
if (hasDynamicSlots) {
patchFlag |= PatchFlags.DYNAMIC_SLOTS
NodeTypes,
type SimpleExpressionNode,
type SkipNode,
- type SlotsExpression,
type TemplateChildNode,
createConditionalExpression,
createSimpleExpression,
// if not found, throw an error
if (node.tagType === ElementTypes.COMPONENT) {
const { slots } = buildSlots(node, context)
- const genChildren = slots as SlotsExpression
- if (genChildren.type === NodeTypes.JS_OBJECT_EXPRESSION) {
- const prop = genChildren.properties.find(
+ if (slots.type === NodeTypes.JS_OBJECT_EXPRESSION) {
+ const prop = slots.properties.find(
p =>
p.type === NodeTypes.JS_PROPERTY &&
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
import {
type CallExpression,
+ type ComponentNode,
type ConditionalExpression,
type DirectiveNode,
- type ElementNode,
ElementTypes,
type ExpressionNode,
type FunctionExpression,
// Instead of being a DirectiveTransform, v-slot processing is called during
// transformElement to build the slots object for a component.
export function buildSlots(
- node: ElementNode,
+ node: ComponentNode,
context: TransformContext,
buildSlotFn: SlotFnBuilder = buildClientSlotFn,
): {
slots: SlotsExpression
hasDynamicSlots: boolean
} {
+ // return early if slots are already built to avoid duplication
+ if (node.slots) {
+ return {
+ slots: node.slots,
+ hasDynamicSlots: node.hasDynamicSlots,
+ }
+ }
context.helper(WITH_CTX)
const { children, loc } = node
]) as SlotsExpression
}
+ node.slots = slots
+ node.hasDynamicSlots = hasDynamicSlots
return {
slots,
hasDynamicSlots,