diff --git a/src/core/vdom/helpers/normalize-scoped-slots.ts b/src/core/vdom/helpers/normalize-scoped-slots.ts index 10a0d1186e1..85a4c367149 100644 --- a/src/core/vdom/helpers/normalize-scoped-slots.ts +++ b/src/core/vdom/helpers/normalize-scoped-slots.ts @@ -14,7 +14,13 @@ export function normalizeScopedSlots( ): any { let res const hasNormalSlots = Object.keys(normalSlots).length > 0 - const isStable = scopedSlots ? !!scopedSlots.$stable : !hasNormalSlots + const hasNormalizedSlots = + scopedSlots && scopedSlots.$hasNormal !== undefined + const isStable = scopedSlots + ? hasNormalizedSlots + ? false + : !!scopedSlots.$stable + : !hasNormalSlots const key = scopedSlots && scopedSlots.$key if (!scopedSlots) { res = {} diff --git a/test/unit/features/component/component-scoped-slot.spec.ts b/test/unit/features/component/component-scoped-slot.spec.ts index 96c23f8c66c..ac37950896f 100644 --- a/test/unit/features/component/component-scoped-slot.spec.ts +++ b/test/unit/features/component/component-scoped-slot.spec.ts @@ -1380,6 +1380,43 @@ describe('Component scoped slot', () => { }).then(done) }) + // #13066 + it('updates forwarded $scopedSlots when normal and scoped slots coexist', done => { + const inner = { + data: () => ({ msg: 'hi' }), + render(h) { + return h('div', this.$scopedSlots.default({ msg: this.msg })) + } + } + + const wrapper = { + render(h) { + return h(inner, { scopedSlots: this.$scopedSlots }) + } + } + + const vm = new Vue({ + data: { count: 0 }, + render(h) { + return h( + wrapper, + { + scopedSlots: { + default: props => h('span', `${props.msg} ${this.count}`) + } + }, + [h('span', { slot: 'footer' }, this.count)] + ) + } + }).$mount() + + expect(vm.$el.textContent).toBe('hi 0') + vm.count++ + waitForUpdate(() => { + expect(vm.$el.textContent).toBe('hi 1') + }).then(done) + }) + // #11652 it('should update when switching between two components with slot and without slot', done => { const Child = {