]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): do not use bail patchFlag on cloned vnodes
authorEvan You <yyx990803@gmail.com>
Tue, 21 Jul 2020 16:35:34 +0000 (12:35 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 21 Jul 2020 17:11:19 +0000 (13:11 -0400)
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.

packages/runtime-core/src/componentRenderUtils.ts
packages/runtime-core/src/vnode.ts

index 54fa4b3f3d80ce50d4d7a224dbc1852289a5588e..bd1ce451df07ac68ad6cb6669ba83eb856897424 100644 (file)
@@ -279,7 +279,7 @@ export function shouldUpdateComponent(
     return true
   }
 
-  if (patchFlag > 0) {
+  if (optimized && patchFlag > 0) {
     if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {
       // slot content that references values that might have changed,
       // e.g. in a v-for
@@ -300,7 +300,7 @@ export function shouldUpdateComponent(
         }
       }
     }
-  } else if (!optimized) {
+  } else {
     // this path is only taken by manually written render functions
     // so presence of any children leads to a forced update
     if (prevChildren || nextChildren) {
index 5cde39f87ebc9257dac11e1722b7677781797a63..5cd08bc15c9203af9c58de627912347c396bce18 100644 (file)
@@ -310,7 +310,11 @@ function _createVNode(
   }
 
   if (isVNode(type)) {
-    return cloneVNode(type, props, children)
+    const cloned = cloneVNode(type, props)
+    if (children) {
+      normalizeChildren(cloned, children)
+    }
+    return cloned
   }
 
   // class component normalization.
@@ -420,8 +424,7 @@ function _createVNode(
 
 export function cloneVNode<T, U>(
   vnode: VNode<T, U>,
-  extraProps?: Data & VNodeProps | null,
-  children?: unknown
+  extraProps?: Data & VNodeProps | null
 ): VNode<T, U> {
   const props = extraProps
     ? vnode.props
@@ -430,7 +433,7 @@ export function cloneVNode<T, U>(
     : vnode.props
   // This is intentionally NOT using spread or extend to avoid the runtime
   // key enumeration cost.
-  const cloned: VNode<T, U> = {
+  return {
     __v_isVNode: true,
     __v_skip: true,
     type: vnode.type,
@@ -444,14 +447,11 @@ export function cloneVNode<T, U>(
     staticCount: vnode.staticCount,
     shapeFlag: vnode.shapeFlag,
     // 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
+    // existing patch flag to be reliable and need to add the FULL_PROPS flag.
+    patchFlag:
+      extraProps && vnode.type !== Fragment
         ? vnode.patchFlag | PatchFlags.FULL_PROPS
-        : PatchFlags.BAIL
-      : vnode.patchFlag,
+        : vnode.patchFlag,
     dynamicProps: vnode.dynamicProps,
     dynamicChildren: vnode.dynamicChildren,
     appContext: vnode.appContext,
@@ -467,10 +467,6 @@ export function cloneVNode<T, U>(
     el: vnode.el,
     anchor: vnode.anchor
   }
-  if (children) {
-    normalizeChildren(cloned, children)
-  }
-  return cloned
 }
 
 /**