diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap index 9b66bb6c869..e3251a687d9 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap @@ -228,6 +228,25 @@ export function render(_ctx) { }" `; +exports[`compiler: transform slot > nested component should not inherit parent slots 1`] = ` +"import { resolveComponent as _resolveComponent, withVaporCtx as _withVaporCtx, createComponentWithFallback as _createComponentWithFallback } from 'vue'; + +export function render(_ctx) { + const _component_Bar = _resolveComponent("Bar") + const _component_Foo = _resolveComponent("Foo") + const n2 = _createComponentWithFallback(_component_Foo, null, { + "header": _withVaporCtx(() => { + return null + }), + "default": _withVaporCtx(() => { + const n1 = _createComponentWithFallback(_component_Bar) + return n1 + }) + }, true) + return n2 +}" +`; + exports[`compiler: transform slot > nested component slot 1`] = ` "import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, withVaporCtx as _withVaporCtx } from 'vue'; diff --git a/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts b/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts index 64d1b4ac4a4..093f1d577be 100644 --- a/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts @@ -155,6 +155,16 @@ describe('compiler: transform slot', () => { }) }) + test('nested component should not inherit parent slots', () => { + const { code } = compileWithSlots(` + + + + + `) + expect(code).toMatchSnapshot() + }) + test('named slots w/ implicit default slot', () => { const { ir, code } = compileWithSlots( ` diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts index dc9c7e0aae0..312800a093a 100644 --- a/packages/compiler-vapor/src/transforms/transformElement.ts +++ b/packages/compiler-vapor/src/transforms/transformElement.ts @@ -37,6 +37,7 @@ import { type IRProps, type IRPropsDynamicAttribute, type IRPropsStatic, + type IRSlots, type VaporDirectiveNode, } from '../ir' import { EMPTY_EXPRESSION } from './utils' @@ -51,6 +52,20 @@ export const isReservedProp: (key: string) => boolean = /*#__PURE__*/ makeMap( export const transformElement: NodeTransform = (node, context) => { let effectIndex = context.block.effect.length const getEffectIndex = () => effectIndex++ + + // If the element is a component, we need to isolate its slots context. + // This ensures that slots defined for this component are not accidentally + // inherited by its children components. + let parentSlots: IRSlots[] | undefined + if ( + node.type === NodeTypes.ELEMENT && + (node.tagType === ElementTypes.COMPONENT || + context.options.isCustomElement(node.tag)) + ) { + parentSlots = context.slots + context.slots = [] + } + return function postTransformElement() { ;({ node } = context) if ( @@ -96,6 +111,10 @@ export const transformElement: NodeTransform = (node, context) => { getEffectIndex, ) } + + if (parentSlots) { + context.slots = parentSlots + } } }