render/updateNodes: recycling, clarify terminology, fix logic

fix #2003 partim 1
fix #1991 partim 1
This commit is contained in:
Pierre-Yves Gérardy 2017-11-21 21:05:20 +01:00 committed by Pierre-Yves Gérardy
parent 8950760e85
commit eaa9f589af

View file

@ -161,12 +161,13 @@ module.exports = function($window) {
} }
//update //update
function updateNodes(parent, old, vnodes, recycling, hooks, nextSibling, ns) { function updateNodes(parent, old, vnodes, recyclingParent, hooks, nextSibling, ns) {
if (old === vnodes || old == null && vnodes == null) return if (old === vnodes && !recyclingParent || old == null && vnodes == null) return
else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns) else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns)
else if (vnodes == null) removeNodes(old, 0, old.length, vnodes) else if (vnodes == null) removeNodes(old, 0, old.length, vnodes)
else { else {
if (old.length === vnodes.length) { var originalOldLength = old.length, hasPool = false
if (originalOldLength === vnodes.length) {
var isUnkeyed = false var isUnkeyed = false
for (var i = 0; i < vnodes.length; i++) { for (var i = 0; i < vnodes.length; i++) {
if (vnodes[i] != null && old[i] != null) { if (vnodes[i] != null && old[i] != null) {
@ -175,56 +176,57 @@ module.exports = function($window) {
} }
} }
if (isUnkeyed) { if (isUnkeyed) {
for (var i = 0; i < old.length; i++) { for (var i = 0; i < originalOldLength; i++) {
if (old[i] === vnodes[i]) continue if (old[i] === vnodes[i] && !recyclingParent || old[i] == null && vnodes[i] == null) continue
else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling)) else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling))
else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes) else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes)
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns) else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recyclingParent, ns)
} }
return return
} }
} }
recycling = recycling || isRecyclable(old, vnodes) if (isRecyclable(old, vnodes)) {
if (recycling && old.pool != null) { hasPool = true
var pool = old.pool
old = old.concat(old.pool) old = old.concat(old.pool)
} }
var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map, o, v, oFromPool
while (oldEnd >= oldStart && end >= start) { while (oldEnd >= oldStart && end >= start) {
var o = old[oldStart], v = vnodes[start] o = old[oldStart]
if (o === v && !recycling) oldStart++, start++ v = vnodes[start]
oFromPool = hasPool && oldStart >= originalOldLength
if (o === v && !oFromPool && !recyclingParent) oldStart++, start++
else if (o == null) oldStart++ else if (o == null) oldStart++
else if (v == null) start++ else if (v == null) start++
else if (o.key === v.key) { else if (o.key === v.key) {
var shouldRecycle = (pool != null && oldStart >= old.length - pool.length) || ((pool == null) && recycling)
oldStart++, start++ oldStart++, start++
updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), shouldRecycle, ns) updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), oFromPool || recyclingParent, ns)
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) if (oFromPool && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
} }
else { else {
var o = old[oldEnd] o = old[oldEnd]
if (o === v && !recycling) oldEnd--, start++ oFromPool = hasPool && oldEnd >= originalOldLength
if (o === v && !oFromPool && !recyclingParent) oldEnd--, start++
else if (o == null) oldEnd-- else if (o == null) oldEnd--
else if (v == null) start++ else if (v == null) start++
else if (o.key === v.key) { else if (o.key === v.key) {
var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), oFromPool || recyclingParent, ns)
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) if (oFromPool && o.tag === v.tag || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling))
oldEnd--, start++ oldEnd--, start++
} }
else break else break
} }
} }
while (oldEnd >= oldStart && end >= start) { while (oldEnd >= oldStart && end >= start) {
var o = old[oldEnd], v = vnodes[end] o = old[oldEnd]
if (o === v && !recycling) oldEnd--, end-- v = vnodes[end]
oFromPool = hasPool && oldEnd >= originalOldLength
if (o === v && !oFromPool && !recyclingParent) oldEnd--, end--
else if (o == null) oldEnd-- else if (o == null) oldEnd--
else if (v == null) end-- else if (v == null) end--
else if (o.key === v.key) { else if (o.key === v.key) {
var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), oFromPool || recyclingParent, ns)
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) if (oFromPool && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling)
if (o.dom != null) nextSibling = o.dom if (o.dom != null) nextSibling = o.dom
oldEnd--, end-- oldEnd--, end--
} }
@ -233,12 +235,12 @@ module.exports = function($window) {
if (v != null) { if (v != null) {
var oldIndex = map[v.key] var oldIndex = map[v.key]
if (oldIndex != null) { if (oldIndex != null) {
var movable = old[oldIndex] o = old[oldIndex]
var shouldRecycle = (pool != null && oldIndex >= old.length - pool.length) || ((pool == null) && recycling) oFromPool = hasPool && oldIndex >= originalOldLength
updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), oFromPool || recyclingParent, ns)
insertNode(parent, toFragment(movable), nextSibling) insertNode(parent, toFragment(o), nextSibling)
old[oldIndex].skip = true o.skip = true
if (movable.dom != null) nextSibling = movable.dom if (o.dom != null) nextSibling = o.dom
} }
else { else {
var dom = createNode(parent, v, hooks, ns, nextSibling) var dom = createNode(parent, v, hooks, ns, nextSibling)
@ -250,9 +252,9 @@ module.exports = function($window) {
if (end < start) break if (end < start) break
} }
createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns) createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns)
removeNodes(old, oldStart, Math.min(oldEnd + 1, pool == null ? old.length : old.length - pool.length), vnodes) removeNodes(old, oldStart, Math.min(oldEnd + 1, originalOldLength), vnodes)
if (pool != null) { if (hasPool) {
var limit = Math.max(oldStart, old.length - pool.length) var limit = Math.max(oldStart, originalOldLength)
for (; oldEnd >= limit; oldEnd--) { for (; oldEnd >= limit; oldEnd--) {
if (old[oldEnd].skip) old[oldEnd].skip = false if (old[oldEnd].skip) old[oldEnd].skip = false
else addToPool(old[oldEnd], vnodes) else addToPool(old[oldEnd], vnodes)