Fix patch() so that the root is patched instead of recreated

Previously, patch(element, vnode) would create a new element every time
for the top-level element, unless the top-level vnode had no id and
className. This is because emptyNodeAt() would create a vnode with sel
equal to the element's tagName, NOT including id and className.

This seems to be just a small fix, however this fix was crucial to get
Web Components (custom elements) working with Cycle.js, because the
custom element's "create" callback was being called infinitely and
recursively, because snabbdom was creating the top-level element every
time, even if the sel of oldVNode and vnode were supposed to be the
same.
pull/159/head
Andre Staltz 9 years ago
parent f178f91dfa
commit c091c59c59

@ -39,7 +39,9 @@ function init(modules, api) {
}
function emptyNodeAt(elm) {
return VNode(api.tagName(elm).toLowerCase(), {}, [], undefined, elm);
var id = elm.id ? '#' + elm.id : '';
var c = elm.className ? '.' + elm.className.split(' ').join('.') : '';
return VNode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);
}
function createRmCb(childElm, listeners) {

@ -136,6 +136,17 @@ describe('snabbdom', function() {
done();
}
});
it('is a patch of the root element', function () {
var elmWithIdAndClass = document.createElement('div');
elmWithIdAndClass.id = 'id';
elmWithIdAndClass.className = 'class';
var vnode1 = h('div#id.class', [h('span', 'Hi')]);
elm = patch(elmWithIdAndClass, vnode1).elm;
assert.strictEqual(elm, elmWithIdAndClass);
assert.equal(elm.tagName, 'DIV');
assert.equal(elm.id, 'id');
assert.equal(elm.className, 'class');
});
});
describe('pathing an element', function() {
it('changes the elements classes', function() {
@ -670,7 +681,7 @@ describe('snabbdom', function() {
{remove: function(_, rm) { rm2 = rm; }},
]);
var vnode1 = h('div', [h('a', {hook: {remove: function(_, rm) { rm3 = rm; }}})]);
var vnode2 = h('div', []);
var vnode2 = h('div', []);
elm = patch(vnode0, vnode1).elm;
assert.equal(elm.children.length, 1);
elm = patch(vnode1, vnode2).elm;
@ -686,7 +697,7 @@ describe('snabbdom', function() {
var result = [];
var parent = document.createElement('div');
var vnode0 = document.createElement('div');
parent.appendChild(vnode0);
parent.appendChild(vnode0);
function cb(vnode, rm) {
result.push(vnode);
rm();
@ -725,7 +736,7 @@ describe('snabbdom', function() {
h('span', 'Child 2'),
]),
]);
var vnode2 = h('div');
var vnode2 = h('div');
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(result.length, 1);
@ -752,7 +763,7 @@ describe('snabbdom', function() {
h('span', 'Child 2'),
]),
]);
var vnode2 = h('div');
var vnode2 = h('div');
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(created, 4);
@ -770,7 +781,7 @@ describe('snabbdom', function() {
'',
h('span', 'Third child'),
]);
var vnode2 = h('div');
var vnode2 = h('div');
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(created, 2);
@ -790,7 +801,7 @@ describe('snabbdom', function() {
h('span', ['Text 1', 'Text 2']),
]),
]);
var vnode2 = h('div');
var vnode2 = h('div');
patch(vnode0, vnode1);
patch(vnode1, vnode2);
assert.equal(created, 4);

Loading…
Cancel
Save