Skip to content

Commit

Permalink
refactor(vapor): use bitwise flags for v-for runtime optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Feb 12, 2025
1 parent 63cf2ee commit a118c02
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function render(_ctx) {
const x4 = _child(n4)
_renderEffect(() => _setText(x4, _toDisplayString(_for_item1.value+_for_item0.value)))
return n4
}, null, null, null, true)
}, null, 1)
_insert(n2, n5)
return n5
})
Expand Down
16 changes: 13 additions & 3 deletions packages/compiler-vapor/src/generators/for.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { ForIRNode } from '../ir'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import type { Identifier } from '@babel/types'
import { parseExpression } from '@babel/parser'
import { VaporVForFlags } from '../../../shared/src/vaporFlags'

export function genFor(
oper: ForIRNode,
Expand Down Expand Up @@ -80,6 +81,17 @@ export function genFor(
const blockFn = context.withId(() => genBlock(render, context, args), idMap)
exitScope()

let flags = 0
if (onlyChild) {
flags |= VaporVForFlags.FAST_REMOVE
}
if (component) {
flags |= VaporVForFlags.IS_COMPONENT
}
if (once) {
flags |= VaporVForFlags.ONCE
}

return [
NEWLINE,
`const n${id} = `,
Expand All @@ -88,9 +100,7 @@ export function genFor(
sourceExpr,
blockFn,
genCallback(keyProp),
component && 'true',
once && 'true',
onlyChild && `true`,
flags ? String(flags) : undefined,
// todo: hydrationNode
),
]
Expand Down
17 changes: 9 additions & 8 deletions packages/runtime-vapor/src/apiCreateFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { warn } from '@vue/runtime-dom'
import { currentInstance, isVaporComponent } from './component'
import type { DynamicSlot } from './componentSlots'
import { renderEffect } from './renderEffect'
import { VaporVForFlags } from '../../shared/src/vaporFlags'

class ForBlock extends VaporFragment {
scope: EffectScope | undefined
Expand Down Expand Up @@ -64,13 +65,7 @@ export const createFor = (
index: ShallowRef<number | undefined>,
) => Block,
getKey?: (item: any, key: any, index?: number) => any,
/**
* Whether this v-for is used directly on a component. If true, we can avoid
* creating an extra fragment / scope for each block
*/
isComponent = false,
once?: boolean,
canUseFastRemove?: boolean,
flags = 0,
// hydrationNode?: Node,
): VaporFragment => {
let isMounted = false
Expand All @@ -80,6 +75,8 @@ export const createFor = (
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
const frag = new VaporFragment(oldBlocks)
const instance = currentInstance!
const canUseFastRemove = flags & VaporVForFlags.FAST_REMOVE
const isComponent = flags & VaporVForFlags.IS_COMPONENT

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

once ? renderList() : renderEffect(renderList)
if (flags & VaporVForFlags.ONCE) {
renderList()
} else {
renderEffect(renderList)
}
return frag
}

Expand Down
20 changes: 20 additions & 0 deletions packages/shared/src/vaporFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Flags to optimize vapor `createFor` runtime behavior, shared between the
* compiler and the runtime
*/
export enum VaporVForFlags {
/**
* v-for is the only child of a parent container, so it can take the fast
* path with textContent = '' when the whole list is emptied
*/
FAST_REMOVE = 1,
/**
* v-for used on component - we can skip creating child scopes for each block
* because the component itself already has a scope.
*/
IS_COMPONENT = 1 << 1,
/**
* v-for inside v-ince
*/
ONCE = 1 << 2,
}

0 comments on commit a118c02

Please sign in to comment.