Skip to content

Commit d073b4f

Browse files
committed
wip: extract VaporFragment into a separate file
resolve the circular dependency caused by TeleportFragment
1 parent c1547b5 commit d073b4f

File tree

11 files changed

+92
-94
lines changed

11 files changed

+92
-94
lines changed

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

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
import {
2-
VaporFragment,
3-
insert,
4-
normalizeBlock,
5-
prepend,
6-
remove,
7-
} from '../src/block'
1+
import { insert, normalizeBlock, prepend, remove } from '../src/block'
2+
import { VaporFragment } from '../src/fragment'
83

94
const node1 = document.createTextNode('node1')
105
const node2 = document.createTextNode('node2')

packages/runtime-vapor/src/apiCreateDynamicComponent.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { resolveDynamicComponent } from '@vue/runtime-dom'
2-
import { DynamicFragment, type VaporFragment } from './block'
32
import { createComponentWithFallback } from './component'
43
import { renderEffect } from './renderEffect'
54
import type { RawProps } from './componentProps'
65
import type { RawSlots } from './componentSlots'
6+
import { DynamicFragment, type VaporFragment } from './fragment'
77

88
export function createDynamicComponent(
99
getter: () => any,

packages/runtime-vapor/src/apiCreateFor.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,15 @@ import {
1111
} from '@vue/reactivity'
1212
import { getSequence, isArray, isObject, isString } from '@vue/shared'
1313
import { createComment, createTextNode } from './dom/node'
14-
import {
15-
type Block,
16-
VaporFragment,
17-
insert,
18-
remove as removeBlock,
19-
} from './block'
14+
import { type Block, insert, remove as removeBlock } from './block'
2015
import { warn } from '@vue/runtime-dom'
2116
import { currentInstance, isVaporComponent } from './component'
2217
import type { DynamicSlot } from './componentSlots'
2318
import { renderEffect } from './renderEffect'
2419
import { VaporVForFlags } from '../../shared/src/vaporFlags'
2520
import { isHydrating, locateHydrationNode } from './dom/hydration'
2621
import { insertionAnchor, insertionParent } from './insertionState'
22+
import { VaporFragment } from './fragment'
2723

2824
class ForBlock extends VaporFragment {
2925
scope: EffectScope | undefined

packages/runtime-vapor/src/apiCreateIf.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
1+
import { type Block, type BlockFn, insert } from './block'
22
import { isHydrating, locateHydrationNode } from './dom/hydration'
33
import { insertionAnchor, insertionParent } from './insertionState'
44
import { renderEffect } from './renderEffect'
5+
import { DynamicFragment } from './fragment'
56

67
export function createIf(
78
condition: () => any,

packages/runtime-vapor/src/block.ts

+5-68
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import {
55
mountComponent,
66
unmountComponent,
77
} from './component'
8-
import { createComment, createTextNode } from './dom/node'
9-
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
108
import { isHydrating } from './dom/hydration'
9+
import {
10+
type DynamicFragment,
11+
type VaporFragment,
12+
isFragment,
13+
} from './fragment'
1114

1215
export type Block =
1316
| Node
@@ -18,72 +21,6 @@ export type Block =
1821

1922
export type BlockFn = (...args: any[]) => Block
2023

21-
export class VaporFragment {
22-
nodes: Block
23-
target?: ParentNode | null
24-
targetAnchor?: Node | null
25-
anchor?: Node
26-
insert?: (parent: ParentNode, anchor: Node | null) => void
27-
remove?: (parent?: ParentNode) => void
28-
getNodes?: () => Block
29-
30-
constructor(nodes: Block) {
31-
this.nodes = nodes
32-
}
33-
}
34-
35-
export class DynamicFragment extends VaporFragment {
36-
anchor: Node
37-
scope: EffectScope | undefined
38-
current?: BlockFn
39-
fallback?: BlockFn
40-
41-
constructor(anchorLabel?: string) {
42-
super([])
43-
this.anchor =
44-
__DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode()
45-
}
46-
47-
update(render?: BlockFn, key: any = render): void {
48-
if (key === this.current) {
49-
return
50-
}
51-
this.current = key
52-
53-
pauseTracking()
54-
const parent = this.anchor.parentNode
55-
56-
// teardown previous branch
57-
if (this.scope) {
58-
this.scope.stop()
59-
parent && remove(this.nodes, parent)
60-
}
61-
62-
if (render) {
63-
this.scope = new EffectScope()
64-
this.nodes = this.scope.run(render) || []
65-
if (parent) insert(this.nodes, parent, this.anchor)
66-
} else {
67-
this.scope = undefined
68-
this.nodes = []
69-
}
70-
71-
if (this.fallback && !isValidBlock(this.nodes)) {
72-
parent && remove(this.nodes, parent)
73-
this.nodes =
74-
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
75-
[]
76-
parent && insert(this.nodes, parent, this.anchor)
77-
}
78-
79-
resetTracking()
80-
}
81-
}
82-
83-
export function isFragment(val: NonNullable<unknown>): val is VaporFragment {
84-
return val instanceof VaporFragment
85-
}
86-
8724
export function isBlock(val: NonNullable<unknown>): val is Block {
8825
return (
8926
val instanceof Node ||

packages/runtime-vapor/src/componentSlots.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { EMPTY_OBJ, NO, hasOwn, isArray, isFunction } from '@vue/shared'
2-
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
2+
import { type Block, type BlockFn, insert } from './block'
33
import { rawPropsProxyHandlers } from './componentProps'
44
import { currentInstance, isRef } from '@vue/runtime-dom'
55
import type { LooseRawProps, VaporComponentInstance } from './component'
66
import { renderEffect } from './renderEffect'
77
import { insertionAnchor, insertionParent } from './insertionState'
88
import { isHydrating, locateHydrationNode } from './dom/hydration'
9+
import { DynamicFragment } from './fragment'
910

1011
export type RawSlots = Record<string, VaporSlot> & {
1112
$?: DynamicSlotSource[]

packages/runtime-vapor/src/components/Teleport.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,7 @@ import {
77
resolveTarget,
88
warn,
99
} from '@vue/runtime-dom'
10-
import {
11-
type Block,
12-
type BlockFn,
13-
VaporFragment,
14-
insert,
15-
remove,
16-
} from '../block'
10+
import { type Block, type BlockFn, insert, remove } from '../block'
1711
import { createComment, createTextNode, querySelector } from '../dom/node'
1812
import type {
1913
LooseRawProps,
@@ -24,6 +18,7 @@ import { rawPropsProxyHandlers } from '../componentProps'
2418
import { renderEffect } from '../renderEffect'
2519
import { extend, isArray } from '@vue/shared'
2620
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
21+
import { VaporFragment } from '../fragment'
2722

2823
export const teleportStack: TeleportFragment[] = __DEV__
2924
? ([] as TeleportFragment[])

packages/runtime-vapor/src/directives/vShow.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import {
66
} from '@vue/runtime-dom'
77
import { renderEffect } from '../renderEffect'
88
import { isVaporComponent } from '../component'
9-
import { type Block, DynamicFragment } from '../block'
9+
import type { Block } from '../block'
1010
import { isArray } from '@vue/shared'
11+
import { DynamicFragment } from '../fragment'
1112

1213
export function applyVShow(target: Block, source: () => any): void {
1314
if (isVaporComponent(target)) {
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
2+
import { createComment, createTextNode } from './dom/node'
3+
import { type Block, type BlockFn, insert, isValidBlock, remove } from './block'
4+
5+
export class VaporFragment {
6+
nodes: Block
7+
target?: ParentNode | null
8+
targetAnchor?: Node | null
9+
anchor?: Node
10+
insert?: (parent: ParentNode, anchor: Node | null) => void
11+
remove?: (parent?: ParentNode) => void
12+
getNodes?: () => Block
13+
14+
constructor(nodes: Block) {
15+
this.nodes = nodes
16+
}
17+
}
18+
19+
export class DynamicFragment extends VaporFragment {
20+
anchor: Node
21+
scope: EffectScope | undefined
22+
current?: BlockFn
23+
fallback?: BlockFn
24+
25+
constructor(anchorLabel?: string) {
26+
super([])
27+
this.anchor =
28+
__DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode()
29+
}
30+
31+
update(render?: BlockFn, key: any = render): void {
32+
if (key === this.current) {
33+
return
34+
}
35+
this.current = key
36+
37+
pauseTracking()
38+
const parent = this.anchor.parentNode
39+
40+
// teardown previous branch
41+
if (this.scope) {
42+
this.scope.stop()
43+
parent && remove(this.nodes, parent)
44+
}
45+
46+
if (render) {
47+
this.scope = new EffectScope()
48+
this.nodes = this.scope.run(render) || []
49+
if (parent) insert(this.nodes, parent, this.anchor)
50+
} else {
51+
this.scope = undefined
52+
this.nodes = []
53+
}
54+
55+
if (this.fallback && !isValidBlock(this.nodes)) {
56+
parent && remove(this.nodes, parent)
57+
this.nodes =
58+
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
59+
[]
60+
parent && insert(this.nodes, parent, this.anchor)
61+
}
62+
63+
resetTracking()
64+
}
65+
}
66+
67+
export function isFragment(val: NonNullable<unknown>): val is VaporFragment {
68+
return val instanceof VaporFragment
69+
}

packages/runtime-vapor/src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export type { VaporDirective } from './directives/custom'
66
export { VaporTeleport } from './components/Teleport'
77

88
// compiler-use only
9-
export { insert, prepend, remove, isFragment, VaporFragment } from './block'
9+
export { insert, prepend, remove } from './block'
1010
export { setInsertionState } from './insertionState'
1111
export { createComponent, createComponentWithFallback } from './component'
1212
export { renderEffect } from './renderEffect'
@@ -43,3 +43,5 @@ export {
4343
applyDynamicModel,
4444
} from './directives/vModel'
4545
export { withVaporDirectives } from './directives/custom'
46+
export { isFragment } from './fragment'
47+
export { VaporFragment } from './fragment'

packages/runtime-vapor/src/vdomInterop.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ import {
2626
mountComponent,
2727
unmountComponent,
2828
} from './component'
29-
import { type Block, VaporFragment, insert, remove } from './block'
29+
import { type Block, insert, remove } from './block'
3030
import { EMPTY_OBJ, extend, isFunction } from '@vue/shared'
3131
import { type RawProps, rawPropsProxyHandlers } from './componentProps'
3232
import type { RawSlots, VaporSlot } from './componentSlots'
3333
import { renderEffect } from './renderEffect'
3434
import { createTextNode } from './dom/node'
3535
import { optimizePropertyLookup } from './dom/prop'
36+
import { VaporFragment } from './fragment'
3637

3738
// mounting vapor components and slots in vdom
3839
const vaporInteropImpl: Omit<

0 commit comments

Comments
 (0)