Skip to content

Commit 3fc906c

Browse files
committed
refactor: move $dp into setInsertionState
1 parent 5f8c1f6 commit 3fc906c

File tree

8 files changed

+57
-37
lines changed

8 files changed

+57
-37
lines changed

packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,11 @@ const t0 = _template("<div><div></div></div>", true)
218218
219219
export function render(_ctx) {
220220
const _component_Comp = _resolveComponent("Comp")
221-
const n3 = t0(); n3.$dp = 1;
221+
const n3 = t0()
222222
const n1 = _child(n3)
223223
_setInsertionState(n1)
224224
const n0 = _createSlot("default", null)
225-
_setInsertionState(n3)
225+
_setInsertionState(n3, null, 1)
226226
const n2 = _createComponentWithFallback(_component_Comp)
227227
return n3
228228
}"

packages/compiler-vapor/src/generate.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export class CodegenContext {
3939

4040
seenInlineHandlerNames: Record<string, number> = Object.create(null)
4141

42+
seenChildIndexes: Map<number, number> = new Map()
43+
4244
block: BlockIRNode
4345
withId<T>(
4446
fn: () => T,

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,30 @@ function genInsertionState(
168168
operation: InsertionStateTypes,
169169
context: CodegenContext,
170170
): CodeFragment[] {
171+
const { seenChildIndexes } = context
172+
let { parent, childIndex, anchor } = operation
173+
const insertionAnchor =
174+
anchor == null
175+
? undefined
176+
: anchor === -1 // -1 indicates prepend
177+
? `0` // runtime anchor value for prepend
178+
: `n${anchor}`
179+
180+
// the index of next block node, used to locate node during hydration
181+
let index: number | undefined
182+
if (anchor == null) {
183+
const existingOffset = seenChildIndexes.get(parent!)
184+
index = existingOffset ? existingOffset + 1 : childIndex
185+
if (index) seenChildIndexes.set(parent!, index)
186+
}
187+
171188
return [
172189
NEWLINE,
173190
...genCall(
174191
context.helper('setInsertionState'),
175-
`n${operation.parent}`,
176-
operation.anchor == null
177-
? undefined
178-
: operation.anchor === -1 // -1 indicates prepend
179-
? `0` // runtime anchor value for prepend
180-
: `n${operation.anchor}`,
192+
`n${parent}`,
193+
insertionAnchor,
194+
index ? `${index}` : undefined,
181195
),
182196
]
183197
}

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ export function genSelf(
2424
context: CodegenContext,
2525
): CodeFragment[] {
2626
const [frag, push] = buildCodeFragment()
27-
const { id, template, operation, dynamicChildOffset, hasDynamicChild } =
28-
dynamic
27+
const { id, template, operation, hasDynamicChild } = dynamic
2928

3029
if (id !== undefined && template !== undefined) {
3130
push(NEWLINE, `const n${id} = t${template}()`)
32-
if (dynamicChildOffset) push(`; n${id}.$dp = ${dynamicChildOffset};`)
3331
push(...genDirectivesForElement(id, context))
3432
}
3533

@@ -115,10 +113,6 @@ export function genChildren(
115113
}
116114
}
117115

118-
if (child.dynamicChildOffset) {
119-
pushBlock(`; ${variable}.$dp = ${child.dynamicChildOffset};`)
120-
}
121-
122116
if (id === child.anchor && !child.hasDynamicChild) {
123117
push(...genSelf(child, context))
124118
}

packages/compiler-vapor/src/ir/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export interface IfIRNode extends BaseIRNode {
8080
once?: boolean
8181
parent?: number
8282
anchor?: number
83+
childIndex?: number
8384
}
8485

8586
export interface IRFor {
@@ -99,6 +100,7 @@ export interface ForIRNode extends BaseIRNode, IRFor {
99100
onlyChild: boolean
100101
parent?: number
101102
anchor?: number
103+
childIndex?: number
102104
}
103105

104106
export interface SetPropIRNode extends BaseIRNode {
@@ -200,6 +202,7 @@ export interface CreateComponentIRNode extends BaseIRNode {
200202
dynamic?: SimpleExpressionNode
201203
parent?: number
202204
anchor?: number
205+
childIndex?: number
203206
scopeId?: string | null
204207
}
205208

@@ -217,6 +220,7 @@ export interface SlotOutletIRNode extends BaseIRNode {
217220
forwarded?: boolean
218221
parent?: number
219222
anchor?: number
223+
childIndex?: number
220224
}
221225

222226
export interface GetTextChildIRNode extends BaseIRNode {
@@ -266,7 +270,6 @@ export interface IRDynamicInfo {
266270
children: IRDynamicInfo[]
267271
template?: number
268272
hasDynamicChild?: boolean
269-
dynamicChildOffset?: number
270273
operation?: OperationNode
271274
needsKey?: boolean
272275
}

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ export const transformChildren: NodeTransform = (node, context) => {
5959

6060
function processDynamicChildren(context: TransformContext<ElementNode>) {
6161
let prevDynamics: IRDynamicInfo[] = []
62-
let staticCount = 0
63-
let prependCount = 0
62+
let hasStaticTemplate = false
6463
const children = context.dynamic.children
6564

6665
for (const [index, child] of children.entries()) {
@@ -70,7 +69,7 @@ function processDynamicChildren(context: TransformContext<ElementNode>) {
7069

7170
if (!(child.flags & DynamicFlag.NON_TEMPLATE)) {
7271
if (prevDynamics.length) {
73-
if (staticCount) {
72+
if (hasStaticTemplate) {
7473
// each dynamic child gets its own placeholder node.
7574
// this makes it easier to locate the corresponding node during hydration.
7675
for (let i = 0; i < prevDynamics.length; i++) {
@@ -89,25 +88,34 @@ function processDynamicChildren(context: TransformContext<ElementNode>) {
8988
}
9089
}
9190
} else {
92-
prependCount += prevDynamics.length
93-
registerInsertion(prevDynamics, context, -1 /* prepend */)
91+
registerInsertion(
92+
prevDynamics,
93+
context,
94+
-1 /* prepend */,
95+
children.findIndex(c => c === prevDynamics[0]),
96+
)
9497
}
9598
prevDynamics = []
9699
}
97-
staticCount++
100+
hasStaticTemplate = true
98101
}
99102
}
100103

101104
if (prevDynamics.length) {
102-
registerInsertion(prevDynamics, context)
103-
context.dynamic.dynamicChildOffset = staticCount + prependCount
105+
registerInsertion(
106+
prevDynamics,
107+
context,
108+
undefined,
109+
children.findIndex(c => c === prevDynamics[0]),
110+
)
104111
}
105112
}
106113

107114
function registerInsertion(
108115
dynamics: IRDynamicInfo[],
109116
context: TransformContext,
110117
anchor?: number,
118+
childIndex?: number,
111119
) {
112120
for (const child of dynamics) {
113121
if (child.template != null) {
@@ -122,6 +130,7 @@ function registerInsertion(
122130
// block types
123131
child.operation.parent = context.reference()
124132
child.operation.anchor = anchor
133+
child.operation.childIndex = childIndex
125134
}
126135
}
127136
}

packages/runtime-vapor/src/dom/hydration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { warn } from '@vue/runtime-dom'
22
import {
33
insertionAnchor,
4+
insertionChildIndex,
45
insertionParent,
56
resetInsertionState,
67
setInsertionState,
@@ -45,7 +46,6 @@ function performHydration<T>(
4546
locateHydrationNode = locateHydrationNodeImpl
4647
// optimize anchor cache lookup
4748
;(Comment.prototype as any).$fe = undefined
48-
;(Node.prototype as any).$dp = undefined
4949
;(Node.prototype as any).$np = undefined
5050
isOptimized = true
5151
}
@@ -129,7 +129,7 @@ function locateHydrationNodeImpl(): void {
129129
} else {
130130
node = currentHydrationNode
131131
if (insertionParent && (!node || node.parentNode !== insertionParent)) {
132-
node = __nthChild(insertionParent, insertionParent.$dp || 0)
132+
node = __nthChild(insertionParent, insertionChildIndex || 0)
133133
}
134134
}
135135

packages/runtime-vapor/src/insertionState.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,6 @@ import { isHydrating } from './dom/hydration'
33

44
export let insertionParent:
55
| (ParentNode & {
6-
// dynamic node position - hydration only
7-
// indicates the position where dynamic nodes begin within the parent
8-
// during hydration, static nodes before this index are skipped
9-
//
10-
// Example:
11-
// const t0 = _template("<div><span></span><span></span></div>", true)
12-
// const n4 = t0(2) // n4.$dp = 2
13-
// The first 2 nodes are static, dynamic nodes start from index 2
14-
$dp?: number
156
// number of prepends - hydration only
167
// consecutive prepends need to skip nodes that were prepended earlier
178
// each prepend increases the value of $prepend
@@ -20,20 +11,27 @@ export let insertionParent:
2011
| undefined
2112
export let insertionAnchor: Node | 0 | undefined
2213

14+
export let insertionChildIndex: number | undefined
15+
2316
/**
2417
* This function is called before a block type that requires insertion
2518
* (component, slot outlet, if, for) is created. The state is used for actual
2619
* insertion on client-side render, and used for node adoption during hydration.
2720
*/
28-
export function setInsertionState(parent: ParentNode, anchor?: Node | 0): void {
21+
export function setInsertionState(
22+
parent: ParentNode,
23+
anchor?: Node | 0,
24+
offset?: number,
25+
): void {
2926
insertionParent = parent
3027
insertionAnchor = anchor
28+
insertionChildIndex = offset
3129

3230
if (isHydrating) {
3331
collectInsertionParents(parent)
3432
}
3533
}
3634

3735
export function resetInsertionState(): void {
38-
insertionParent = insertionAnchor = undefined
36+
insertionParent = insertionAnchor = insertionChildIndex = undefined
3937
}

0 commit comments

Comments
 (0)