Skip to content

Commit 6390ddf

Browse files
committed
fix(runtime-core): do not use bail patchFlag on cloned vnodes
fix #1665 - cloned vnodes with extra props will receive only the full props flag - this commit affects `cloneVNode` behavior when used in manual render functions. - ok for normal elements since elements only use patchFlags for own props optimization - full props flag is skipped for fragments because fragments use patchFlags only for children optimization - this also affects `shouldUpdateComponent` where it should now only respect patchFlags in optimized mode, since component vnodes use the patchFlag for both props and slots optimization checks.
1 parent 324167d commit 6390ddf

File tree

2 files changed

+13
-17
lines changed

2 files changed

+13
-17
lines changed

packages/runtime-core/src/componentRenderUtils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export function shouldUpdateComponent(
279279
return true
280280
}
281281

282-
if (patchFlag > 0) {
282+
if (optimized && patchFlag > 0) {
283283
if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {
284284
// slot content that references values that might have changed,
285285
// e.g. in a v-for
@@ -300,7 +300,7 @@ export function shouldUpdateComponent(
300300
}
301301
}
302302
}
303-
} else if (!optimized) {
303+
} else {
304304
// this path is only taken by manually written render functions
305305
// so presence of any children leads to a forced update
306306
if (prevChildren || nextChildren) {

packages/runtime-core/src/vnode.ts

+11-15
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,11 @@ function _createVNode(
310310
}
311311

312312
if (isVNode(type)) {
313-
return cloneVNode(type, props, children)
313+
const cloned = cloneVNode(type, props)
314+
if (children) {
315+
normalizeChildren(cloned, children)
316+
}
317+
return cloned
314318
}
315319

316320
// class component normalization.
@@ -420,8 +424,7 @@ function _createVNode(
420424

421425
export function cloneVNode<T, U>(
422426
vnode: VNode<T, U>,
423-
extraProps?: Data & VNodeProps | null,
424-
children?: unknown
427+
extraProps?: Data & VNodeProps | null
425428
): VNode<T, U> {
426429
const props = extraProps
427430
? vnode.props
@@ -430,7 +433,7 @@ export function cloneVNode<T, U>(
430433
: vnode.props
431434
// This is intentionally NOT using spread or extend to avoid the runtime
432435
// key enumeration cost.
433-
const cloned: VNode<T, U> = {
436+
return {
434437
__v_isVNode: true,
435438
__v_skip: true,
436439
type: vnode.type,
@@ -444,14 +447,11 @@ export function cloneVNode<T, U>(
444447
staticCount: vnode.staticCount,
445448
shapeFlag: vnode.shapeFlag,
446449
// if the vnode is cloned with extra props, we can no longer assume its
447-
// existing patch flag to be reliable and need to bail out of optimized mode.
448-
// however we don't want block nodes to de-opt their children, so if the
449-
// vnode is a block node, we only add the FULL_PROPS flag to it.
450-
patchFlag: extraProps
451-
? vnode.dynamicChildren
450+
// existing patch flag to be reliable and need to add the FULL_PROPS flag.
451+
patchFlag:
452+
extraProps && vnode.type !== Fragment
452453
? vnode.patchFlag | PatchFlags.FULL_PROPS
453-
: PatchFlags.BAIL
454-
: vnode.patchFlag,
454+
: vnode.patchFlag,
455455
dynamicProps: vnode.dynamicProps,
456456
dynamicChildren: vnode.dynamicChildren,
457457
appContext: vnode.appContext,
@@ -467,10 +467,6 @@ export function cloneVNode<T, U>(
467467
el: vnode.el,
468468
anchor: vnode.anchor
469469
}
470-
if (children) {
471-
normalizeChildren(cloned, children)
472-
}
473-
return cloned
474470
}
475471

476472
/**

0 commit comments

Comments
 (0)