Merge branch 'edison/feat/fowardedSlots' into edison/testVapor

This commit is contained in:
daiwei 2025-06-20 10:23:43 +08:00
commit 1bb0fa1c87
3 changed files with 34 additions and 33 deletions

View File

@ -796,7 +796,7 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot(with fallback) > vapor slot', async () => { test('vdom slot > vapor forwarded slot(with fallback) > vapor slot', async () => {
@ -820,7 +820,7 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>forwarded fallback</div>') expect(root.innerHTML).toBe('<div>forwarded fallback</div><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot > vdom slot', async () => { test('vdom slot > vapor forwarded slot > vdom slot', async () => {
@ -1083,11 +1083,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot--><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot--><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot (multiple) > vdom forwarded slot(with fallback) > vdom slot', async () => { test('vdom slot > vapor forwarded slot (multiple) > vdom forwarded slot(with fallback) > vdom slot', async () => {
@ -1116,12 +1116,12 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe( expect(root.innerHTML).toBe(
'<!--slot--><!--slot--><div>vdom fallback</div>', '<div>vdom fallback</div><!--slot--><!--slot-->',
) )
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot--><!--slot-->')
}) })
test('vdom slot > vdom forwarded slot > vapor slot', async () => { test('vdom slot > vdom forwarded slot > vapor slot', async () => {
@ -1168,11 +1168,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vdom forwarded slot (multiple) > vapor forwarded slot > vdom slot', async () => { test('vdom slot > vdom forwarded slot (multiple) > vapor forwarded slot > vdom slot', async () => {
@ -1197,11 +1197,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vdom forwarded slot (multiple) > vapor forwarded slot(with fallback) > vdom slot', async () => { test('vdom slot > vdom forwarded slot (multiple) > vapor forwarded slot(with fallback) > vdom slot', async () => {
@ -1229,11 +1229,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>vapor fallback</div>') expect(root.innerHTML).toBe('<div>vapor fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot > vapor forwarded slot > vdom slot', async () => { test('vdom slot > vapor forwarded slot > vapor forwarded slot > vdom slot', async () => {
@ -1257,11 +1257,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot > vdom slot', async () => { test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot > vdom slot', async () => {
@ -1286,11 +1286,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>vapor1 fallback</div>') expect(root.innerHTML).toBe('<div>vapor1 fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot > vapor forwarded slot(with fallback) > vdom slot', async () => { test('vdom slot > vapor forwarded slot > vapor forwarded slot(with fallback) > vdom slot', async () => {
@ -1317,11 +1317,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>vapor2 fallback</div>') expect(root.innerHTML).toBe('<div>vapor2 fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot > vapor forwarded slot > vapor slot', async () => { test('vdom slot > vapor forwarded slot > vapor forwarded slot > vapor slot', async () => {
@ -1344,11 +1344,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><div>fallback</div>') expect(root.innerHTML).toBe('<div>fallback</div><!--slot--><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot--><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot(with fallback) > vdom slot', async () => { test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot(with fallback) > vdom slot', async () => {
@ -1376,11 +1376,11 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><div>vapor1 fallback</div>') expect(root.innerHTML).toBe('<div>vapor1 fallback</div><!--slot-->')
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot-->')
}) })
test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot(with fallback) > vapor slot', async () => { test('vdom slot > vapor forwarded slot(with fallback) > vapor forwarded slot(with fallback) > vapor slot', async () => {
@ -1409,12 +1409,12 @@ describe('component: slots', () => {
show.value = false show.value = false
await nextTick() await nextTick()
expect(root.innerHTML).toBe( expect(root.innerHTML).toBe(
'<!--slot--><!--slot--><div>vapor1 fallback</div>', '<div>vapor1 fallback</div><!--slot--><!--slot-->',
) )
show.value = true show.value = true
await nextTick() await nextTick()
expect(root.innerHTML).toBe('<!--slot--><!--slot--><span>bar</span>') expect(root.innerHTML).toBe('<span>bar</span><!--slot--><!--slot-->')
}) })
test('vdom slot > vdom forwarded slot(with fallback) > vdom forwarded slot(with fallback) > vapor slot', async () => { test('vdom slot > vdom forwarded slot(with fallback) > vdom forwarded slot(with fallback) > vapor slot', async () => {

View File

@ -216,13 +216,16 @@ export function insert(
insert(b, parent, anchor) insert(b, parent, anchor)
} }
} else { } else {
if (block.anchor) {
insert(block.anchor, parent, anchor)
anchor = block.anchor
}
// fragment // fragment
if (block.insert) { if (block.insert) {
block.insert(parent, anchor, (block as TransitionBlock).$transition) block.insert(parent, anchor, (block as TransitionBlock).$transition)
} else { } else {
insert(block.nodes, parent, anchor, parentSuspense) insert(block.nodes, parent, anchor, parentSuspense)
} }
if (block.anchor) insert(block.anchor, parent, anchor)
} }
} }

View File

@ -138,16 +138,10 @@ const vaporInteropImpl: Omit<
slot(n1: VNode, n2: VNode, container, anchor) { slot(n1: VNode, n2: VNode, container, anchor) {
if (!n1) { if (!n1) {
// mount // mount
const selfAnchor = (n2.el = n2.anchor = createTextNode()) let selfAnchor: Node | undefined
insert(selfAnchor, container, anchor)
const { slot, fallback } = n2.vs! const { slot, fallback } = n2.vs!
const propsRef = (n2.vs!.ref = shallowRef(n2.props)) const propsRef = (n2.vs!.ref = shallowRef(n2.props))
const slotBlock = slot(new Proxy(propsRef, vaporSlotPropsProxyHandler)) const slotBlock = slot(new Proxy(propsRef, vaporSlotPropsProxyHandler))
// TODO fallback for slot with v-if content
// fallback is a vnode slot function here, and slotBlock, if a DynamicFragment,
// expects a Vapor BlockFn as fallback
// fallback
// forwarded vdom slot without its own fallback, use the fallback provided by // forwarded vdom slot without its own fallback, use the fallback provided by
// the slot outlet // the slot outlet
if (slotBlock instanceof DynamicFragment) { if (slotBlock instanceof DynamicFragment) {
@ -157,11 +151,15 @@ const vaporInteropImpl: Omit<
ensureVDOMSlotFallback(nodes, fallback) ensureVDOMSlotFallback(nodes, fallback)
nodes = nodes.nodes nodes = nodes.nodes
} }
// use fragment's anchor when possible
selfAnchor = slotBlock.anchor
} else if (isFragment(slotBlock)) { } else if (isFragment(slotBlock)) {
ensureVDOMSlotFallback(slotBlock, fallback) ensureVDOMSlotFallback(slotBlock, fallback)
selfAnchor = slotBlock.anchor!
} }
// TODO use fragment's anchor as selfAnchor? if (!selfAnchor) selfAnchor = createTextNode()
insert((n2.el = n2.anchor = selfAnchor), container, anchor)
insert((n2.vb = slotBlock), container, selfAnchor) insert((n2.vb = slotBlock), container, selfAnchor)
} else { } else {
// update // update