Skip to content

Commit a17e04e

Browse files
committed
feat(compiler): support nested component slot
1 parent 7c77682 commit a17e04e

File tree

8 files changed

+118
-10
lines changed

8 files changed

+118
-10
lines changed

packages/compiler/src/transforms/transformChildren.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,31 @@ export const transformChildren: NodeTransform = (node, context) => {
1919
const childContext = context.create(child, i)
2020
transformNode(childContext)
2121

22+
const childDynamic = childContext.dynamic
23+
2224
if (isFragment) {
2325
childContext.reference()
2426
childContext.registerTemplate()
2527

2628
if (
27-
!(childContext.dynamic.flags & DynamicFlag.NON_TEMPLATE) ||
28-
childContext.dynamic.flags & DynamicFlag.INSERT
29+
!(childDynamic.flags & DynamicFlag.NON_TEMPLATE) ||
30+
childDynamic.flags & DynamicFlag.INSERT
2931
) {
30-
context.block.returns.push(childContext.dynamic.id!)
32+
context.block.returns.push(childDynamic.id!)
3133
}
3234
} else {
3335
context.childrenTemplate.push(childContext.template)
3436
}
3537

38+
if (
39+
childDynamic.hasDynamicChild ||
40+
childDynamic.id !== undefined ||
41+
childDynamic.flags & DynamicFlag.NON_TEMPLATE ||
42+
childDynamic.flags & DynamicFlag.INSERT
43+
) {
44+
context.dynamic.hasDynamicChild = true
45+
}
46+
3647
context.dynamic.children[i] = childContext.dynamic
3748
}
3849

packages/compiler/src/transforms/transformElement.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function transformComponentElement(
101101
props: propsResult[0] ? propsResult[1] : [propsResult[1]],
102102
asset,
103103
root: singleRoot,
104-
slots: context.slots,
104+
slots: [...context.slots],
105105
once: context.inVOnce,
106106
})
107107
context.slots = []
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`compiler: children transform > efficient find 1`] = `
4+
"
5+
const n1 = t0()
6+
const n0 = _nthChild(n1, 2)
7+
_setText(n0, () => ({ msg: msg }))
8+
return n1
9+
"
10+
`;
11+
12+
exports[`compiler: children transform > efficient traversal 1`] = `
13+
"
14+
const n3 = t0()
15+
const p0 = _next(_child(n3))
16+
const n0 = _child(p0)
17+
const p1 = _next(p0)
18+
const n1 = _child(p1)
19+
const p2 = _next(p1)
20+
const n2 = _child(p2)
21+
_setText(n0, () => ({ msg: msg }))
22+
_setText(n1, () => ({ msg: msg }))
23+
_setText(n2, () => ({ msg: msg }))
24+
return n3
25+
"
26+
`;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`compiler: transform slot > nested component slot 1`] = `
4+
"
5+
const n1 = _createComponent(A, null, {
6+
"default": () => {
7+
const n0 = _createComponent(B)
8+
return n0
9+
}
10+
})
11+
return n1
12+
"
13+
`;

packages/compiler/test/transforms/transformChildren.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,28 @@ describe('compiler: children transform', () => {
112112
])
113113
expect(code).contains('_setDynamicProps(n0, [obj], true)')
114114
})
115+
116+
test('efficient traversal', () => {
117+
const { code } = compileWithElementTransform(
118+
`<div>
119+
<div>x</div>
120+
<div><span>{{ msg }}</span></div>
121+
<div><span>{{ msg }}</span></div>
122+
<div><span>{{ msg }}</span></div>
123+
</div>`,
124+
)
125+
expect(code).toMatchSnapshot()
126+
})
127+
128+
test('efficient find', () => {
129+
const { code } = compileWithElementTransform(
130+
`<div>
131+
<div>x</div>
132+
<div>x</div>
133+
<div>{{ msg }}</div>
134+
</div>`,
135+
)
136+
expect(code).contains(`const n0 = _nthChild(n1, 2)`)
137+
expect(code).toMatchSnapshot()
138+
})
115139
})

packages/compiler/test/transforms/vSlot.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, test } from 'vitest'
22
// import { ErrorCodes, NodeTypes } from '@vue/compiler-dom'
3+
import { IRNodeTypes, IRSlotType } from '@vue/compiler-vapor'
34
import {
45
// IRNodeTypes,
56
// IRSlotType,
@@ -99,6 +100,34 @@ describe('compiler: transform slot', () => {
99100
// ])
100101
})
101102

103+
test('nested component slot', () => {
104+
const { ir, code } = compileWithSlots(`<A><B/></A>`)
105+
expect(code).toMatchSnapshot()
106+
expect(ir.block.operation).toMatchObject([
107+
{
108+
type: IRNodeTypes.CREATE_COMPONENT_NODE,
109+
tag: 'A',
110+
slots: [
111+
{
112+
slotType: IRSlotType.STATIC,
113+
slots: {
114+
default: {
115+
type: IRNodeTypes.BLOCK,
116+
operation: [
117+
{
118+
type: IRNodeTypes.CREATE_COMPONENT_NODE,
119+
tag: 'B',
120+
slots: [],
121+
},
122+
],
123+
},
124+
},
125+
},
126+
],
127+
},
128+
])
129+
})
130+
102131
/*
103132
test('on component named slot', () => {
104133
const { ir, code } = compileWithSlots(

playground/main.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
import { createApp, vaporInteropPlugin } from 'vue'
1+
import {
2+
createVaporApp,
3+
// vaporInteropPlugin,
4+
} from 'vue'
25

36
const modules = import.meta.glob<any>('./src/*.tsx')
47
const mod = (
58
modules[`./src${location.pathname}.tsx`] || modules['./src/App.tsx']
69
)()
710

811
mod.then(({ default: mod }) => {
9-
const app = createApp(mod)
10-
app.use(vaporInteropPlugin).mount('#app')
12+
const app = createVaporApp(mod)
13+
// app.use(vaporInteropPlugin).
14+
.mount('#app')
1115

1216
// @ts-expect-error
1317
globalThis.unmount = () => {
18+
// @ts-expect-error
1419
app.unmount()
1520
}
1621
})

playground/vite.config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { defineConfig } from 'vite'
22
import Inspect from 'vite-plugin-inspect'
33
import VueJsxVapor from 'unplugin-vue-jsx-vapor/vite'
4-
import VueJsx from '@vitejs/plugin-vue-jsx'
4+
// import VueJsx from '@vitejs/plugin-vue-jsx'
55

66
export default defineConfig({
77
plugins: [
88
VueJsxVapor({
9-
interop: true,
9+
// interop: true,
1010
}),
11-
VueJsx(),
11+
// VueJsx(),
1212
Inspect(),
1313
],
1414
})

0 commit comments

Comments
 (0)