Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,33 @@ export function render(_ctx) {
}"
`;

exports[`compiler: transform <slot> outlets > slot outlet with scopeId and slotted=false should generate noSlotted 1`] = `
"import { createSlot as _createSlot } from 'vue';

export function render(_ctx) {
const n0 = _createSlot("default", null, null, undefined, true)
return n0
}"
`;

exports[`compiler: transform <slot> outlets > slot outlet with scopeId and slotted=true should not generate noSlotted 1`] = `
"import { createSlot as _createSlot } from 'vue';

export function render(_ctx) {
const n0 = _createSlot("default", null)
return n0
}"
`;

exports[`compiler: transform <slot> outlets > slot outlet without scopeId should not generate noSlotted 1`] = `
"import { createSlot as _createSlot } from 'vue';

export function render(_ctx) {
const n0 = _createSlot("default", null)
return n0
}"
`;

exports[`compiler: transform <slot> outlets > statically named slot outlet 1`] = `
"import { createSlot as _createSlot } from 'vue';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,64 @@ describe('compiler: transform <slot> outlets', () => {
},
})
})

test('slot outlet with scopeId and slotted=false should generate noSlotted', () => {
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
scopeId: 'test-scope',
slotted: false,
})
expect(code).toMatchSnapshot()
expect(code).toContain('true')
expect(ir.block.dynamic.children[0].operation).toMatchObject({
type: IRNodeTypes.SLOT_OUTLET_NODE,
id: 0,
name: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'default',
isStatic: true,
},
props: [],
fallback: undefined,
noSlotted: true,
})
})

test('slot outlet with scopeId and slotted=true should not generate noSlotted', () => {
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
scopeId: 'test-scope',
slotted: true,
})
expect(code).toMatchSnapshot()
expect(ir.block.dynamic.children[0].operation).toMatchObject({
type: IRNodeTypes.SLOT_OUTLET_NODE,
id: 0,
name: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'default',
isStatic: true,
},
props: [],
fallback: undefined,
noSlotted: false,
})
})

test('slot outlet without scopeId should not generate noSlotted', () => {
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
slotted: false,
})
expect(code).toMatchSnapshot()
expect(ir.block.dynamic.children[0].operation).toMatchObject({
type: IRNodeTypes.SLOT_OUTLET_NODE,
id: 0,
name: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'default',
isStatic: true,
},
props: [],
fallback: undefined,
noSlotted: false,
})
})
})
4 changes: 3 additions & 1 deletion packages/compiler-vapor/src/generators/slotOutlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function genSlotOutlet(
context: CodegenContext,
): CodeFragment[] {
const { helper } = context
const { id, name, fallback, forwarded } = oper
const { id, name, fallback, forwarded, noSlotted } = oper
const [frag, push] = buildCodeFragment()

const nameExpr = name.isStatic
Expand All @@ -32,6 +32,8 @@ export function genSlotOutlet(
nameExpr,
genRawProps(oper.props, context) || 'null',
fallbackArg,
noSlotted && 'undefined', // instance
noSlotted && 'true', // noSlotted
),
)

Expand Down
1 change: 1 addition & 0 deletions packages/compiler-vapor/src/ir/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export interface SlotOutletIRNode extends BaseIRNode {
props: IRProps[]
fallback?: BlockIRNode
forwarded?: boolean
noSlotted?: boolean
parent?: number
anchor?: number
append?: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
props: irProps,
fallback,
forwarded: context.inSlot,
noSlotted: !!(context.options.scopeId && !context.options.slotted),
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,11 @@ export { type VaporInteropInterface } from './apiCreateApp'
/**
* @internal
*/
export { type RendererInternals, MoveType, invalidateMount } from './renderer'
export {
type RendererInternals,
MoveType,
getInheritedScopeIds,
} from './renderer'
/**
* @internal
*/
Expand Down
78 changes: 54 additions & 24 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,30 +777,9 @@ function baseCreateRenderer(
hostSetScopeId(el, slotScopeIds[i])
}
}
let subTree = parentComponent && parentComponent.subTree
if (subTree) {
if (
__DEV__ &&
subTree.patchFlag > 0 &&
subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
) {
subTree =
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
}
if (
vnode === subTree ||
(isSuspense(subTree.type) &&
(subTree.ssContent === vnode || subTree.ssFallback === vnode))
) {
const parentVNode = parentComponent!.vnode!
setScopeId(
el,
parentVNode,
parentVNode.scopeId,
parentVNode.slotScopeIds,
parentComponent!.parent,
)
}
const inheritedScopeIds = getInheritedScopeIds(vnode, parentComponent)
for (let i = 0; i < inheritedScopeIds.length; i++) {
hostSetScopeId(el, inheritedScopeIds[i])
}
}

Expand Down Expand Up @@ -2792,3 +2771,54 @@ export function getVaporInterface(
}
return res!
}

/**
* shared between vdom and vapor
*/
export function getInheritedScopeIds(
vnode: VNode,
parentComponent: GenericComponentInstance | null,
): string[] {
const inheritedScopeIds: string[] = []

let currentParent = parentComponent
let currentVNode = vnode

while (currentParent) {
let subTree = currentParent.subTree
if (!subTree) break

if (
__DEV__ &&
subTree.patchFlag > 0 &&
subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
) {
subTree =
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
}

if (
currentVNode === subTree ||
(isSuspense(subTree.type) &&
(subTree.ssContent === currentVNode ||
subTree.ssFallback === currentVNode))
) {
const parentVNode = currentParent.vnode!

if (parentVNode.scopeId) {
inheritedScopeIds.push(parentVNode.scopeId)
}

if (parentVNode.slotScopeIds) {
inheritedScopeIds.push(...parentVNode.slotScopeIds)
}

currentVNode = parentVNode
currentParent = currentParent.parent
} else {
break
}
}

return inheritedScopeIds
}
Loading
Loading