Skip to content

Commit b2259a5

Browse files
authored
refactor: general destructuring function (#221)
1 parent 5a0a2bf commit b2259a5

File tree

8 files changed

+69
-83
lines changed

8 files changed

+69
-83
lines changed

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

+9-18
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

33
exports[`compiler: v-for > array de-structured value 1`] = `
4-
"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
4+
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
55
const t0 = _template("<div></div>")
66
77
export function render(_ctx) {
8-
const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
8+
const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [[id, ...other], index] = _state) => [id, other, index], (_ctx0) => {
99
const n2 = t0()
1010
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
1111
return n2
12-
}, ([id, ...other], index) => (id), null, null, false, _state => {
13-
const [[id, ...other], index] = _state
14-
return [id, other, index]
15-
})
12+
}), ([id, ...other], index) => (id))
1613
return n0
1714
}"
1815
`;
@@ -69,35 +66,29 @@ export function render(_ctx) {
6966
`;
7067

7168
exports[`compiler: v-for > object de-structured value 1`] = `
72-
"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
69+
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
7370
const t0 = _template("<div></div>")
7471
7572
export function render(_ctx) {
76-
const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
73+
const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [{ id, ...other }, index] = _state) => [id, other, index], (_ctx0) => {
7774
const n2 = t0()
7875
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx0[1] + _ctx0[2]))
7976
return n2
80-
}, ({ id, ...other }, index) => (id), null, null, false, _state => {
81-
const [{ id, ...other }, index] = _state
82-
return [id, other, index]
83-
})
77+
}), ({ id, ...other }, index) => (id))
8478
return n0
8579
}"
8680
`;
8781

8882
exports[`compiler: v-for > v-for aliases w/ complex expressions 1`] = `
89-
"import { renderEffect as _renderEffect, setText as _setText, createFor as _createFor, template as _template } from 'vue/vapor';
83+
"import { renderEffect as _renderEffect, setText as _setText, withDestructure as _withDestructure, createFor as _createFor, template as _template } from 'vue/vapor';
9084
const t0 = _template("<div></div>")
9185
9286
export function render(_ctx) {
93-
const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
87+
const n0 = _createFor(() => (_ctx.list), _withDestructure((_state, [{ foo = bar, baz: [qux = quux] }] = _state) => [foo, qux], (_ctx0) => {
9488
const n2 = t0()
9589
_renderEffect(() => _setText(n2, _ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux))
9690
return n2
97-
}, null, null, null, false, _state => {
98-
const [{ foo = bar, baz: [qux = quux] }] = _state
99-
return [foo, qux]
100-
})
91+
}))
10192
return n0
10293
}"
10394
`;

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

+9-3
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ describe('compiler: v-for', () => {
129129
`<div v-for="( { id, ...other }, index) in list" :key="id">{{ id + other + index }}</div>`,
130130
)
131131
expect(code).matchSnapshot()
132-
expect(code).contains(`return [id, other, index]`)
132+
expect(code).contains(
133+
`(_state, [{ id, ...other }, index] = _state) => [id, other, index]`,
134+
)
133135
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
134136
expect(ir.block.operation[0]).toMatchObject({
135137
type: IRNodeTypes.FOR,
@@ -162,7 +164,9 @@ describe('compiler: v-for', () => {
162164
`<div v-for="([id, ...other], index) in list" :key="id">{{ id + other + index }}</div>`,
163165
)
164166
expect(code).matchSnapshot()
165-
expect(code).contains(`return [id, other, index]`)
167+
expect(code).contains(
168+
`(_state, [[id, ...other], index] = _state) => [id, other, index]`,
169+
)
166170
expect(code).contains(`_ctx0[0] + _ctx0[1] + _ctx0[2]`)
167171
expect(ir.block.operation[0]).toMatchObject({
168172
type: IRNodeTypes.FOR,
@@ -197,7 +201,9 @@ describe('compiler: v-for', () => {
197201
</div>`,
198202
)
199203
expect(code).matchSnapshot()
200-
expect(code).contains(`return [foo, qux]`)
204+
expect(code).contains(
205+
`(_state, [{ foo = bar, baz: [qux = quux] }] = _state) => [foo, qux]`,
206+
)
201207
expect(code).contains(
202208
`_ctx0[0] + _ctx.bar + _ctx.baz + _ctx0[1] + _ctx.quux`,
203209
)

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

+11-17
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import type { ForIRNode } from '../ir'
66
import {
77
type CodeFragment,
88
DELIMITERS_ARRAY,
9-
INDENT_END,
10-
INDENT_START,
119
NEWLINE,
1210
genCall,
1311
genMulti,
@@ -51,7 +49,7 @@ export function genFor(
5149
if (rawKey) idMap[rawKey] = `${propsName}[${idsOfValue.size}]`
5250
if (rawIndex) idMap[rawIndex] = `${propsName}[${idsOfValue.size + 1}]`
5351

54-
const blockFn = context.withId(
52+
let blockFn = context.withId(
5553
() => genBlock(render, context, [propsName]),
5654
idMap,
5755
)
@@ -77,31 +75,28 @@ export function genFor(
7775
]
7876
}
7977

80-
let destructureAssignmentFn: CodeFragment[] | false = false
8178
if (isDestructureAssignment) {
8279
const idMap: Record<string, null> = {}
8380
idsOfValue.forEach(id => (idMap[id] = null))
8481
if (rawKey) idMap[rawKey] = null
8582
if (rawIndex) idMap[rawIndex] = null
86-
destructureAssignmentFn = [
87-
'_state => {',
88-
INDENT_START,
89-
NEWLINE,
90-
'const ',
83+
const destructureAssignmentFn: CodeFragment[] = [
84+
'(_state, ',
9185
...genMulti(
9286
DELIMITERS_ARRAY,
9387
rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined,
9488
rawKey ? rawKey : rawIndex ? '__' : undefined,
9589
rawIndex,
9690
),
97-
' = _state',
98-
NEWLINE,
99-
'return ',
91+
' = _state) => ',
10092
...genMulti(DELIMITERS_ARRAY, ...idsOfValue, rawKey, rawIndex),
101-
INDENT_END,
102-
NEWLINE,
103-
'}',
10493
]
94+
95+
blockFn = genCall(
96+
vaporHelper('withDestructure'),
97+
destructureAssignmentFn,
98+
blockFn,
99+
)
105100
}
106101

107102
return [
@@ -114,8 +109,7 @@ export function genFor(
114109
getKeyFn,
115110
false, // todo: getMemo
116111
false, // todo: hydrationNode
117-
(once && 'true') || (destructureAssignmentFn && 'false'),
118-
destructureAssignmentFn,
112+
once && 'true',
119113
),
120114
]
121115
}

packages/runtime-vapor/__tests__/for.spec.ts

+18-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
renderEffect,
88
shallowRef,
99
template,
10+
withDestructure,
1011
withDirectives,
1112
} from '../src'
1213
import { makeRender } from './_utils'
@@ -318,25 +319,24 @@ describe('createFor', () => {
318319
const { host } = define(() => {
319320
const n1 = createFor(
320321
() => list.value,
321-
state => {
322-
const span = document.createElement('li')
323-
renderEffect(() => {
324-
const [name, key, index] = state
325-
span.innerHTML = `${key}. ${name}`
326-
327-
// index should be undefined if source is not an object
328-
expect(index).toBe(undefined)
329-
})
330-
return span
331-
},
322+
withDestructure(
323+
state => {
324+
const [{ name }, key, index] = state
325+
return [name, key, index]
326+
},
327+
state => {
328+
const span = document.createElement('li')
329+
renderEffect(() => {
330+
const [name, key, index] = state
331+
span.innerHTML = `${key}. ${name}`
332+
333+
// index should be undefined if source is not an object
334+
expect(index).toBe(undefined)
335+
})
336+
return span
337+
},
338+
),
332339
item => item.name,
333-
undefined,
334-
undefined,
335-
false,
336-
state => {
337-
const [{ name }, key, index] = state
338-
return [name, key, index]
339-
},
340340
)
341341
return n1
342342
}).render()

packages/runtime-vapor/src/apiCreateFor.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
invokeWithUpdate,
2727
} from './directivesChildFragment'
2828
import type { DynamicSlot } from './componentSlots'
29-
import { destructuring } from './destructuring'
3029

3130
interface ForBlock extends Fragment {
3231
scope: BlockEffectScope
@@ -49,7 +48,6 @@ export const createFor = (
4948
getMemo?: (item: any, key: any, index?: number) => any[],
5049
hydrationNode?: Node,
5150
once?: boolean,
52-
assignment?: (state: any[]) => any[],
5351
): Fragment => {
5452
let isMounted = false
5553
let oldBlocks: ForBlock[] = []
@@ -283,11 +281,7 @@ export const createFor = (
283281
memo: getMemo && getMemo(item, key, index),
284282
[fragmentKey]: true,
285283
})
286-
const proxyState = proxyRefs(state)
287-
const itemCtx = assignment
288-
? destructuring(scope, proxyState, assignment)
289-
: proxyState
290-
block.nodes = scope.run(() => renderItem(itemCtx))!
284+
block.nodes = scope.run(() => renderItem(proxyRefs(state)))!
291285

292286
invokeWithMount(scope, () => {
293287
// TODO v-memo
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { shallowReactive } from '@vue/reactivity'
2+
import { renderEffect } from './renderEffect'
3+
4+
export function withDestructure<P extends any[], R>(
5+
assign: (...args: P) => any[],
6+
block: (ctx: any[]) => R,
7+
): (...args: P) => R {
8+
return (...args: P) => {
9+
const ctx = shallowReactive<any[]>([])
10+
renderEffect(() => {
11+
const res = assign(...args)
12+
const len = res.length
13+
for (let i = 0; i < len; i++) {
14+
ctx[i] = res[i]
15+
}
16+
})
17+
return block(ctx)
18+
}
19+
}

packages/runtime-vapor/src/destructuring.ts

-20
This file was deleted.

packages/runtime-vapor/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ export { createComponent } from './apiCreateComponent'
135135
export { resolveComponent, resolveDirective } from './helpers/resolveAssets'
136136
export { toHandlers } from './helpers/toHandlers'
137137

138+
export { withDestructure } from './destructure'
139+
138140
// **Internal** DOM-only runtime directive helpers
139141
export {
140142
vModelText,

0 commit comments

Comments
 (0)