Skip to content

Commit 4f2a04e

Browse files
committed
fix: fix scopedSlots regression
1 parent 642e7aa commit 4f2a04e

File tree

3 files changed

+54
-19
lines changed

3 files changed

+54
-19
lines changed

src/core/instance/render.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ export function renderMixin(Vue: typeof Component) {
102102
vm.$scopedSlots = normalizeScopedSlots(
103103
vm.$parent!,
104104
_parentVnode.data!.scopedSlots,
105-
vm.$slots
105+
vm.$slots,
106+
vm.$scopedSlots
106107
)
107108
if (vm._slotsProxy) {
108109
syncSetupSlots(vm._slotsProxy, vm.$scopedSlots)

src/core/vdom/helpers/normalize-scoped-slots.ts

+23-18
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,40 @@ import { currentInstance, setCurrentInstance } from 'v3/currentInstance'
88

99
export function normalizeScopedSlots(
1010
ownerVm: Component,
11-
slots: { [key: string]: Function } | void,
12-
normalSlots: { [key: string]: VNode[] }
11+
scopedSlots: { [key: string]: Function } | undefined,
12+
normalSlots: { [key: string]: VNode[] },
13+
prevScopedSlots?: { [key: string]: Function }
1314
): any {
1415
let res
15-
const prevSlots = ownerVm.$scopedSlots
1616
const hasNormalSlots = Object.keys(normalSlots).length > 0
17-
const isStable = slots ? !!slots.$stable : !hasNormalSlots
18-
const key = slots && slots.$key
19-
if (!slots) {
17+
const isStable = scopedSlots ? !!scopedSlots.$stable : !hasNormalSlots
18+
const key = scopedSlots && scopedSlots.$key
19+
if (!scopedSlots) {
2020
res = {}
21-
} else if (slots._normalized) {
21+
} else if (scopedSlots._normalized) {
2222
// fast path 1: child component re-render only, parent did not change
23-
return slots._normalized
23+
return scopedSlots._normalized
2424
} else if (
2525
isStable &&
26-
prevSlots &&
27-
prevSlots !== emptyObject &&
28-
key === prevSlots.$key &&
26+
prevScopedSlots &&
27+
prevScopedSlots !== emptyObject &&
28+
key === prevScopedSlots.$key &&
2929
!hasNormalSlots &&
30-
!prevSlots.$hasNormal
30+
!prevScopedSlots.$hasNormal
3131
) {
3232
// fast path 2: stable scoped slots w/ no normal slots to proxy,
3333
// only need to normalize once
34-
return prevSlots
34+
return prevScopedSlots
3535
} else {
3636
res = {}
37-
for (const key in slots) {
38-
if (slots[key] && key[0] !== '$') {
39-
res[key] = normalizeScopedSlot(ownerVm, normalSlots, key, slots[key])
37+
for (const key in scopedSlots) {
38+
if (scopedSlots[key] && key[0] !== '$') {
39+
res[key] = normalizeScopedSlot(
40+
ownerVm,
41+
normalSlots,
42+
key,
43+
scopedSlots[key]
44+
)
4045
}
4146
}
4247
}
@@ -48,8 +53,8 @@ export function normalizeScopedSlots(
4853
}
4954
// avoriaz seems to mock a non-extensible $scopedSlots object
5055
// and when that is passed down this would cause an error
51-
if (slots && Object.isExtensible(slots)) {
52-
slots._normalized = res
56+
if (scopedSlots && Object.isExtensible(scopedSlots)) {
57+
scopedSlots._normalized = res
5358
}
5459
def(res, '$stable', isStable)
5560
def(res, '$key', key)

test/unit/features/component/component-slot.spec.ts

+29
Original file line numberDiff line numberDiff line change
@@ -1044,4 +1044,33 @@ describe('Component slot', () => {
10441044

10451045
expect(vm.$el.innerHTML).toBe(`<!----><span>b</span>`)
10461046
})
1047+
1048+
// regression 2.7.0-alpha.4
1049+
it('passing scoped slots through nested parent chain', () => {
1050+
const Foo = {
1051+
template: `
1052+
<div><slot>foo default</slot></div>
1053+
`
1054+
}
1055+
1056+
const Bar = {
1057+
components: { Foo },
1058+
template: `<Foo><slot name="bar"/></Foo>`
1059+
}
1060+
1061+
const App = {
1062+
components: { Bar },
1063+
template: `<Bar>
1064+
<template #bar>
1065+
<span>App content for Bar#bar</span>
1066+
</template>
1067+
</Bar>`
1068+
}
1069+
1070+
const vm = new Vue({
1071+
render: h => h(App)
1072+
}).$mount()
1073+
1074+
expect(vm.$el.innerHTML).toMatch(`App content for Bar#bar`)
1075+
})
10471076
})

0 commit comments

Comments
 (0)