| 652 | } |
| 653 | |
| 654 | export function cloneVNode<T, U>( |
| 655 | vnode: VNode<T, U>, |
| 656 | extraProps?: (Data & VNodeProps) | null, |
| 657 | mergeRef = false, |
| 658 | cloneTransition = false, |
| 659 | ): VNode<T, U> { |
| 660 | // This is intentionally NOT using spread or extend to avoid the runtime |
| 661 | // key enumeration cost. |
| 662 | const { props, ref, patchFlag, children, transition } = vnode |
| 663 | const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props |
| 664 | const cloned: VNode<T, U> = { |
| 665 | __v_isVNode: true, |
| 666 | __v_skip: true, |
| 667 | type: vnode.type, |
| 668 | props: mergedProps, |
| 669 | key: mergedProps && normalizeKey(mergedProps), |
| 670 | ref: |
| 671 | extraProps && extraProps.ref |
| 672 | ? // #2078 in the case of <component :is="vnode" ref="extra"/> |
| 673 | // if the vnode itself already has a ref, cloneVNode will need to merge |
| 674 | // the refs so the single vnode can be set on multiple refs |
| 675 | mergeRef && ref |
| 676 | ? isArray(ref) |
| 677 | ? ref.concat(normalizeRef(extraProps)!) |
| 678 | : [ref, normalizeRef(extraProps)!] |
| 679 | : normalizeRef(extraProps) |
| 680 | : ref, |
| 681 | scopeId: vnode.scopeId, |
| 682 | slotScopeIds: vnode.slotScopeIds, |
| 683 | children: |
| 684 | __DEV__ && patchFlag === PatchFlags.CACHED && isArray(children) |
| 685 | ? (children as VNode[]).map(deepCloneVNode) |
| 686 | : children, |
| 687 | target: vnode.target, |
| 688 | targetStart: vnode.targetStart, |
| 689 | targetAnchor: vnode.targetAnchor, |
| 690 | staticCount: vnode.staticCount, |
| 691 | shapeFlag: vnode.shapeFlag, |
| 692 | // if the vnode is cloned with extra props, we can no longer assume its |
| 693 | // existing patch flag to be reliable and need to add the FULL_PROPS flag. |
| 694 | // note: preserve flag for fragments since they use the flag for children |
| 695 | // fast paths only. |
| 696 | patchFlag: |
| 697 | extraProps && vnode.type !== Fragment |
| 698 | ? patchFlag === PatchFlags.CACHED // hoisted node |
| 699 | ? PatchFlags.FULL_PROPS |
| 700 | : patchFlag | PatchFlags.FULL_PROPS |
| 701 | : patchFlag, |
| 702 | dynamicProps: vnode.dynamicProps, |
| 703 | dynamicChildren: vnode.dynamicChildren, |
| 704 | appContext: vnode.appContext, |
| 705 | dirs: vnode.dirs, |
| 706 | transition, |
| 707 | |
| 708 | // These should technically only be non-null on mounted VNodes. However, |
| 709 | // they *should* be copied for kept-alive vnodes. So we just always copy |
| 710 | // them since them being non-null during a mount doesn't affect the logic as |
| 711 | // they will simply be overwritten. |