Skip to content

Commit 6958051

Browse files
Doctor-wusxzz
andauthored
feat: implement setRef update (#191)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
1 parent 8dea04b commit 6958051

File tree

9 files changed

+702
-54
lines changed

9 files changed

+702
-54
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformRef.spec.ts.snap

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`compiler: template ref transform > dynamic ref 1`] = `
4-
"import { setRef as _setRef, template as _template } from 'vue/vapor';
4+
"import { renderEffect as _renderEffect, setRef as _setRef, template as _template } from 'vue/vapor';
55
const t0 = _template("<div></div>")
66
77
export function render(_ctx) {
88
const n0 = t0()
9-
_setRef(n0, _ctx.foo)
9+
let r0
10+
_renderEffect(() => r0 = _setRef(n0, _ctx.foo, r0))
1011
return n0
1112
}"
1213
`;
@@ -18,7 +19,7 @@ const t0 = _template("<div></div>")
1819
export function render(_ctx) {
1920
const n0 = _createFor(() => ([1,2,3]), (_block) => {
2021
const n2 = t0()
21-
_setRef(n2, "foo", true)
22+
_setRef(n2, "foo", void 0, true)
2223
return [n2, () => {}]
2324
})
2425
return n0

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`compiler: template ref transform > dynamic ref 1`] = `
4-
"import { setRef as _setRef, template as _template } from 'vue/vapor';
4+
"import { renderEffect as _renderEffect, setRef as _setRef, template as _template } from 'vue/vapor';
55
const t0 = _template("<div></div>")
66
77
export function render(_ctx) {
88
const n0 = t0()
9-
_setRef(n0, _ctx.foo)
9+
let r0
10+
_renderEffect(() => r0 = _setRef(n0, _ctx.foo, r0))
1011
return n0
1112
}"
1213
`;
@@ -18,7 +19,7 @@ const t0 = _template("<div></div>")
1819
export function render(_ctx) {
1920
const n0 = _createFor(() => ([1,2,3]), (_block) => {
2021
const n2 = t0()
21-
_setRef(n2, "foo", true)
22+
_setRef(n2, "foo", void 0, true)
2223
return [n2, () => {}]
2324
})
2425
return n0

packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts

+40-40
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ describe('compiler: template ref transform', () => {
4343
},
4444
},
4545
})
46-
4746
expect(code).matchSnapshot()
4847
expect(code).contains('_setRef(n0, "foo")')
4948
})
@@ -56,21 +55,28 @@ describe('compiler: template ref transform', () => {
5655
flags: DynamicFlag.REFERENCED,
5756
})
5857
expect(ir.template).toEqual(['<div></div>'])
59-
expect(ir.block.operation).lengthOf(1)
60-
expect(ir.block.operation[0]).toMatchObject({
61-
type: IRNodeTypes.SET_TEMPLATE_REF,
62-
element: 0,
63-
value: {
64-
content: 'foo',
65-
isStatic: false,
66-
loc: {
67-
start: { line: 1, column: 12, offset: 11 },
68-
end: { line: 1, column: 15, offset: 14 },
69-
},
58+
expect(ir.block.operation).toMatchObject([
59+
{
60+
type: IRNodeTypes.DECLARE_OLD_REF,
61+
id: 0,
7062
},
71-
})
63+
])
64+
expect(ir.block.effect).toMatchObject([
65+
{
66+
operations: [
67+
{
68+
type: IRNodeTypes.SET_TEMPLATE_REF,
69+
element: 0,
70+
value: {
71+
content: 'foo',
72+
isStatic: false,
73+
},
74+
},
75+
],
76+
},
77+
])
7278
expect(code).matchSnapshot()
73-
expect(code).contains('_setRef(n0, _ctx.foo)')
79+
expect(code).contains('_setRef(n0, _ctx.foo, r0)')
7480
})
7581

7682
test('ref + v-if', () => {
@@ -82,21 +88,17 @@ describe('compiler: template ref transform', () => {
8288
expect(ir.block.operation[0].type).toBe(IRNodeTypes.IF)
8389

8490
const { positive } = ir.block.operation[0] as IfIRNode
85-
86-
expect(positive.operation).lengthOf(1)
87-
expect(positive.operation[0]).toMatchObject({
88-
type: IRNodeTypes.SET_TEMPLATE_REF,
89-
element: 2,
90-
value: {
91-
content: 'foo',
92-
isStatic: true,
93-
loc: {
94-
start: { line: 1, column: 10, offset: 9 },
95-
end: { line: 1, column: 15, offset: 14 },
91+
expect(positive.operation).toMatchObject([
92+
{
93+
type: IRNodeTypes.SET_TEMPLATE_REF,
94+
element: 2,
95+
value: {
96+
content: 'foo',
97+
isStatic: true,
9698
},
99+
effect: false,
97100
},
98-
})
99-
101+
])
100102
expect(code).matchSnapshot()
101103
expect(code).contains('_setRef(n2, "foo")')
102104
})
@@ -107,21 +109,19 @@ describe('compiler: template ref transform', () => {
107109
)
108110

109111
const { render } = ir.block.operation[0] as ForIRNode
110-
expect(render.operation).lengthOf(1)
111-
expect(render.operation[0]).toMatchObject({
112-
type: IRNodeTypes.SET_TEMPLATE_REF,
113-
element: 2,
114-
value: {
115-
content: 'foo',
116-
isStatic: true,
117-
loc: {
118-
start: { line: 1, column: 10, offset: 9 },
119-
end: { line: 1, column: 15, offset: 14 },
112+
expect(render.operation).toMatchObject([
113+
{
114+
type: IRNodeTypes.SET_TEMPLATE_REF,
115+
element: 2,
116+
value: {
117+
content: 'foo',
118+
isStatic: true,
120119
},
120+
refFor: true,
121+
effect: false,
121122
},
122-
refFor: true,
123-
})
123+
])
124124
expect(code).matchSnapshot()
125-
expect(code).contains('_setRef(n2, "foo", true)')
125+
expect(code).contains('_setRef(n2, "foo", void 0, true)')
126126
})
127127
})

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { genSetHtml } from './html'
77
import { genIf } from './if'
88
import { genSetModelValue } from './modelValue'
99
import { genDynamicProps, genSetProp } from './prop'
10-
import { genSetTemplateRef } from './templateRef'
10+
import { genDeclareOldRef, genSetTemplateRef } from './templateRef'
1111
import { genCreateTextNode, genSetText } from './text'
1212
import {
1313
type CodeFragment,
@@ -59,6 +59,8 @@ export function genOperation(
5959
return genFor(oper, context)
6060
case IRNodeTypes.CREATE_COMPONENT_NODE:
6161
return genCreateComponent(oper, context)
62+
case IRNodeTypes.DECLARE_OLD_REF:
63+
return genDeclareOldRef(oper)
6264
}
6365

6466
return []

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { genExpression } from './expression'
22
import type { CodegenContext } from '../generate'
3-
import type { SetTemplateRefIRNode } from '../ir'
3+
import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
44
import { type CodeFragment, NEWLINE, genCall } from './utils'
55

66
export function genSetTemplateRef(
@@ -10,11 +10,17 @@ export function genSetTemplateRef(
1010
const { vaporHelper } = context
1111
return [
1212
NEWLINE,
13+
oper.effect && `r${oper.element} = `,
1314
...genCall(
1415
vaporHelper('setRef'),
1516
`n${oper.element}`,
1617
genExpression(oper.value, context),
18+
oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
1719
oper.refFor && 'true',
1820
),
1921
]
2022
}
23+
24+
export function genDeclareOldRef(oper: DeclareOldRefIRNode): CodeFragment[] {
25+
return [NEWLINE, `let r${oper.id}`]
26+
}

packages/compiler-vapor/src/ir.ts

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export enum IRNodeTypes {
3232
CREATE_COMPONENT_NODE,
3333

3434
WITH_DIRECTIVE,
35+
DECLARE_OLD_REF, // consider make it more general
3536

3637
IF,
3738
FOR,
@@ -158,6 +159,7 @@ export interface SetTemplateRefIRNode extends BaseIRNode {
158159
element: number
159160
value: SimpleExpressionNode
160161
refFor: boolean
162+
effect: boolean
161163
}
162164

163165
export interface SetModelValueIRNode extends BaseIRNode {
@@ -207,6 +209,11 @@ export interface CreateComponentIRNode extends BaseIRNode {
207209
root: boolean
208210
}
209211

212+
export interface DeclareOldRefIRNode extends BaseIRNode {
213+
type: IRNodeTypes.DECLARE_OLD_REF
214+
id: number
215+
}
216+
210217
export type IRNode = OperationNode | RootIRNode
211218
export type OperationNode =
212219
| SetPropIRNode
@@ -224,6 +231,7 @@ export type OperationNode =
224231
| IfIRNode
225232
| ForIRNode
226233
| CreateComponentIRNode
234+
| DeclareOldRefIRNode
227235

228236
export enum DynamicFlag {
229237
NONE = 0,

packages/compiler-vapor/src/transforms/transformTemplateRef.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
import type { NodeTransform } from '../transform'
77
import { IRNodeTypes } from '../ir'
88
import { normalizeBindShorthand } from './vBind'
9-
import { findProp } from '../utils'
9+
import { findProp, isConstantExpression } from '../utils'
1010
import { EMPTY_EXPRESSION } from './utils'
1111

1212
export const transformTemplateRef: NodeTransform = (node, context) => {
@@ -24,11 +24,20 @@ export const transformTemplateRef: NodeTransform = (node, context) => {
2424
: EMPTY_EXPRESSION
2525
}
2626

27-
return () =>
28-
context.registerOperation({
27+
return () => {
28+
const id = context.reference()
29+
const effect = !isConstantExpression(value)
30+
effect &&
31+
context.registerOperation({
32+
type: IRNodeTypes.DECLARE_OLD_REF,
33+
id,
34+
})
35+
context.registerEffect([value], {
2936
type: IRNodeTypes.SET_TEMPLATE_REF,
30-
element: context.reference(),
37+
element: id,
3138
value,
3239
refFor: !!context.inVFor,
40+
effect,
3341
})
42+
}
3443
}

0 commit comments

Comments
 (0)