Skip to content

Commit 242cc15

Browse files
committed
refactor(vapor): use bitwise flags for v-for runtime optimizations
1 parent 63cf2ee commit 242cc15

File tree

6 files changed

+45
-14
lines changed

6 files changed

+45
-14
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function render(_ctx) {
2323
const n2 = t0()
2424
_setTemplateRef(n2, "foo", void 0, true)
2525
return n2
26-
}, null, null, true)
26+
}, null, 4)
2727
return n0
2828
}"
2929
`;

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function render(_ctx) {
7777
const x4 = _child(n4)
7878
_renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
7979
return n4
80-
}, null, null, null, true)
80+
}, null, 1)
8181
_insert(n2, n5)
8282
return n5
8383
})

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export function render(_ctx) {
6868
const n0 = _createFor(() => (_ctx.list), (_for_item0) => {
6969
const n2 = t0()
7070
return n2
71-
}, null, null, true)
71+
}, null, 4)
7272
return n0
7373
}"
7474
`;

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

+13-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { ForIRNode } from '../ir'
1010
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
1111
import type { Identifier } from '@babel/types'
1212
import { parseExpression } from '@babel/parser'
13+
import { VaporVForFlags } from '../../../shared/src/vaporFlags'
1314

1415
export function genFor(
1516
oper: ForIRNode,
@@ -80,6 +81,17 @@ export function genFor(
8081
const blockFn = context.withId(() => genBlock(render, context, args), idMap)
8182
exitScope()
8283

84+
let flags = 0
85+
if (onlyChild) {
86+
flags |= VaporVForFlags.FAST_REMOVE
87+
}
88+
if (component) {
89+
flags |= VaporVForFlags.IS_COMPONENT
90+
}
91+
if (once) {
92+
flags |= VaporVForFlags.ONCE
93+
}
94+
8395
return [
8496
NEWLINE,
8597
`const n${id} = `,
@@ -88,9 +100,7 @@ export function genFor(
88100
sourceExpr,
89101
blockFn,
90102
genCallback(keyProp),
91-
component && 'true',
92-
once && 'true',
93-
onlyChild && `true`,
103+
flags ? String(flags) : undefined,
94104
// todo: hydrationNode
95105
),
96106
]

packages/runtime-vapor/src/apiCreateFor.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { warn } from '@vue/runtime-dom'
2121
import { currentInstance, isVaporComponent } from './component'
2222
import type { DynamicSlot } from './componentSlots'
2323
import { renderEffect } from './renderEffect'
24+
import { VaporVForFlags } from '../../shared/src/vaporFlags'
2425

2526
class ForBlock extends VaporFragment {
2627
scope: EffectScope | undefined
@@ -64,13 +65,7 @@ export const createFor = (
6465
index: ShallowRef<number | undefined>,
6566
) => Block,
6667
getKey?: (item: any, key: any, index?: number) => any,
67-
/**
68-
* Whether this v-for is used directly on a component. If true, we can avoid
69-
* creating an extra fragment / scope for each block
70-
*/
71-
isComponent = false,
72-
once?: boolean,
73-
canUseFastRemove?: boolean,
68+
flags = 0,
7469
// hydrationNode?: Node,
7570
): VaporFragment => {
7671
let isMounted = false
@@ -80,6 +75,8 @@ export const createFor = (
8075
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
8176
const frag = new VaporFragment(oldBlocks)
8277
const instance = currentInstance!
78+
const canUseFastRemove = flags & VaporVForFlags.FAST_REMOVE
79+
const isComponent = flags & VaporVForFlags.IS_COMPONENT
8380

8481
if (__DEV__ && !instance) {
8582
warn('createFor() can only be used inside setup()')
@@ -354,7 +351,11 @@ export const createFor = (
354351
doRemove && removeBlock(nodes, parent!)
355352
}
356353

357-
once ? renderList() : renderEffect(renderList)
354+
if (flags & VaporVForFlags.ONCE) {
355+
renderList()
356+
} else {
357+
renderEffect(renderList)
358+
}
358359
return frag
359360
}
360361

packages/shared/src/vaporFlags.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Flags to optimize vapor `createFor` runtime behavior, shared between the
3+
* compiler and the runtime
4+
*/
5+
export enum VaporVForFlags {
6+
/**
7+
* v-for is the only child of a parent container, so it can take the fast
8+
* path with textContent = '' when the whole list is emptied
9+
*/
10+
FAST_REMOVE = 1,
11+
/**
12+
* v-for used on component - we can skip creating child scopes for each block
13+
* because the component itself already has a scope.
14+
*/
15+
IS_COMPONENT = 1 << 1,
16+
/**
17+
* v-for inside v-ince
18+
*/
19+
ONCE = 1 << 2,
20+
}

0 commit comments

Comments
 (0)