diff --git a/mithril.js b/mithril.js index 68a0cb07..025d9f78 100644 --- a/mithril.js +++ b/mithril.js @@ -472,7 +472,9 @@ var _13 = function($window) { while (oldEnd >= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] if (o === v && !recycling) oldStart++, start++ - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldStart++ + else if (v == null) start++ + else if (o.key === v.key) { oldStart++, start++ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) @@ -480,7 +482,9 @@ var _13 = function($window) { else { var o = old[oldEnd] if (o === v && !recycling) oldEnd--, start++ - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldEnd-- + else if (v == null) start++ + else if (o.key === v.key) { updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) oldEnd--, start++ @@ -491,7 +495,9 @@ var _13 = function($window) { while (oldEnd >= oldStart && end >= start) { var o = old[oldEnd], v = vnodes[end] if (o === v && !recycling) oldEnd--, end-- - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldEnd-- + else if (v == null) end-- + else if (o.key === v.key) { updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) if (o.dom != null) nextSibling = o.dom diff --git a/mithril.min.js b/mithril.min.js index 71078381..bdf1bb88 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,40 +1,40 @@ -new function(){function l(a,b,k,d,n,h){return{tag:a,key:b,attrs:k,children:d,text:n,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function t(a){if(null==a||"string"!==typeof a&&null==a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a&&void 0===G[a]){for(var b,k,d=[],n={};b=N.exec(a);){var h=b[1],v=b[2];""===h&&""!==v?k=v:"#"===h?n.id=v:"."===h?d.push(v):"["===b[3][0]&&((h=b[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -"class"===b[4]?d.push(h):n[b[4]]=h||!0)}0a.indexOf("?")?"?":"&";a+=d+f}return a}function v(a){try{return""!== -a?JSON.parse(a):null}catch(x){throw Error(a);}}function q(a){return a.responseText}function r(a,b){if("function"===typeof a)if(b instanceof Array)for(var d=0;dm.status||304===m.status)b(r(f.type,a));else{var h=Error(m.responseText),k;for(k in a)h[k]=a[k];d(h)}}catch(F){d(F)}}; -p&&null!=f.data?m.send(f.data):m.send()}))},jsonp:function(f){return d(new b(function(b,d){var m=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+l++,k=a.document.createElement("script");a[m]=function(d){k.parentNode.removeChild(k);b(r(f.type,d));delete a[m]};k.onerror=function(){k.parentNode.removeChild(k);d(Error("JSONP request failed"));delete a[m]};null==f.data&&(f.data={});f.url=n(f.url,f.data);f.data[f.callbackKey||"callback"]=m;k.src=h(f.url,f.data);a.document.documentElement.appendChild(k)}))}, -setCompletionCallback:function(a){w=a}}}(window,"undefined"!==typeof Promise?Promise:z),I=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1=u&&B>=n;){var y=a[u],l=e[n];if(y!==l||g)if(null!=y&&null!=l&&y.key===l.key)u++,n++,h(c,y,l,f,q(a,u,d),g, -m),g&&y.tag===l.tag&&r(c,v(y),d);else if(y=a[w],y!==l||g)if(null!=y&&null!=l&&y.key===l.key)h(c,y,l,f,q(a,w+1,d),g,m),(g||n=u&&B>=n;){y=a[w];l=e[B];if(y!==l||g)if(null!=y&&null!=l&&y.key===l.key)h(c,y,l,f,q(a,w+1,d),g,m),g&&y.tag===l.tag&&r(c,v(y),d),null!=y.dom&&(d=y.dom),w--;else{if(!x){x=a;var y=w,D={},A;for(A=0;Aa.indexOf("?")?"?":"&";a+=d+f}return a}function w(a){try{return""!== +a?JSON.parse(a):null}catch(x){throw Error(a);}}function p(a){return a.responseText}function r(a,b){if("function"===typeof a)if(b instanceof Array)for(var d=0;dn.status||304===n.status)b(r(f.type,a));else{var h=Error(n.responseText),k;for(k in a)h[k]=a[k];d(h)}}catch(F){d(F)}}; +q&&null!=f.data?n.send(f.data):n.send()}))},jsonp:function(f){return d(new b(function(b,d){var n=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+m++,k=a.document.createElement("script");a[n]=function(d){k.parentNode.removeChild(k);b(r(f.type,d));delete a[n]};k.onerror=function(){k.parentNode.removeChild(k);d(Error("JSONP request failed"));delete a[n]};null==f.data&&(f.data={});f.url=l(f.url,f.data);f.data[f.callbackKey||"callback"]=n;k.src=h(f.url,f.data);a.document.documentElement.appendChild(k)}))}, +setCompletionCallback:function(a){u=a}}}(window,"undefined"!==typeof Promise?Promise:z),I=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1=v&&B>=l;){var y=a[v],m=e[l];if(y!==m||g)if(null==y)v++;else if(null==m)l++;else if(y.key===m.key)v++,l++, +h(c,y,m,f,p(a,v,d),g,n),g&&y.tag===m.tag&&r(c,w(y),d);else if(y=a[u],y!==m||g)if(null==y)u--;else if(null==m)l++;else if(y.key===m.key)h(c,y,m,f,p(a,u+1,d),g,n),(g||l=v&&B>=l;){y=a[u];m=e[B];if(y!==m||g)if(null==y)u--;else{if(null!=m)if(y.key===m.key)h(c,y,m,f,p(a,u+1,d),g,n),g&&y.tag===m.tag&&r(c,w(y),d),null!=y.dom&&(d=y.dom),u--;else{if(!x){x=a;var y=u,D={},A;for(A=0;A= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] if (o === v && !recycling) oldStart++, start++ - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldStart++ + else if (v == null) start++ + else if (o.key === v.key) { oldStart++, start++ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) @@ -149,7 +151,9 @@ module.exports = function($window) { else { var o = old[oldEnd] if (o === v && !recycling) oldEnd--, start++ - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldEnd-- + else if (v == null) start++ + else if (o.key === v.key) { updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) oldEnd--, start++ @@ -160,7 +164,9 @@ module.exports = function($window) { while (oldEnd >= oldStart && end >= start) { var o = old[oldEnd], v = vnodes[end] if (o === v && !recycling) oldEnd--, end-- - else if (o != null && v != null && o.key === v.key) { + else if (o == null) oldEnd-- + else if (v == null) end-- + else if (o.key === v.key) { updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) if (o.dom != null) nextSibling = o.dom diff --git a/render/tests/test-updateNodes.js b/render/tests/test-updateNodes.js index b8468bc8..e56a828c 100644 --- a/render/tests/test-updateNodes.js +++ b/render/tests/test-updateNodes.js @@ -715,6 +715,22 @@ o.spec("updateNodes", function() { o(updated[2].dom.nodeName).equals("A") o(updated[2].dom).equals(root.childNodes[2]) }) + o("change type, position and length", function() { + var vnodes = {tag: "div", children: [ + undefined, + {tag: "#", children: "a"} + ]} + var updated = {tag: "div", children: [ + {tag: "[", children: [{tag: "#", children: "b"}]}, + undefined, + undefined + ]} + + render(root, vnodes) + render(root, updated) + + o(root.firstChild.childNodes.length).equals(1) + }) o("removes then recreates then reverses children", function() { var vnodes = [{tag: "a", key: 1, children: [{tag: "i", key: 3}, {tag: "s", key: 4}]}, {tag: "b", key: 2}] var temp1 = []