Skip to content

Commit dccd6e3

Browse files
authored
Merge branch 'main' into feat/runtime-vapor-createSlot
2 parents f47bd32 + db140a1 commit dccd6e3

File tree

7 files changed

+136
-11
lines changed

7 files changed

+136
-11
lines changed

packages/compiler-vapor/src/generate.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ export class CodegenContext {
4141
delegates = new Set<string>()
4242

4343
identifiers: Record<string, string[]> = Object.create(null)
44+
45+
genEffects: Array<
46+
(effects: IREffect[], context: CodegenContext) => CodeFragment[]
47+
> = []
48+
4449
withId = <T>(fn: () => T, map: Record<string, string | null>): T => {
4550
const { identifiers } = this
4651
const ids = Object.keys(map)
@@ -55,7 +60,6 @@ export class CodegenContext {
5560

5661
return ret
5762
}
58-
genEffect?: (effects: IREffect[]) => CodeFragment[]
5963

6064
constructor(
6165
public ir: RootIRNode,

packages/compiler-vapor/src/generators/block.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ export function genBlockContent(
5050
}
5151

5252
push(...genOperations(operation, context))
53-
push(...(context.genEffect || genEffects)(effect, context))
53+
push(
54+
...(context.genEffects.length
55+
? context.genEffects[context.genEffects.length - 1]
56+
: genEffects)(effect, context),
57+
)
5458

5559
push(NEWLINE, `return `)
5660

packages/compiler-vapor/src/generators/for.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export function genFor(
1818
oper: ForIRNode,
1919
context: CodegenContext,
2020
): CodeFragment[] {
21-
const { vaporHelper } = context
21+
const { vaporHelper, genEffects } = context
2222
const { source, value, key, index, render, keyProp } = oper
2323

2424
const rawValue = value && value.content
@@ -27,7 +27,8 @@ export function genFor(
2727

2828
const sourceExpr = ['() => (', ...genExpression(source, context), ')']
2929
let updateFn = '_updateEffect'
30-
context.genEffect = genEffectInFor
30+
31+
genEffects.push(genEffectInFor)
3132

3233
const idMap: Record<string, string> = {}
3334
if (rawValue) idMap[rawValue] = `_block.s[0]`
@@ -65,7 +66,7 @@ export function genFor(
6566
]
6667
}
6768

68-
context.genEffect = undefined
69+
genEffects.pop()
6970

7071
return [
7172
NEWLINE,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import type { SetupContext } from '../src/component'
2+
import {
3+
createComponent,
4+
defineComponent,
5+
ref,
6+
template,
7+
useAttrs,
8+
useSlots,
9+
} from '../src'
10+
import { makeRender } from './_utils'
11+
12+
const define = makeRender<any>()
13+
14+
describe('SFC <script setup> helpers', () => {
15+
test.todo('should warn runtime usage', () => {})
16+
17+
test('useSlots / useAttrs (no args)', () => {
18+
let slots: SetupContext['slots'] | undefined
19+
let attrs: SetupContext['attrs'] | undefined
20+
21+
const Comp = {
22+
setup() {
23+
slots = useSlots()
24+
attrs = useAttrs()
25+
},
26+
}
27+
const count = ref(0)
28+
const passedAttrs = { id: () => count.value }
29+
const passedSlots = {
30+
default: () => template('')(),
31+
x: () => template('')(),
32+
}
33+
34+
const { render } = define({
35+
render: () => createComponent(Comp, passedAttrs, passedSlots),
36+
})
37+
render()
38+
39+
expect(typeof slots!.default).toBe('function')
40+
expect(typeof slots!.x).toBe('function')
41+
expect(attrs).toMatchObject({ id: 0 })
42+
43+
count.value++
44+
expect(attrs).toMatchObject({ id: 1 })
45+
})
46+
47+
test('useSlots / useAttrs (with args)', () => {
48+
let slots: SetupContext['slots'] | undefined
49+
let attrs: SetupContext['attrs'] | undefined
50+
let ctx: SetupContext | undefined
51+
const Comp = defineComponent({
52+
setup(_, _ctx) {
53+
slots = useSlots()
54+
attrs = useAttrs()
55+
ctx = _ctx
56+
},
57+
})
58+
const { render } = define({ render: () => createComponent(Comp) })
59+
render()
60+
expect(slots).toBe(ctx!.slots)
61+
expect(attrs).toBe(ctx!.attrs)
62+
})
63+
64+
describe.todo('mergeDefaults', () => {
65+
test.todo('object syntax', () => {})
66+
test.todo('array syntax', () => {})
67+
test.todo('merging with skipFactory', () => {})
68+
test.todo('should warn missing', () => {})
69+
})
70+
71+
describe('mergeModels', () => {
72+
test.todo('array syntax', () => {})
73+
test.todo('object syntax', () => {})
74+
test.todo('overwrite', () => {})
75+
})
76+
77+
test.todo('createPropsRestProxy', () => {})
78+
79+
describe.todo('withAsyncContext', () => {
80+
test.todo('basic', async () => {})
81+
test.todo('error handling', async () => {})
82+
test.todo('should not leak instance on multiple awaits', async () => {})
83+
test.todo('should not leak on multiple awaits + error', async () => {})
84+
test.todo('race conditions', async () => {})
85+
test.todo('should teardown in-scope effects', async () => {})
86+
})
87+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {
2+
type SetupContext,
3+
createSetupContext,
4+
getCurrentInstance,
5+
} from './component'
6+
import { warn } from './warning'
7+
8+
// TODO: warning compiler-macros runtime usages
9+
10+
export function useSlots(): SetupContext['slots'] {
11+
return getContext().slots
12+
}
13+
14+
export function useAttrs(): SetupContext['attrs'] {
15+
return getContext().attrs
16+
}
17+
18+
function getContext(): SetupContext {
19+
const i = getCurrentInstance()!
20+
if (__DEV__ && !i) {
21+
warn(`useContext() called without active instance.`)
22+
}
23+
return i.setupContext || (i.setupContext = createSetupContext(i))
24+
}

packages/runtime-vapor/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ export {
111111
onErrorCaptured,
112112
// onServerPrefetch,
113113
} from './apiLifecycle'
114+
export { useAttrs, useSlots } from './apiSetupHelpers'
114115
export {
115116
createVaporApp,
116117
type App,

playground/src/sub-comp.vue

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
22
import {
3-
getCurrentInstance,
43
onBeforeMount,
54
onBeforeUnmount,
65
onMounted,
76
onUnmounted,
7+
useAttrs,
88
watchEffect,
99
} from 'vue/vapor'
1010
@@ -14,7 +14,7 @@ const props = defineProps<{
1414
baz: string
1515
}>()
1616
17-
const attrs = getCurrentInstance()?.attrs
17+
const attrs = useAttrs()
1818
1919
watchEffect(() => {
2020
console.log({ ...attrs })
@@ -29,8 +29,12 @@ onUnmounted(() => console.log('sub: unmounted'))
2929
</script>
3030

3131
<template>
32-
<div>sub-comp</div>
33-
{{ props }}
34-
{{ attrs }}
35-
{{ keys(attrs) }}
32+
<h2>sub-comp</h2>
33+
<p>
34+
props: {{ props }}
35+
<br />
36+
attrs: {{ attrs }}
37+
<br />
38+
keys(attrs): {{ keys(attrs) }}
39+
</p>
3640
</template>

0 commit comments

Comments
 (0)