From 80a54ddae16d81e7f3c2c834e60bfe4c5861dc1b Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Wed, 19 Jun 2024 22:20:25 +0800 Subject: [PATCH 1/7] test(runtime-vapor): add test case --- .../__tests__/componentSlots.spec.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/packages/runtime-vapor/__tests__/componentSlots.spec.ts b/packages/runtime-vapor/__tests__/componentSlots.spec.ts index 2ea5715be..456363921 100644 --- a/packages/runtime-vapor/__tests__/componentSlots.spec.ts +++ b/packages/runtime-vapor/__tests__/componentSlots.spec.ts @@ -1,6 +1,7 @@ // NOTE: This test is implemented based on the case of `runtime-core/__test__/componentSlots.spec.ts`. import { + type ComponentInternalInstance, createComponent, createForSlots, createSlot, @@ -291,6 +292,47 @@ describe('component: slots', () => { expect(instance.slots).not.toHaveProperty('1') }) + test('dynamicSlots should not cover high weight static slots', async () => { + const dynamicFlag = ref(true) + + let instance: ComponentInternalInstance + const { component: Child } = define({ + render() { + instance = getCurrentInstance()! + return [createSlot('default'), createSlot('others')] + }, + }) + + const { render, html } = define({ + render() { + return createComponent(Child, {}, [ + () => + dynamicFlag.value + ? { name: 'default', fn: () => template('dynamic default')() } + : { name: 'others', fn: () => template('ohters')() }, + { + default: () => template('default')(), + }, + ]) + }, + }) + + render() + + expect(html()).toBe('default') + + dynamicFlag.value = false + await nextTick() + + expect(html()).toBe('defaultothers') + expect(instance!.slots).haveOwnProperty('others') + + dynamicFlag.value = true + await nextTick() + expect(html()).toBe('default') + expect(instance!.slots).not.haveOwnProperty('others') + }) + test.todo('should respect $stable flag', async () => { // TODO: $stable flag? }) From a38175ec5472d9bf7bb6c8833b288a89d35d64b4 Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Sun, 23 Jun 2024 17:08:37 +0800 Subject: [PATCH 2/7] feat(runtime-vapor): fix slots level --- .../__tests__/componentSlots.spec.ts | 70 ++++++++++++++++- packages/runtime-vapor/src/componentSlots.ts | 76 ++++++++++++++----- 2 files changed, 127 insertions(+), 19 deletions(-) diff --git a/packages/runtime-vapor/__tests__/componentSlots.spec.ts b/packages/runtime-vapor/__tests__/componentSlots.spec.ts index 4e52173ef..b1262ada7 100644 --- a/packages/runtime-vapor/__tests__/componentSlots.spec.ts +++ b/packages/runtime-vapor/__tests__/componentSlots.spec.ts @@ -3,6 +3,7 @@ import { type ComponentInternalInstance, createComponent, + createFor, createForSlots, createSlot, createVaporApp, @@ -15,6 +16,7 @@ import { renderEffect, setText, template, + useSlots, withDestructure, } from '../src' import { makeRender } from './_utils' @@ -326,7 +328,71 @@ describe('component: slots', () => { expect(instance.slots).not.toHaveProperty('1') }) - test('dynamicSlots should not cover high weight static slots', async () => { + test('should not delete new rendered slot when the old slot is removed in loop slot', async () => { + const loop = ref([1, 'default', 3]) + + let childInstance + const t0 = template('
') + const { component: Child } = define({ + setup() { + childInstance = getCurrentInstance() + const slots = useSlots() + const keys = () => Object.keys(slots) + return { + keys, + slots, + } + }, + render: (_ctx: any) => { + const n0 = createFor( + () => _ctx.keys(), + (_ctx0: any) => { + const n5 = t0() + const n4 = createSlot(() => _ctx0[0]) + insert(n4, n5 as ParentNode) + return n5 + }, + ) + return n0 + }, + }) + + const t1 = template(' static default ') + const { render } = define({ + setup() { + return createComponent(Child, {}, [ + { + default: () => { + return t1() + }, + }, + () => + createForSlots(loop.value, (item, i) => ({ + name: item, + fn: () => template(item)(), + })), + ]) + }, + }) + const { html } = render() + + expect(childInstance!.slots).toHaveProperty('1') + expect(childInstance!.slots).toHaveProperty('default') + expect(childInstance!.slots).toHaveProperty('3') + expect(html()).toBe( + '
1
3
default
', + ) + loop.value = [1] + await nextTick() + expect(childInstance!.slots).toHaveProperty('1') + expect(childInstance!.slots).toHaveProperty('default') + expect(childInstance!.slots).not.toHaveProperty('3') + expect(html()).toBe( + '
1
static default
', + ) + }) + + test('dynamicSlots should not cover high level slots', async () => { const dynamicFlag = ref(true) let instance: ComponentInternalInstance @@ -343,7 +409,7 @@ describe('component: slots', () => { () => dynamicFlag.value ? { name: 'default', fn: () => template('dynamic default')() } - : { name: 'others', fn: () => template('ohters')() }, + : { name: 'others', fn: () => template('others')() }, { default: () => template('default')(), }, diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index d0f5e3573..8cfed3e71 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -45,51 +45,93 @@ export function initSlots( // with ctx const slots = rawSlots[0] as StaticSlots for (const name in slots) { - registerSlot(name, slots[name]) + resolveSlot(name, slots[name]) } return } instance.slots = shallowReactive({}) - const keys: Set[] = [] + const renderedSlotKeys: Set[] = [] + const slotNameLevels: Record = {} rawSlots.forEach((slots, index) => { const isDynamicSlot = isDynamicSlotFn(slots) if (isDynamicSlot) { firstEffect(instance, () => { - const recordNames = keys[index] || (keys[index] = new Set()) + const renderedKeys = + renderedSlotKeys[index] || (renderedSlotKeys[index] = new Set()) let dynamicSlot: ReturnType - if (isDynamicSlotFn(slots)) { - dynamicSlot = slots() - if (isArray(dynamicSlot)) { - for (const slot of dynamicSlot) { - registerSlot(slot.name, slot.fn, recordNames) - } - } else if (dynamicSlot) { - registerSlot(dynamicSlot.name, dynamicSlot.fn, recordNames) + dynamicSlot = slots() + const restoreKeys = cleanupSlot(index) + if (isArray(dynamicSlot)) { + for (const slot of dynamicSlot) { + registerSlot(slot.name, slot.fn, index, renderedKeys) + } + } else if (dynamicSlot) { + registerSlot(dynamicSlot.name, dynamicSlot.fn, index, renderedKeys) + } + if (restoreKeys.length) { + for (const key of restoreKeys) { + resolveSlot(key, slotNameLevels[key][0][1]) } - } else { } - for (const name of recordNames) { + for (const name of renderedKeys) { if ( !(isArray(dynamicSlot) ? dynamicSlot.some(s => s.name === name) : dynamicSlot && dynamicSlot.name === name) ) { - recordNames.delete(name) + renderedKeys.delete(name) delete instance.slots[name] } } }) } else { for (const name in slots) { - registerSlot(name, slots[name]) + registerSlot(name, slots[name], index) } } }) - function registerSlot(name: string, fn: Slot, recordNames?: Set) { + function cleanupSlot(level: number) { + const restoreKeys: string[] = [] + Object.keys(slotNameLevels).forEach(key => { + const index = slotNameLevels[key].findIndex(([l]) => l === level) + if (index > -1) { + slotNameLevels[key].splice(index, 1) + if (!slotNameLevels[key].length) { + delete slotNameLevels[key] + return + } + if (index === 0) { + renderedSlotKeys[level] && renderedSlotKeys[level].delete(key) + restoreKeys.push(key) + } + } + }) + return restoreKeys + } + + function registerSlot( + name: string, + fn: Slot, + level: number, + renderedKeys?: Set, + ) { + slotNameLevels[name] = slotNameLevels[name] || [] + slotNameLevels[name].push([level, fn]) + slotNameLevels[name].sort((a, b) => b[0] - a[0]) + for (let i = 1; i < slotNameLevels[name].length; i++) { + const hidenLevel = slotNameLevels[name][i][0] + renderedSlotKeys[hidenLevel] && renderedSlotKeys[hidenLevel].delete(name) + } + if (slotNameLevels[name][0][0] === level) { + renderedKeys && renderedKeys.add(name) + } + resolveSlot(name, slotNameLevels[name][0][1]) + } + + function resolveSlot(name: string, fn: Slot) { instance.slots[name] = withCtx(fn) - recordNames && recordNames.add(name) } function withCtx(fn: Slot): Slot { From d38e440562391ebc3687e8f8608fb5c3c2b79930 Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Sun, 23 Jun 2024 17:57:15 +0800 Subject: [PATCH 3/7] feat(runtime-vapor): simplify code --- packages/runtime-vapor/src/componentSlots.ts | 45 +++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index 8cfed3e71..6cb7661a1 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -52,7 +52,7 @@ export function initSlots( instance.slots = shallowReactive({}) const renderedSlotKeys: Set[] = [] - const slotNameLevels: Record = {} + const slotsQueue: Record = {} rawSlots.forEach((slots, index) => { const isDynamicSlot = isDynamicSlotFn(slots) if (isDynamicSlot) { @@ -61,7 +61,7 @@ export function initSlots( renderedSlotKeys[index] || (renderedSlotKeys[index] = new Set()) let dynamicSlot: ReturnType dynamicSlot = slots() - const restoreKeys = cleanupSlot(index) + const restoreSlotNames = cleanupSlot(index) if (isArray(dynamicSlot)) { for (const slot of dynamicSlot) { registerSlot(slot.name, slot.fn, index, renderedKeys) @@ -69,9 +69,12 @@ export function initSlots( } else if (dynamicSlot) { registerSlot(dynamicSlot.name, dynamicSlot.fn, index, renderedKeys) } - if (restoreKeys.length) { - for (const key of restoreKeys) { - resolveSlot(key, slotNameLevels[key][0][1]) + if (restoreSlotNames.length) { + for (const key of restoreSlotNames) { + const [restoreLevel, restoreFn] = slotsQueue[key][0] + renderedSlotKeys[restoreLevel] && + renderedSlotKeys[restoreLevel].add(key) + resolveSlot(key, restoreFn) } } for (const name of renderedKeys) { @@ -93,22 +96,22 @@ export function initSlots( }) function cleanupSlot(level: number) { - const restoreKeys: string[] = [] - Object.keys(slotNameLevels).forEach(key => { - const index = slotNameLevels[key].findIndex(([l]) => l === level) + const restoreSlotNames: string[] = [] + Object.keys(slotsQueue).forEach(slotName => { + const index = slotsQueue[slotName].findIndex(([l]) => l === level) if (index > -1) { - slotNameLevels[key].splice(index, 1) - if (!slotNameLevels[key].length) { - delete slotNameLevels[key] + slotsQueue[slotName].splice(index, 1) + if (!slotsQueue[slotName].length) { + delete slotsQueue[slotName] return } if (index === 0) { - renderedSlotKeys[level] && renderedSlotKeys[level].delete(key) - restoreKeys.push(key) + renderedSlotKeys[level] && renderedSlotKeys[level].delete(slotName) + restoreSlotNames.push(slotName) } } }) - return restoreKeys + return restoreSlotNames } function registerSlot( @@ -117,17 +120,17 @@ export function initSlots( level: number, renderedKeys?: Set, ) { - slotNameLevels[name] = slotNameLevels[name] || [] - slotNameLevels[name].push([level, fn]) - slotNameLevels[name].sort((a, b) => b[0] - a[0]) - for (let i = 1; i < slotNameLevels[name].length; i++) { - const hidenLevel = slotNameLevels[name][i][0] + slotsQueue[name] = slotsQueue[name] || [] + slotsQueue[name].push([level, fn]) + slotsQueue[name].sort((a, b) => b[0] - a[0]) + if (slotsQueue[name][1]) { + const hidenLevel = slotsQueue[name][1][0] renderedSlotKeys[hidenLevel] && renderedSlotKeys[hidenLevel].delete(name) } - if (slotNameLevels[name][0][0] === level) { + if (slotsQueue[name][0][0] === level) { renderedKeys && renderedKeys.add(name) } - resolveSlot(name, slotNameLevels[name][0][1]) + resolveSlot(name, slotsQueue[name][0][1]) } function resolveSlot(name: string, fn: Slot) { From 1babaefe43e84db570b8adcc732b0a1fd6aad5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Sun, 23 Jun 2024 18:25:57 +0800 Subject: [PATCH 4/7] refactor --- packages/runtime-vapor/src/componentSlots.ts | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index 6cb7661a1..0e4e2dc02 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -45,22 +45,20 @@ export function initSlots( // with ctx const slots = rawSlots[0] as StaticSlots for (const name in slots) { - resolveSlot(name, slots[name]) + addSlot(name, slots[name]) } return } instance.slots = shallowReactive({}) const renderedSlotKeys: Set[] = [] - const slotsQueue: Record = {} + const slotsQueue: Record = {} rawSlots.forEach((slots, index) => { const isDynamicSlot = isDynamicSlotFn(slots) if (isDynamicSlot) { firstEffect(instance, () => { - const renderedKeys = - renderedSlotKeys[index] || (renderedSlotKeys[index] = new Set()) - let dynamicSlot: ReturnType - dynamicSlot = slots() + const renderedKeys = (renderedSlotKeys[index] ||= new Set()) + let dynamicSlot = slots() const restoreSlotNames = cleanupSlot(index) if (isArray(dynamicSlot)) { for (const slot of dynamicSlot) { @@ -74,7 +72,7 @@ export function initSlots( const [restoreLevel, restoreFn] = slotsQueue[key][0] renderedSlotKeys[restoreLevel] && renderedSlotKeys[restoreLevel].add(key) - resolveSlot(key, restoreFn) + addSlot(key, restoreFn) } } for (const name of renderedKeys) { @@ -116,12 +114,12 @@ export function initSlots( function registerSlot( name: string, - fn: Slot, + slot: Slot, level: number, renderedKeys?: Set, ) { - slotsQueue[name] = slotsQueue[name] || [] - slotsQueue[name].push([level, fn]) + slotsQueue[name] ||= [] + slotsQueue[name].push([level, slot]) slotsQueue[name].sort((a, b) => b[0] - a[0]) if (slotsQueue[name][1]) { const hidenLevel = slotsQueue[name][1][0] @@ -130,10 +128,10 @@ export function initSlots( if (slotsQueue[name][0][0] === level) { renderedKeys && renderedKeys.add(name) } - resolveSlot(name, slotsQueue[name][0][1]) + addSlot(name, slotsQueue[name][0][1]) } - function resolveSlot(name: string, fn: Slot) { + function addSlot(name: string, fn: Slot) { instance.slots[name] = withCtx(fn) } From d9c0c29977c02f4389d34d99afeebaa1170637ae Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Sun, 23 Jun 2024 18:42:18 +0800 Subject: [PATCH 5/7] fix(runtime-vapor): fix loop slots cleanup and add some annotate --- .../__tests__/componentSlots.spec.ts | 70 +++++++++++++++++++ packages/runtime-vapor/src/componentSlots.ts | 14 +++- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/packages/runtime-vapor/__tests__/componentSlots.spec.ts b/packages/runtime-vapor/__tests__/componentSlots.spec.ts index b1262ada7..62e99da38 100644 --- a/packages/runtime-vapor/__tests__/componentSlots.spec.ts +++ b/packages/runtime-vapor/__tests__/componentSlots.spec.ts @@ -392,6 +392,76 @@ describe('component: slots', () => { ) }) + test('should cleanup all slots when loop slot has same key', async () => { + const loop = ref([1, 1, 1]) + + let childInstance + const t0 = template('
') + const { component: Child } = define({ + setup() { + childInstance = getCurrentInstance() + const slots = useSlots() + const keys = () => Object.keys(slots) + return { + keys, + slots, + } + }, + render: (_ctx: any) => { + const n0 = createFor( + () => _ctx.keys(), + (_ctx0: any) => { + const n5 = t0() + const n4 = createSlot(() => _ctx0[0]) + insert(n4, n5 as ParentNode) + return n5 + }, + ) + return n0 + }, + }) + + const t1 = template(' static default ') + const { render } = define({ + setup() { + return createComponent(Child, {}, [ + { + default: () => { + return t1() + }, + }, + () => + createForSlots(loop.value, (item, i) => ({ + name: item, + fn: () => template(item)(), + })), + ]) + }, + }) + const { html } = render() + expect(childInstance!.slots).toHaveProperty('1') + expect(childInstance!.slots).toHaveProperty('default') + expect(html()).toBe( + '
1
static default
', + ) + loop.value = [1] + await nextTick() + expect(childInstance!.slots).toHaveProperty('1') + expect(childInstance!.slots).toHaveProperty('default') + expect(html()).toBe( + '
1
static default
', + ) + loop.value = [1, 2, 3] + await nextTick() + expect(childInstance!.slots).toHaveProperty('1') + expect(childInstance!.slots).toHaveProperty('2') + expect(childInstance!.slots).toHaveProperty('3') + expect(childInstance!.slots).toHaveProperty('default') + expect(html()).toBe( + '
1
2
3
static default
', + ) + }) + test('dynamicSlots should not cover high level slots', async () => { const dynamicFlag = ref(true) diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index 0e4e2dc02..a96425a7e 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -52,6 +52,10 @@ export function initSlots( instance.slots = shallowReactive({}) const renderedSlotKeys: Set[] = [] + /** + * Maintain a queue for each slot name, so that we can + * render the next slot when the highest level slot was removed + */ const slotsQueue: Record = {} rawSlots.forEach((slots, index) => { const isDynamicSlot = isDynamicSlotFn(slots) @@ -59,6 +63,8 @@ export function initSlots( firstEffect(instance, () => { const renderedKeys = (renderedSlotKeys[index] ||= new Set()) let dynamicSlot = slots() + // cleanup slots and re-calc to avoid diffing slots between renders + // cleanup will return a slotNames array contains the slot names that need to be restored const restoreSlotNames = cleanupSlot(index) if (isArray(dynamicSlot)) { for (const slot of dynamicSlot) { @@ -67,6 +73,7 @@ export function initSlots( } else if (dynamicSlot) { registerSlot(dynamicSlot.name, dynamicSlot.fn, index, renderedKeys) } + // restore after re-calc slots if (restoreSlotNames.length) { for (const key of restoreSlotNames) { const [restoreLevel, restoreFn] = slotsQueue[key][0] @@ -75,6 +82,7 @@ export function initSlots( addSlot(key, restoreFn) } } + // delete stale slots for (const name of renderedKeys) { if ( !(isArray(dynamicSlot) @@ -95,14 +103,16 @@ export function initSlots( function cleanupSlot(level: number) { const restoreSlotNames: string[] = [] + // remove slots from all queues Object.keys(slotsQueue).forEach(slotName => { const index = slotsQueue[slotName].findIndex(([l]) => l === level) if (index > -1) { - slotsQueue[slotName].splice(index, 1) + slotsQueue[slotName] = slotsQueue[slotName].filter(([l]) => l !== level) if (!slotsQueue[slotName].length) { delete slotsQueue[slotName] return } + // restore next slot if the removed slots was the highest level slot if (index === 0) { renderedSlotKeys[level] && renderedSlotKeys[level].delete(slotName) restoreSlotNames.push(slotName) @@ -121,6 +131,7 @@ export function initSlots( slotsQueue[name] ||= [] slotsQueue[name].push([level, slot]) slotsQueue[name].sort((a, b) => b[0] - a[0]) + // hide old slot if the registered slot is the highest level if (slotsQueue[name][1]) { const hidenLevel = slotsQueue[name][1][0] renderedSlotKeys[hidenLevel] && renderedSlotKeys[hidenLevel].delete(name) @@ -128,6 +139,7 @@ export function initSlots( if (slotsQueue[name][0][0] === level) { renderedKeys && renderedKeys.add(name) } + // render the highest level slot addSlot(name, slotsQueue[name][0][1]) } From 90d2987b06ca816a087dc5f9952718c0799e674f Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Tue, 16 Jul 2024 01:56:38 +0800 Subject: [PATCH 6/7] chore(runtime-vapor): add more comments --- packages/runtime-vapor/src/componentSlots.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index a96425a7e..a205a3b3f 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -55,6 +55,15 @@ export function initSlots( /** * Maintain a queue for each slot name, so that we can * render the next slot when the highest level slot was removed + * + * |- key1: [level2, slot2], [level1, slot1] + * | + * |- key2: [level3, slot3] + * | + * |... + * + * For example, if level2 slot re-rendered and it turns out to render key3 + * then we need to take out level1 slot and render in key1 */ const slotsQueue: Record = {} rawSlots.forEach((slots, index) => { From 8d07cc9784c7ce1eb7f66f200aa695017c244b73 Mon Sep 17 00:00:00 2001 From: Doctor Wu Date: Thu, 8 Aug 2024 16:47:43 +0800 Subject: [PATCH 7/7] fix(runtime-vapor): fix slots level mix & simplify implements --- packages/runtime-vapor/src/componentSlots.ts | 39 +++----------------- 1 file changed, 5 insertions(+), 34 deletions(-) diff --git a/packages/runtime-vapor/src/componentSlots.ts b/packages/runtime-vapor/src/componentSlots.ts index a205a3b3f..15ebb207c 100644 --- a/packages/runtime-vapor/src/componentSlots.ts +++ b/packages/runtime-vapor/src/componentSlots.ts @@ -51,7 +51,6 @@ export function initSlots( } instance.slots = shallowReactive({}) - const renderedSlotKeys: Set[] = [] /** * Maintain a queue for each slot name, so that we can * render the next slot when the highest level slot was removed @@ -70,38 +69,24 @@ export function initSlots( const isDynamicSlot = isDynamicSlotFn(slots) if (isDynamicSlot) { firstEffect(instance, () => { - const renderedKeys = (renderedSlotKeys[index] ||= new Set()) let dynamicSlot = slots() // cleanup slots and re-calc to avoid diffing slots between renders // cleanup will return a slotNames array contains the slot names that need to be restored const restoreSlotNames = cleanupSlot(index) if (isArray(dynamicSlot)) { for (const slot of dynamicSlot) { - registerSlot(slot.name, slot.fn, index, renderedKeys) + registerSlot(slot.name, slot.fn, index) } } else if (dynamicSlot) { - registerSlot(dynamicSlot.name, dynamicSlot.fn, index, renderedKeys) + registerSlot(dynamicSlot.name, dynamicSlot.fn, index) } // restore after re-calc slots if (restoreSlotNames.length) { for (const key of restoreSlotNames) { - const [restoreLevel, restoreFn] = slotsQueue[key][0] - renderedSlotKeys[restoreLevel] && - renderedSlotKeys[restoreLevel].add(key) + const [_, restoreFn] = slotsQueue[key][0] addSlot(key, restoreFn) } } - // delete stale slots - for (const name of renderedKeys) { - if ( - !(isArray(dynamicSlot) - ? dynamicSlot.some(s => s.name === name) - : dynamicSlot && dynamicSlot.name === name) - ) { - renderedKeys.delete(name) - delete instance.slots[name] - } - } }) } else { for (const name in slots) { @@ -119,11 +104,11 @@ export function initSlots( slotsQueue[slotName] = slotsQueue[slotName].filter(([l]) => l !== level) if (!slotsQueue[slotName].length) { delete slotsQueue[slotName] + delete instance.slots[slotName] return } // restore next slot if the removed slots was the highest level slot if (index === 0) { - renderedSlotKeys[level] && renderedSlotKeys[level].delete(slotName) restoreSlotNames.push(slotName) } } @@ -131,24 +116,10 @@ export function initSlots( return restoreSlotNames } - function registerSlot( - name: string, - slot: Slot, - level: number, - renderedKeys?: Set, - ) { + function registerSlot(name: string, slot: Slot, level: number) { slotsQueue[name] ||= [] slotsQueue[name].push([level, slot]) slotsQueue[name].sort((a, b) => b[0] - a[0]) - // hide old slot if the registered slot is the highest level - if (slotsQueue[name][1]) { - const hidenLevel = slotsQueue[name][1][0] - renderedSlotKeys[hidenLevel] && renderedSlotKeys[hidenLevel].delete(name) - } - if (slotsQueue[name][0][0] === level) { - renderedKeys && renderedKeys.add(name) - } - // render the highest level slot addSlot(name, slotsQueue[name][0][1]) }