From 3d931160db3060aedfbdfc684314284b1f2e755b Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Thu, 20 Aug 2015 12:13:42 -0700 Subject: [PATCH] Fixes #2311, #2323: when elements are removed from their previous position when they are added elsewhere, make sure to remove them from composed, not logical parent. --- src/lib/dom-api.html | 2 +- test/unit/polymer-dom-content.html | 325 +++++++++++++++++++++++++++++ test/unit/polymer-dom.js | 2 +- 3 files changed, 327 insertions(+), 2 deletions(-) diff --git a/src/lib/dom-api.html b/src/lib/dom-api.html index 285db365d9..1be13b3bde 100644 --- a/src/lib/dom-api.html +++ b/src/lib/dom-api.html @@ -289,7 +289,7 @@ this._updateInsertionPoints(root.host); this._lazyDistribute(root.host); } else if (ensureComposedRemoval) { - removeFromComposedParent(parent || node.parentNode, node); + removeFromComposedParent(node._composedParent, node); } }, diff --git a/test/unit/polymer-dom-content.html b/test/unit/polymer-dom-content.html index dd6feb4444..c10224a0d6 100644 --- a/test/unit/polymer-dom-content.html +++ b/test/unit/polymer-dom-content.html @@ -29,6 +29,26 @@ + + + + + + + + + + Child @@ -877,6 +918,290 @@ document.body.removeChild(h2); }); + test('moving children between distributing hosts (parsed child)', function() { + var div = document.createElement('div'); + div.innerHTML = '
'; + var h1 = div.firstChild; + var h2 = document.createElement('x-dist'); + document.body.appendChild(div); + document.body.appendChild(h2); + Polymer.dom.flush(); + var d = Polymer.dom(h1).firstElementChild; + assert.equal(d.localName, 'div'); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(div); + document.body.removeChild(h2); + }); + + test('moving children between distributing host and fragment', function() { + var h1 = document.createElement('x-dist'); + var h2 = document.createDocumentFragment();; + document.body.appendChild(h1); + Polymer.dom.flush(); + var d = document.createElement('div'); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(h1); + }); + + test('moving children between distributing host and fragment (parsed child)', function() { + var div = document.createElement('div'); + div.innerHTML = '
'; + var h1 = div.firstChild; + var h2 = document.createDocumentFragment();; + document.body.appendChild(h1); + Polymer.dom.flush(); + var d = Polymer.dom(h1).firstElementChild; + assert.equal(d.localName, 'div'); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(h1); + }); + + test('moving children between distributing hosts with deep insertion points', function() { + var h1 = document.createElement('x-dist-inside-deep-tree'); + var h2 = document.createElement('x-dist-inside-deep-tree'); + document.body.appendChild(h1); + document.body.appendChild(h2); + Polymer.dom.flush(); + var d = document.createElement('div'); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(h1); + document.body.removeChild(h2); + }); + + test('moving children between distributing hosts with deep insertion points (parsed child)', function() { + var div = document.createElement('div'); + div.innerHTML = '
'; + var h1 = div.firstChild; + var h2 = document.createElement('x-dist-inside-deep-tree'); + document.body.appendChild(div); + document.body.appendChild(h2); + Polymer.dom.flush(); + var d = Polymer.dom(h1).firstElementChild; + assert.equal(d.localName, 'div'); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes().length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.deepEqual(Polymer.dom(h2.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(div); + document.body.removeChild(h2); + }); + + test('moving children between distributing host with deep insertion and fragment', function() { + var h1 = document.createElement('x-dist-inside-deep-tree'); + var h2 = document.createDocumentFragment();; + document.body.appendChild(h1); + Polymer.dom.flush(); + var d = document.createElement('div'); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(h1); + }); + + test('moving children between distributing host with deep insertion and fragment (parsed child)', function() { + var div = document.createElement('div'); + div.innerHTML = '
'; + var h1 = div.firstChild; + var h2 = document.createDocumentFragment();; + document.body.appendChild(h1); + Polymer.dom.flush(); + var d = Polymer.dom(h1).firstElementChild; + assert.equal(d.localName, 'div'); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + Polymer.dom(h1).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h1).childNodes.length, 1); + assert.equal(Polymer.dom(h1).firstElementChild, d); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes(), [d]); + assert.equal(Polymer.dom(h2).childNodes.length, 0); + Polymer.dom(h2).appendChild(d); + Polymer.dom.flush(); + assert.equal(Polymer.dom(h2).childNodes.length, 1); + assert.equal(Polymer.dom(h2).firstElementChild, d); + assert.equal(Polymer.dom(h1).childNodes.length, 0); + assert.deepEqual(Polymer.dom(h1.$.content).getDistributedNodes().length, 0); + document.body.removeChild(h1); + }); + + test('moving an element containing a dom-repeat that distributes items', function() { + var x1 = document.createElement('x-repeat'); + var div = document.createElement('div'); + Polymer.dom(document.body).appendChild(x1); + Polymer.dom(document.body).appendChild(div); + Polymer.dom.flush(); + assert.equal(Polymer.dom(x1.$.dist).children.length, 4); + if (x1.$.dist.shadyRoot) { + assert.equal(x1.$.dist.$.distWrapper.children.length, 4); + } + Polymer.dom(div).appendChild(x1); + Polymer.dom.flush(); + assert.equal(Polymer.dom(x1.$.dist).children.length, 4); + if (x1.$.dist.shadyRoot) { + assert.equal(x1.$.dist.$.distWrapper.children.length, 4); + } + Polymer.dom(document.body).appendChild(x1); + Polymer.dom.flush(); + assert.equal(Polymer.dom(x1.$.dist).children.length, 4); + if (x1.$.dist.shadyRoot) { + assert.equal(x1.$.dist.$.distWrapper.children.length, 4); + } + Polymer.dom(div).appendChild(x1); + Polymer.dom.flush(); + assert.equal(Polymer.dom(x1.$.dist).children.length, 4); + if (x1.$.dist.shadyRoot) { + assert.equal(x1.$.dist.$.distWrapper.children.length, 4); + } + Polymer.dom(document.body).removeChild(div); + }); + }); suite('multi-content mutations', function() { diff --git a/test/unit/polymer-dom.js b/test/unit/polymer-dom.js index 18873c8b70..bf7f0e6ead 100644 --- a/test/unit/polymer-dom.js +++ b/test/unit/polymer-dom.js @@ -59,7 +59,7 @@ suite('Polymer.dom', function() { Polymer.dom.flush(); assert.equal(Polymer.dom(el.$.container).querySelectorAll('*').length, 6, 'querySelectorAll finds repeated elements'); document.body.removeChild(el); - }) + }); test('querySelector document', function() { assert.ok(Polymer.dom().querySelector('body'));