diff --git a/mithril.js b/mithril.js index b32feeef..0b180154 100644 --- a/mithril.js +++ b/mithril.js @@ -547,7 +547,7 @@ var _14 = function($window) { var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map0 while (oldEnd >= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] - if (o === v) oldStart++, start++ + if (o === v && !recycling) oldStart++, start++ else if (o != null && v != null && o.key === v.key) { oldStart++, start++ updateNode(parent0, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) @@ -555,10 +555,10 @@ var _14 = function($window) { } else { var o = old[oldEnd] - if (o === v) oldEnd--, start++ + if (o === v && !recycling) oldEnd--, start++ else if (o != null && v != null && o.key === v.key) { updateNode(parent0, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) - if (start < end) insertNode(parent0, toFragment(o), getNextSibling(old, oldStart, nextSibling)) + if (recycling || start < end) insertNode(parent0, toFragment(o), getNextSibling(old, oldStart, nextSibling)) oldEnd--, start++ } else break @@ -566,7 +566,7 @@ var _14 = function($window) { } while (oldEnd >= oldStart && end >= start) { var o = old[oldEnd], v = vnodes[end] - if (o === v) oldEnd--, end-- + if (o === v && !recycling) oldEnd--, end-- else if (o != null && v != null && o.key === v.key) { updateNode(parent0, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) if (recycling && o.tag === v.tag) insertNode(parent0, toFragment(o), nextSibling) diff --git a/mithril.min.js b/mithril.min.js index e7525777..35aff7af 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,42 +1,43 @@ -new function(){function u(b,e,m,g,k,h){return{tag:b,key:e,attrs:m,children:g,text:k,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function v(b){if(null==b||"string"!==typeof b&&null==b.view)throw Error("The selector must be either a string or a component.");if("string"===typeof b&&void 0===F[b]){for(var e,m,g=[],k={};e=O.exec(b);){var h=e[1],q=e[2];""===h&&""!==q?m=q:"#"===h?k.id=q:"."===h?g.push(q):"["===e[3][0]&&((h=e[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -k[e[4]]=h||!0)}0d.filter(D).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream");return w(e(),d,function(){var b= -d.filter(L);if(0b.indexOf("?")?"?":"&";b+=h+g}return b}function k(b){try{return""!==b?JSON.parse(b):null}catch(e){throw Error(b);}}function h(b){return b.responseText}function q(b,e){if("function"===typeof b)if(e instanceof Array)for(var g=0;gn.status||304=== -n.status)l(q(f.type,b));else{var e=Error(n.responseText),g;for(g in b)e[g]=b[g];l.error(e)}}catch(k){l.error(k)}"function"===typeof r&&r()}};A?n.send(f.data):n.send();return l},jsonp:function(f){var h=e();void 0!==f.initialValue&&h(f.initialValue);var k=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+t++,n=b.document.createElement("script");b[k]=function(e){n.parentNode.removeChild(n);h(q(f.type,e));"function"===typeof r&&r();delete b[k]};n.onerror=function(){n.parentNode.removeChild(n); -h.error(Error("JSONP request failed"));"function"===typeof r&&r();delete b[k]};null==f.data&&(f.data={});f.url=m(f.url,f.data);f.data[f.callbackKey||"callback"]=k;n.src=g(f.url,f.data);b.document.documentElement.appendChild(n);return h},setCompletionCallback:function(b){r=b}}}(window,M),I=function(){var b=[];return{subscribe:b.push.bind(b),unsubscribe:function(e){e=b.indexOf(e);-1=l&&A>=n;){var x=a[l],p=d[n];if(x===p)l++,n++;else if(null!=x&&null!=p&&x.key===p.key)l++,n++,h(c,x,p,b,t(a,l,g),z,k),z&&x.tag===p.tag&&r(c,q(x),g);else if(x=a[w],x===p)w--,n++;else if(null!=x&&null!=p&&x.key===p.key)h(c,x,p,b,t(a,w+1,g),z,k),n=l&&A>=n;){x=a[w];p=d[A];if(x===p)w--;else if(null!=x&&null!=p&&x.key===p.key)h(c,x,p,b,t(a,w+1,g),z,k),z&&x.tag===p.tag&&r(c,q(x),g),null!=x.dom&&(g=x.dom),w--;else{if(!B){B=a;var x=w,u={},v;for(v=0;v< -x;v++){var C=B[v];null!=C&&(C=C.key,null!=C&&(u[C]=v))}B=u}null!=p&&(x=B[p.key],null!=x?(u=a[x],h(c,u,p,b,t(a,w+1,g),z,k),r(c,q(u),g),a[x].skip=!0,null!=u.dom&&(g=u.dom)):(p=m(p,b,void 0),r(c,p,g),g=p))}A--;if(Ad.filter(D).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream");return A(e(),d,function(){var b= +d.filter(L);if(0b.indexOf("?")?"?":"&";b+=m+f}return b}function h(b){try{return""!==b?JSON.parse(b):null}catch(e){throw Error(b);}}function k(b){return b.responseText}function m(b,e){if("function"===typeof b)if(e instanceof Array)for(var f=0;fp.status||304=== +p.status)l(m(g.type,b));else{var e=Error(p.responseText),f;for(f in b)e[f]=b[f];l.error(e)}}catch(h){l.error(h)}"function"===typeof q&&q()}};z?p.send(g.data):p.send();return l},jsonp:function(g){var h=e();void 0!==g.initialValue&&h(g.initialValue);var k=g.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+t++,p=b.document.createElement("script");b[k]=function(e){p.parentNode.removeChild(p);h(m(g.type,e));"function"===typeof q&&q();delete b[k]};p.onerror=function(){p.parentNode.removeChild(p); +h.error(Error("JSONP request failed"));"function"===typeof q&&q();delete b[k]};null==g.data&&(g.data={});g.url=n(g.url,g.data);g.data[g.callbackKey||"callback"]=k;p.src=f(g.url,g.data);b.document.documentElement.appendChild(p);return h},setCompletionCallback:function(b){q=b}}}(window,M),I=function(){var b=[];return{subscribe:b.push.bind(b),unsubscribe:function(e){e=b.indexOf(e);-1=l&&A>=z;){var x=a[l],r=d[z];if(x!==r||v)if(null!=x&&null!=r&&x.key===r.key)l++,z++,k(c,x,r,b,t(a,l,f),v,h),v&&x.tag===r.tag&&q(c,m(x),f);else if(x=a[p],x!==r||v)if(null!=x&&null!=r&&x.key===r.key)k(c,x,r,b,t(a,p+1,f),v,h),(v||z=l&&A>=z;){x=a[p];r=d[A];if(x!==r||v)if(null!=x&&null!=r&&x.key===r.key)k(c,x,r,b,t(a,p+1,f),v,h),v&&x.tag===r.tag&&q(c,m(x),f),null!=x.dom&&(f=x.dom),p--;else{if(!B){B=a;var x=p,u={},w;for(w= +0;w= oldStart && end >= start) { var o = old[oldStart], v = vnodes[start] - if (o === v) oldStart++, start++ + if (o === v && !recycling) oldStart++, start++ else if (o != null && v != null && o.key === v.key) { oldStart++, start++ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) @@ -140,10 +140,10 @@ module.exports = function($window) { } else { var o = old[oldEnd] - if (o === v) oldEnd--, start++ + if (o === v && !recycling) oldEnd--, start++ else if (o != null && v != null && o.key === v.key) { updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) - if (start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) + if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) oldEnd--, start++ } else break @@ -151,7 +151,7 @@ module.exports = function($window) { } while (oldEnd >= oldStart && end >= start) { var o = old[oldEnd], v = vnodes[end] - if (o === v) oldEnd--, end-- + if (o === v && !recycling) oldEnd--, end-- else if (o != null && v != null && 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) diff --git a/render/tests/test-oninit.js b/render/tests/test-oninit.js index 8123b1c8..1f0e7701 100644 --- a/render/tests/test-oninit.js +++ b/render/tests/test-oninit.js @@ -148,7 +148,6 @@ o.spec("oninit", function() { render(root, []) render(root, [updated]) - o(vnode.dom).equals(updated.dom) o(create.callCount).equals(1) o(create.this).equals(vnode.state) o(create.args[0]).equals(vnode) @@ -201,16 +200,4 @@ o.spec("oninit", function() { o(vnode.dom.oninit).equals(undefined) o(vnode.dom.attributes["oninit"]).equals(undefined) }) - o("calls oninit on recycle", function() { - var create = o.spy() - var vnodes = [{tag: "div", key: 1, attrs: {oninit: create}}] - var temp = [] - var updated = [{tag: "div", key: 1, attrs: {oninit: create}}] - - render(root, vnodes) - render(root, temp) - render(root, updated) - - o(create.callCount).equals(2) - }) }) diff --git a/render/tests/test-updateElement.js b/render/tests/test-updateElement.js index dfda41c5..28ba84ff 100644 --- a/render/tests/test-updateElement.js +++ b/render/tests/test-updateElement.js @@ -211,4 +211,38 @@ o.spec("updateElement", function() { o(updated.dom.attributes["class"].nodeValue).equals("b") }) + o("restores correctly when recycling", function() { + var vnode = {tag: "div", key: 1} + var updated = {tag: "div", key: 2} + + render(root, [vnode]) + var a = vnode.dom + + render(root, [updated]) + + render(root, [vnode]) + var c = vnode.dom + + o(root.childNodes.length).equals(1) + o(a).equals(c) + }) + o("restores correctly when recycling via map", function() { + var a = {tag: "div", key: 1} + var b = {tag: "div", key: 2} + var c = {tag: "div", key: 3} + var d = {tag: "div", key: 4} + var e = {tag: "div", key: 5} + var f = {tag: "div", key: 6} + + render(root, [a, b, c]) + var x = root.childNodes[1] + + render(root, [d]) + + render(root, [e, b, f]) + var y = root.childNodes[1] + + o(root.childNodes.length).equals(3) + o(x).equals(y) + }) })