( node: ElementNode, context: TransformContext, buildSlotFn: SlotFnBuilder = buildClientSlotFn, )
| 116 | // Instead of being a DirectiveTransform, v-slot processing is called during |
| 117 | // transformElement to build the slots object for a component. |
| 118 | export function buildSlots( |
| 119 | node: ElementNode, |
| 120 | context: TransformContext, |
| 121 | buildSlotFn: SlotFnBuilder = buildClientSlotFn, |
| 122 | ): { |
| 123 | slots: SlotsExpression |
| 124 | hasDynamicSlots: boolean |
| 125 | } { |
| 126 | context.helper(WITH_CTX) |
| 127 | |
| 128 | const { children, loc } = node |
| 129 | const slotsProperties: Property[] = [] |
| 130 | const dynamicSlots: (ConditionalExpression | CallExpression)[] = [] |
| 131 | |
| 132 | // If the slot is inside a v-for or another v-slot, force it to be dynamic |
| 133 | // since it likely uses a scope variable. |
| 134 | let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0 |
| 135 | // with `prefixIdentifiers: true`, this can be further optimized to make |
| 136 | // it dynamic when |
| 137 | // 1. the slot arg or exp uses the scope variables. |
| 138 | // 2. the slot children use the scope variables. |
| 139 | if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) { |
| 140 | hasDynamicSlots = |
| 141 | node.props.some( |
| 142 | prop => |
| 143 | isVSlot(prop) && |
| 144 | (hasScopeRef(prop.arg, context.identifiers) || |
| 145 | hasScopeRef(prop.exp, context.identifiers)), |
| 146 | ) || children.some(child => hasScopeRef(child, context.identifiers)) |
| 147 | } |
| 148 | |
| 149 | // 1. Check for slot with slotProps on component itself. |
| 150 | // <Comp v-slot="{ prop }"/> |
| 151 | const onComponentSlot = findDir(node, 'slot', true) |
| 152 | if (onComponentSlot) { |
| 153 | const { arg, exp } = onComponentSlot |
| 154 | if (arg && !isStaticExp(arg)) { |
| 155 | hasDynamicSlots = true |
| 156 | } |
| 157 | slotsProperties.push( |
| 158 | createObjectProperty( |
| 159 | arg || createSimpleExpression('default', true), |
| 160 | buildSlotFn(exp, undefined, children, loc), |
| 161 | ), |
| 162 | ) |
| 163 | } |
| 164 | |
| 165 | // 2. Iterate through children and check for template slots |
| 166 | // <template v-slot:foo="{ prop }"> |
| 167 | let hasTemplateSlots = false |
| 168 | let hasNamedDefaultSlot = false |
| 169 | const implicitDefaultChildren: TemplateChildNode[] = [] |
| 170 | const seenSlotNames = new Set<string>() |
| 171 | let conditionalBranchIndex = 0 |
| 172 | |
| 173 | for (let i = 0; i < children.length; i++) { |
| 174 | const slotElement = children[i] |
| 175 | let slotDir |
no test coverage detected