Skip to content

Commit 5bdcd81

Browse files
authored
feat(vapor): set scopeId (#14004)
1 parent d381c2f commit 5bdcd81

File tree

12 files changed

+887
-33
lines changed

12 files changed

+887
-33
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,33 @@ export function render(_ctx) {
111111
}"
112112
`;
113113
114+
exports[`compiler: transform <slot> outlets > slot outlet with scopeId and slotted=false should generate noSlotted 1`] = `
115+
"import { createSlot as _createSlot } from 'vue';
116+
117+
export function render(_ctx) {
118+
const n0 = _createSlot("default", null, null, undefined, true)
119+
return n0
120+
}"
121+
`;
122+
123+
exports[`compiler: transform <slot> outlets > slot outlet with scopeId and slotted=true should not generate noSlotted 1`] = `
124+
"import { createSlot as _createSlot } from 'vue';
125+
126+
export function render(_ctx) {
127+
const n0 = _createSlot("default", null)
128+
return n0
129+
}"
130+
`;
131+
132+
exports[`compiler: transform <slot> outlets > slot outlet without scopeId should not generate noSlotted 1`] = `
133+
"import { createSlot as _createSlot } from 'vue';
134+
135+
export function render(_ctx) {
136+
const n0 = _createSlot("default", null)
137+
return n0
138+
}"
139+
`;
140+
114141
exports[`compiler: transform <slot> outlets > statically named slot outlet 1`] = `
115142
"import { createSlot as _createSlot } from 'vue';
116143

packages/compiler-vapor/__tests__/transforms/transformSlotOutlet.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,64 @@ describe('compiler: transform <slot> outlets', () => {
277277
},
278278
})
279279
})
280+
281+
test('slot outlet with scopeId and slotted=false should generate noSlotted', () => {
282+
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
283+
scopeId: 'test-scope',
284+
slotted: false,
285+
})
286+
expect(code).toMatchSnapshot()
287+
expect(code).toContain('true')
288+
expect(ir.block.dynamic.children[0].operation).toMatchObject({
289+
type: IRNodeTypes.SLOT_OUTLET_NODE,
290+
id: 0,
291+
name: {
292+
type: NodeTypes.SIMPLE_EXPRESSION,
293+
content: 'default',
294+
isStatic: true,
295+
},
296+
props: [],
297+
fallback: undefined,
298+
noSlotted: true,
299+
})
300+
})
301+
302+
test('slot outlet with scopeId and slotted=true should not generate noSlotted', () => {
303+
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
304+
scopeId: 'test-scope',
305+
slotted: true,
306+
})
307+
expect(code).toMatchSnapshot()
308+
expect(ir.block.dynamic.children[0].operation).toMatchObject({
309+
type: IRNodeTypes.SLOT_OUTLET_NODE,
310+
id: 0,
311+
name: {
312+
type: NodeTypes.SIMPLE_EXPRESSION,
313+
content: 'default',
314+
isStatic: true,
315+
},
316+
props: [],
317+
fallback: undefined,
318+
noSlotted: false,
319+
})
320+
})
321+
322+
test('slot outlet without scopeId should not generate noSlotted', () => {
323+
const { ir, code } = compileWithSlotsOutlet(`<slot />`, {
324+
slotted: false,
325+
})
326+
expect(code).toMatchSnapshot()
327+
expect(ir.block.dynamic.children[0].operation).toMatchObject({
328+
type: IRNodeTypes.SLOT_OUTLET_NODE,
329+
id: 0,
330+
name: {
331+
type: NodeTypes.SIMPLE_EXPRESSION,
332+
content: 'default',
333+
isStatic: true,
334+
},
335+
props: [],
336+
fallback: undefined,
337+
noSlotted: false,
338+
})
339+
})
280340
})

packages/compiler-vapor/src/generators/slotOutlet.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function genSlotOutlet(
1212
context: CodegenContext,
1313
): CodeFragment[] {
1414
const { helper } = context
15-
const { id, name, fallback, forwarded } = oper
15+
const { id, name, fallback, forwarded, noSlotted } = oper
1616
const [frag, push] = buildCodeFragment()
1717

1818
const nameExpr = name.isStatic
@@ -32,6 +32,8 @@ export function genSlotOutlet(
3232
nameExpr,
3333
genRawProps(oper.props, context) || 'null',
3434
fallbackArg,
35+
noSlotted && 'undefined', // instance
36+
noSlotted && 'true', // noSlotted
3537
),
3638
)
3739

packages/compiler-vapor/src/ir/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ export interface SlotOutletIRNode extends BaseIRNode {
221221
props: IRProps[]
222222
fallback?: BlockIRNode
223223
forwarded?: boolean
224+
noSlotted?: boolean
224225
parent?: number
225226
anchor?: number
226227
append?: boolean

packages/compiler-vapor/src/transforms/transformSlotOutlet.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
108108
props: irProps,
109109
fallback,
110110
forwarded: context.inSlot,
111+
noSlotted: !!(context.options.scopeId && !context.options.slotted),
111112
}
112113
}
113114
}

packages/runtime-core/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,11 @@ export { type VaporInteropInterface } from './apiCreateApp'
516516
/**
517517
* @internal
518518
*/
519-
export { type RendererInternals, MoveType, invalidateMount } from './renderer'
519+
export {
520+
type RendererInternals,
521+
MoveType,
522+
getInheritedScopeIds,
523+
} from './renderer'
520524
/**
521525
* @internal
522526
*/

packages/runtime-core/src/renderer.ts

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -777,30 +777,9 @@ function baseCreateRenderer(
777777
hostSetScopeId(el, slotScopeIds[i])
778778
}
779779
}
780-
let subTree = parentComponent && parentComponent.subTree
781-
if (subTree) {
782-
if (
783-
__DEV__ &&
784-
subTree.patchFlag > 0 &&
785-
subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
786-
) {
787-
subTree =
788-
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
789-
}
790-
if (
791-
vnode === subTree ||
792-
(isSuspense(subTree.type) &&
793-
(subTree.ssContent === vnode || subTree.ssFallback === vnode))
794-
) {
795-
const parentVNode = parentComponent!.vnode!
796-
setScopeId(
797-
el,
798-
parentVNode,
799-
parentVNode.scopeId,
800-
parentVNode.slotScopeIds,
801-
parentComponent!.parent,
802-
)
803-
}
780+
const inheritedScopeIds = getInheritedScopeIds(vnode, parentComponent)
781+
for (let i = 0; i < inheritedScopeIds.length; i++) {
782+
hostSetScopeId(el, inheritedScopeIds[i])
804783
}
805784
}
806785

@@ -2792,3 +2771,54 @@ export function getVaporInterface(
27922771
}
27932772
return res!
27942773
}
2774+
2775+
/**
2776+
* shared between vdom and vapor
2777+
*/
2778+
export function getInheritedScopeIds(
2779+
vnode: VNode,
2780+
parentComponent: GenericComponentInstance | null,
2781+
): string[] {
2782+
const inheritedScopeIds: string[] = []
2783+
2784+
let currentParent = parentComponent
2785+
let currentVNode = vnode
2786+
2787+
while (currentParent) {
2788+
let subTree = currentParent.subTree
2789+
if (!subTree) break
2790+
2791+
if (
2792+
__DEV__ &&
2793+
subTree.patchFlag > 0 &&
2794+
subTree.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT
2795+
) {
2796+
subTree =
2797+
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
2798+
}
2799+
2800+
if (
2801+
currentVNode === subTree ||
2802+
(isSuspense(subTree.type) &&
2803+
(subTree.ssContent === currentVNode ||
2804+
subTree.ssFallback === currentVNode))
2805+
) {
2806+
const parentVNode = currentParent.vnode!
2807+
2808+
if (parentVNode.scopeId) {
2809+
inheritedScopeIds.push(parentVNode.scopeId)
2810+
}
2811+
2812+
if (parentVNode.slotScopeIds) {
2813+
inheritedScopeIds.push(...parentVNode.slotScopeIds)
2814+
}
2815+
2816+
currentVNode = parentVNode
2817+
currentParent = currentParent.parent
2818+
} else {
2819+
break
2820+
}
2821+
}
2822+
2823+
return inheritedScopeIds
2824+
}

0 commit comments

Comments
 (0)