diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 4fd61895..a83821b3 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -113,11 +113,6 @@ export function renderComponentRoot( root.shapeFlag & ShapeFlags.COMPONENT ) { root = cloneVNode(root, fallthroughAttrs) - // If the child root node is a compiler optimized vnode, make sure it - // force update full props to account for the merged attrs. - if (root.dynamicChildren) { - root.patchFlag |= PatchFlags.FULL_PROPS - } } else if (__DEV__ && !accessedAttrs && root.type !== Comment) { const allAttrs = Object.keys(attrs) const eventAttrs: string[] = [] diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 6cfdc85c..4152b7de 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -354,6 +354,11 @@ function baseCreateRenderer( n1 = null } + if (n2.patchFlag === PatchFlags.BAIL) { + optimized = false + n2.dynamicChildren = null + } + const { type, ref, shapeFlag } = n2 switch (type) { case Text: @@ -1280,9 +1285,6 @@ function baseCreateRenderer( const c2 = n2.children const { patchFlag, shapeFlag } = n2 - if (patchFlag === PatchFlags.BAIL) { - optimized = false - } // fast path if (patchFlag > 0) { if (patchFlag & PatchFlags.KEYED_FRAGMENT) { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index d3e3ef4d..efab10c6 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -412,7 +412,15 @@ export function cloneVNode( target: vnode.target, targetAnchor: vnode.targetAnchor, shapeFlag: vnode.shapeFlag, - patchFlag: vnode.patchFlag, + // if the vnode is cloned with extra props, we can no longer assume its + // existing patch flag to be reliable and need to bail out of optimized mode. + // however we don't want block nodes to de-opt their children, so if the + // vnode is a block node, we only add the FULL_PROPS flag to it. + patchFlag: extraProps + ? vnode.dynamicChildren + ? vnode.patchFlag | PatchFlags.FULL_PROPS + : PatchFlags.BAIL + : vnode.patchFlag, dynamicProps: vnode.dynamicProps, dynamicChildren: vnode.dynamicChildren, appContext: vnode.appContext, diff --git a/packages/shared/src/patchFlags.ts b/packages/shared/src/patchFlags.ts index c541b2ab..5ec63151 100644 --- a/packages/shared/src/patchFlags.ts +++ b/packages/shared/src/patchFlags.ts @@ -76,9 +76,10 @@ export const enum PatchFlags { HOISTED = -1, // A special flag that indicates that the diffing algorithm should bail out - // of optimized mode. This is only on block fragments created by renderSlot() + // of optimized mode. For example, on block fragments created by renderSlot() // when encountering non-compiler generated slots (i.e. manually written // render functions, which should always be fully diffed) + // OR manually cloneVNodes BAIL = -2 }