diff --git a/src/render.ts b/src/render.ts index b7c66f3c..3860223b 100644 --- a/src/render.ts +++ b/src/render.ts @@ -174,6 +174,13 @@ const setValue = (element: T, propertyKey: PropertyKey, v */ const isListenerProperty = (propertyKey: string): propertyKey is `on${string}` => propertyKey[0] === 'o' && propertyKey[1] === 'n'; +/** + * Check if an item is in a list. + * @param items List of child nodes. + * @param item The item to check. + */ +const contains = (items: T[], item: T) => ([] as typeof items).indexOf.call(items, item) !== -1; + /** * Render a set of Nodes into another, with some checks for Nodes in order to avoid * useless changes in the tree and to mantain or update the state of compatible Nodes. @@ -259,7 +266,7 @@ export const internalRender = ( } const renderFragmentContext = getOrCreateContext(placeholder); - const isAttached = () => fragments.indexOf(renderFragmentContext) !== -1; + const isAttached = contains.bind(null, fragments, renderFragmentContext); let running = true; const requestUpdate: UpdateRequest = renderFragmentContext.requestUpdate = () => { if (renderFragmentContext.requestUpdate !== requestUpdate) { @@ -458,7 +465,7 @@ export const internalRender = ( const oldClasses = convertClasses(oldProperties.class); for (let i = 0, len = oldClasses.length; i < len; i++) { const className = oldClasses[i]; - if (newClasses.indexOf(className) === -1) { + if (contains(newClasses, className)) { classList.remove(className); } } @@ -492,7 +499,7 @@ export const internalRender = ( const Component = template.Component; if (type === 'string') { const observedAttributes = Component.observedAttributes; - if (!observedAttributes || observedAttributes.indexOf(propertyKey) === -1) { + if (!observedAttributes || contains(observedAttributes, propertyKey)) { const descriptor = (propertyKey in templateElement) && getPropertyDescriptor(templateElement, propertyKey); if (!descriptor || !descriptor.get || descriptor.set) { setValue(templateElement, propertyKey, value); @@ -585,7 +592,7 @@ export const internalRender = ( // now, we are confident that if the input is a Node or a Component, // check if Nodes are the same instance // (patch result should return same Node instances for compatible types) - if (templateNode.parentNode === root) { + if (contains(childNodes, templateNode)) { while (templateNode !== currentNode) { DOM.removeChild(root, currentNode, slot); currentNode = childNodes.item(currentIndex) as Node; diff --git a/test/render.spec.js b/test/render.spec.js index 9f560f70..acd8e8be 100644 --- a/test/render.spec.js +++ b/test/render.spec.js @@ -219,23 +219,43 @@ describe('render', function() { }); it('should update nodes', () => { - DNA.render(DNA.h('ul', { class: 'list' }, DNA.h('li', null, 'One'), DNA.h('li', null, 'Two'), DNA.h('li', null, 'Three'), DNA.h('li', null, 'Four')), wrapper); + DNA.render(DNA.h('ul', { class: 'list' }, + DNA.h('li', null, 'One'), + DNA.h('li', null, 'Two'), + DNA.h('li', null, 'Three'), + DNA.h('li', null, 'Four'), + DNA.h('li', null, 5), + DNA.h('li', null, '6') + ), wrapper); const list = wrapper.querySelector('ul.list'); const children = list.childNodes; expect(children[0].textContent).to.be.equal('One'); expect(children[1].textContent).to.be.equal('Two'); expect(children[2].textContent).to.be.equal('Three'); expect(children[3].textContent).to.be.equal('Four'); - DNA.render(DNA.h('ul', { class: 'list' }, DNA.h('li', null, 'Five'), DNA.h('li', null, 'Six'), DNA.h('li', null, 'Seven'), DNA.h('li', null, 'Height')), wrapper); + expect(children[4].textContent).to.be.equal('5'); + expect(children[5].textContent).to.be.equal('6'); + DNA.render(DNA.h('ul', { class: 'list' }, + DNA.h('li', null, 'Seven'), + DNA.h('li', null, 'Eight'), + DNA.h('li', null, 'Nine'), + DNA.h('li', null, 'Ten'), + DNA.h('li', null, 11), + DNA.h('li', null, 12) + ), wrapper); const newChildren = list.childNodes; expect(children[0]).to.be.equal(newChildren[0]); expect(children[1]).to.be.equal(newChildren[1]); expect(children[2]).to.be.equal(newChildren[2]); expect(children[3]).to.be.equal(newChildren[3]); - expect(children[0].textContent).to.be.equal('Five'); - expect(children[1].textContent).to.be.equal('Six'); - expect(children[2].textContent).to.be.equal('Seven'); - expect(children[3].textContent).to.be.equal('Height'); + expect(children[4]).to.be.equal(newChildren[4]); + expect(children[5]).to.be.equal(newChildren[5]); + expect(children[0].textContent).to.be.equal('Seven'); + expect(children[1].textContent).to.be.equal('Eight'); + expect(children[2].textContent).to.be.equal('Nine'); + expect(children[3].textContent).to.be.equal('Ten'); + expect(children[4].textContent).to.be.equal('11'); + expect(children[5].textContent).to.be.equal('12'); }); it('should update add and remove attributes', () => {