Skip to content

Commit

Permalink
fix(compiler-core): properly track scope vars in v-for + slot
Browse files Browse the repository at this point in the history
chore: improve code

chore: improve code

chore: improve code
  • Loading branch information
edison1105 committed Nov 21, 2022
1 parent e3bc21f commit 61299d6
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 12 deletions.
20 changes: 14 additions & 6 deletions packages/compiler-core/src/transforms/vSlot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ export const trackVForSlotScopes: NodeTransform = (node, context) => {

export type SlotFnBuilder = (
slotProps: ExpressionNode | undefined,
vForProps: ExpressionNode | undefined,
slotChildren: TemplateChildNode[],
loc: SourceLocation
) => FunctionExpression

const buildClientSlotFn: SlotFnBuilder = (props, children, loc) =>
const buildClientSlotFn: SlotFnBuilder = (props, _vFor, children, loc) =>
createFunctionExpression(
props,
children,
Expand Down Expand Up @@ -138,6 +139,9 @@ export function buildSlots(
hasDynamicSlots = hasScopeRef(node, context.identifiers)
}

let vFor: DirectiveNode | undefined
let vForProps: ExpressionNode | undefined

// 1. Check for slot with slotProps on component itself.
// <Comp v-slot="{ prop }"/>
const onComponentSlot = findDir(node, 'slot', true)
Expand All @@ -146,10 +150,12 @@ export function buildSlots(
if (arg && !isStaticExp(arg)) {
hasDynamicSlots = true
}
vFor = findDir(node, 'for')
if (vFor) vForProps = vFor.exp
slotsProperties.push(
createObjectProperty(
arg || createSimpleExpression('default', true),
buildSlotFn(exp, children, loc)
buildSlotFn(exp, vForProps, children, loc)
)
)
}
Expand Down Expand Up @@ -201,11 +207,13 @@ export function buildSlots(
hasDynamicSlots = true
}

const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc)
vFor = findDir(slotElement, 'for')
if (vFor) vForProps = vFor.exp
const slotFunction = buildSlotFn(slotProps, vForProps, slotChildren, slotLoc)

// check if this slot is conditional (v-if/v-for)
let vIf: DirectiveNode | undefined
let vElse: DirectiveNode | undefined
let vFor: DirectiveNode | undefined
if ((vIf = findDir(slotElement, 'if'))) {
hasDynamicSlots = true
dynamicSlots.push(
Expand Down Expand Up @@ -257,7 +265,7 @@ export function buildSlots(
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElse.loc)
)
}
} else if ((vFor = findDir(slotElement, 'for'))) {
} else if (vFor) {
hasDynamicSlots = true
const parseResult =
vFor.parseResult ||
Expand Down Expand Up @@ -306,7 +314,7 @@ export function buildSlots(
props: ExpressionNode | undefined,
children: TemplateChildNode[]
) => {
const fn = buildSlotFn(props, children, loc)
const fn = buildSlotFn(props, undefined, children, loc)
if (__COMPAT__ && context.compatConfig) {
fn.isNonScopedSlot = true
}
Expand Down
2 changes: 1 addition & 1 deletion packages/compiler-ssr/__tests__/ssrComponent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ describe('ssr: components', () => {
_push(\`\${_ssrInterpolate(msg + key + _ctx.bar)}\`)
} else {
return [
_createTextVNode(_toDisplayString(msg + _ctx.key + _ctx.bar), 1 /* TEXT */)
_createTextVNode(_toDisplayString(msg + key + _ctx.bar), 1 /* TEXT */)
]
}
})
Expand Down
17 changes: 13 additions & 4 deletions packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
// fallback in case the child is render-fn based). Store them in an array
// for later use.
if (clonedNode.children.length) {
buildSlots(clonedNode, context, (props, children) => {
vnodeBranches.push(createVNodeSlotBranch(props, children, context))
buildSlots(clonedNode, context, (props, vFor, children) => {
vnodeBranches.push(createVNodeSlotBranch(props, vFor, children, context))
return createFunctionExpression(undefined)
})
}
Expand All @@ -145,7 +145,7 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
const wipEntries: WIPSlotEntry[] = []
wipMap.set(node, wipEntries)

const buildSSRSlotFn: SlotFnBuilder = (props, children, loc) => {
const buildSSRSlotFn: SlotFnBuilder = (props, _vFor, children, loc) => {
const param0 = (props && stringifyExpression(props)) || `_`
const fn = createFunctionExpression(
[param0, `_push`, `_parent`, `_scopeId`],
Expand Down Expand Up @@ -273,6 +273,7 @@ const vnodeDirectiveTransforms = {

function createVNodeSlotBranch(
props: ExpressionNode | undefined,
vFor: ExpressionNode | undefined,
children: TemplateChildNode[],
parentContext: TransformContext
): ReturnStatement {
Expand All @@ -299,7 +300,7 @@ function createVNodeSlotBranch(
tag: 'template',
tagType: ElementTypes.TEMPLATE,
isSelfClosing: false,
// important: provide v-slot="props" on the wrapper for proper
// important: provide v-slot="props" and v-for="exp" on the wrapper for proper
// scope analysis
props: [
{
Expand All @@ -309,6 +310,14 @@ function createVNodeSlotBranch(
arg: undefined,
modifiers: [],
loc: locStub
},
{
type: NodeTypes.DIRECTIVE,
name: 'for',
exp: vFor,
arg: undefined,
modifiers: [],
loc: locStub
}
],
children,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function ssrTransformSuspense(
wipSlots: []
}
wipMap.set(node, wipEntry)
wipEntry.slotsExp = buildSlots(node, context, (_props, children, loc) => {
wipEntry.slotsExp = buildSlots(node, context, (_props, _vFor, children, loc) => {
const fn = createFunctionExpression(
[],
undefined, // no return, assign body later
Expand Down

0 comments on commit 61299d6

Please sign in to comment.