1010 * of making flow understand it is not worth it.
1111 */
1212
13- import VNode from './vnode'
13+ import VNode , { cloneVNode } from './vnode'
1414import config from '../config'
1515import { SSR_ATTR } from 'shared/constants'
1616import { registerRef } from './modules/ref'
@@ -121,7 +121,25 @@ export function createPatchFunction (backend) {
121121 }
122122
123123 let creatingElmInVPre = 0
124- function createElm ( vnode , insertedVnodeQueue , parentElm , refElm , nested ) {
124+
125+ function createElm (
126+ vnode ,
127+ insertedVnodeQueue ,
128+ parentElm ,
129+ refElm ,
130+ nested ,
131+ ownerArray ,
132+ index
133+ ) {
134+ if ( isDef ( vnode . elm ) && isDef ( ownerArray ) ) {
135+ // This vnode was used in a previous render!
136+ // now it's used as a new node, overwriting its elm would cause
137+ // potential patch errors down the road when it's used as an insertion
138+ // reference node. Instead, we clone the node on-demand before creating
139+ // associated DOM element for it.
140+ vnode = ownerArray [ index ] = cloneVNode ( vnode )
141+ }
142+
125143 vnode . isRootInsert = ! nested // for transition enter check
126144 if ( createComponent ( vnode , insertedVnodeQueue , parentElm , refElm ) ) {
127145 return
@@ -144,6 +162,7 @@ export function createPatchFunction (backend) {
144162 )
145163 }
146164 }
165+
147166 vnode . elm = vnode . ns
148167 ? nodeOps . createElementNS ( vnode . ns , tag )
149168 : nodeOps . createElement ( tag , vnode )
@@ -267,7 +286,7 @@ export function createPatchFunction (backend) {
267286 checkDuplicateKeys ( children )
268287 }
269288 for ( let i = 0 ; i < children . length ; ++ i ) {
270- createElm ( children [ i ] , insertedVnodeQueue , vnode . elm , null , true )
289+ createElm ( children [ i ] , insertedVnodeQueue , vnode . elm , null , true , children , i )
271290 }
272291 } else if ( isPrimitive ( vnode . text ) ) {
273292 nodeOps . appendChild ( vnode . elm , nodeOps . createTextNode ( String ( vnode . text ) ) )
@@ -320,7 +339,7 @@ export function createPatchFunction (backend) {
320339
321340 function addVnodes ( parentElm , refElm , vnodes , startIdx , endIdx , insertedVnodeQueue ) {
322341 for ( ; startIdx <= endIdx ; ++ startIdx ) {
323- createElm ( vnodes [ startIdx ] , insertedVnodeQueue , parentElm , refElm )
342+ createElm ( vnodes [ startIdx ] , insertedVnodeQueue , parentElm , refElm , false , vnodes , startIdx )
324343 }
325344 }
326345
@@ -430,7 +449,7 @@ export function createPatchFunction (backend) {
430449 ? oldKeyToIdx [ newStartVnode . key ]
431450 : findIdxInOld ( newStartVnode , oldCh , oldStartIdx , oldEndIdx )
432451 if ( isUndef ( idxInOld ) ) { // New element
433- createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm )
452+ createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm , false , newCh , newStartIdx )
434453 } else {
435454 vnodeToMove = oldCh [ idxInOld ]
436455 if ( sameVnode ( vnodeToMove , newStartVnode ) ) {
@@ -439,7 +458,7 @@ export function createPatchFunction (backend) {
439458 canMove && nodeOps . insertBefore ( parentElm , vnodeToMove . elm , oldStartVnode . elm )
440459 } else {
441460 // same key but different element. treat as new element
442- createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm )
461+ createElm ( newStartVnode , insertedVnodeQueue , parentElm , oldStartVnode . elm , false , newCh , newStartIdx )
443462 }
444463 }
445464 newStartVnode = newCh [ ++ newStartIdx ]
0 commit comments