diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts index 51962b2fa..e23b39e1f 100644 --- a/packages/compiler-core/src/transforms/vFor.ts +++ b/packages/compiler-core/src/transforms/vFor.ts @@ -353,6 +353,13 @@ export function finalizeForParseResult( true ) } + if (result.value) { + validateBrowserExpression( + result.value as SimpleExpressionNode, + context, + true + ) + } } result.finalized = true } diff --git a/packages/compiler-core/src/transforms/vSlot.ts b/packages/compiler-core/src/transforms/vSlot.ts index fac861b20..b270797cc 100644 --- a/packages/compiler-core/src/transforms/vSlot.ts +++ b/packages/compiler-core/src/transforms/vSlot.ts @@ -97,7 +97,7 @@ export const trackVForSlotScopes: NodeTransform = (node, context) => { export type SlotFnBuilder = ( slotProps: ExpressionNode | undefined, - vForExp: ExpressionNode | undefined, + vFor: DirectiveNode | undefined, slotChildren: TemplateChildNode[], loc: SourceLocation ) => FunctionExpression @@ -200,12 +200,7 @@ export function buildSlots( } const vFor = findDir(slotElement, 'for') - const slotFunction = buildSlotFn( - slotProps, - vFor?.exp, - slotChildren, - slotLoc - ) + const slotFunction = buildSlotFn(slotProps, vFor, slotChildren, slotLoc) // check if this slot is conditional (v-if/v-for) let vIf: DirectiveNode | undefined diff --git a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts index 7a12cb290..e59eee745 100644 --- a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts +++ b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts @@ -37,7 +37,8 @@ import { JSChildNode, RESOLVE_DYNAMIC_COMPONENT, TRANSITION, - stringifyExpression + stringifyExpression, + DirectiveNode } from '@vue/compiler-dom' import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers' import { @@ -54,7 +55,7 @@ import { ssrProcessTransitionGroup, ssrTransformTransitionGroup } from './ssrTransformTransitionGroup' -import { isSymbol, isObject, isArray } from '@vue/shared' +import { isSymbol, isObject, isArray, extend } from '@vue/shared' import { buildSSRProps } from './ssrTransformElement' import { ssrProcessTransition, @@ -278,8 +279,8 @@ const vnodeDirectiveTransforms = { } function createVNodeSlotBranch( - props: ExpressionNode | undefined, - vForExp: ExpressionNode | undefined, + slotProps: ExpressionNode | undefined, + vFor: DirectiveNode | undefined, children: TemplateChildNode[], parentContext: TransformContext ): ReturnStatement { @@ -300,32 +301,29 @@ function createVNodeSlotBranch( } // wrap the children with a wrapper template for proper children treatment. + // important: provide v-slot="props" and v-for="exp" on the wrapper for + // proper scope analysis + const wrapperProps: TemplateNode['props'] = [] + if (slotProps) { + wrapperProps.push({ + type: NodeTypes.DIRECTIVE, + name: 'slot', + exp: slotProps, + arg: undefined, + modifiers: [], + loc: locStub + }) + } + if (vFor) { + wrapperProps.push(extend({}, vFor)) + } const wrapperNode: TemplateNode = { type: NodeTypes.ELEMENT, ns: Namespaces.HTML, tag: 'template', tagType: ElementTypes.TEMPLATE, isSelfClosing: false, - // important: provide v-slot="props" and v-for="exp" on the wrapper for - // proper scope analysis - props: [ - { - type: NodeTypes.DIRECTIVE, - name: 'slot', - exp: props, - arg: undefined, - modifiers: [], - loc: locStub - }, - { - type: NodeTypes.DIRECTIVE, - name: 'for', - exp: vForExp, - arg: undefined, - modifiers: [], - loc: locStub - } - ], + props: wrapperProps, children, loc: locStub, codegenNode: undefined