Skip to content
Browse files

Fixes #2311, #2323: when elements are removed from their previous pos…

…ition when they are added elsewhere, make sure to remove them from composed, not logical parent.
  • Loading branch information...
1 parent 0f8483d commit 3d931160db3060aedfbdfc684314284b1f2e755b @sorvell sorvell committed
Showing with 327 additions and 2 deletions.
  1. +1 −1 src/lib/dom-api.html
  2. +325 −0 test/unit/polymer-dom-content.html
  3. +1 −1 test/unit/polymer-dom.js
View
2 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);
}
},
View
325 test/unit/polymer-dom-content.html
@@ -29,6 +29,26 @@
</script>
</dom-module>
+<dom-module id="x-dist-inside-deep-tree">
+ <template>
+ x-dist-inside-deep-tree
+ <div></div>
+ <div>
+ <div>
+ <div>
+ <div id="distWrapper"><content id="content"></content></div>
+ </div>
+ </div>
+ </div>
+ <div></div>
+ </template>
+ <script>
+ HTMLImports.whenReady(function() {
+ Polymer({is: 'x-dist-inside-deep-tree'});
+ });
+ </script>
+</dom-module>
+
<dom-module id="x-no-dist">
<template><span id="static">x-no-dist</span></template>
<script>
@@ -191,6 +211,27 @@
</script>
</dom-module>
+<dom-module id="x-repeat">
+ <template>
+ <x-dist-inside-deep-tree id="dist">
+ <template is="dom-repeat" items="{{items}}"><div>{{item}}</div></template>
+ </x-dist-inside-deep-tree>
+ </template>
+ <script>
+ HTMLImports.whenReady(function() {
+ Polymer({
+ is: 'x-repeat',
+ properties: {
+ items: {
+ type: Array,
+ value: ["ITEM1", "ITEM2", "ITEM3"]
+ }
+ }
+ });
+ });
+ </script>
+</dom-module>
+
<x-compose-lazy-no-dist><span>Child</span></x-compose-lazy-no-dist>
@@ -877,6 +918,290 @@
document.body.removeChild(h2);
});
+ test('moving children between distributing hosts (parsed child)', function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<x-dist><div></div></x-dist>';
+ 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 = '<x-dist><div></div></x-dist>';
+ 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 = '<x-dist-inside-deep-tree><div></div></x-dist-inside-deep-tree>';
+ 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 = '<x-dist-inside-deep-tree><div></div></x-dist-inside-deep-tree>';
+ 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() {
View
2 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'));

0 comments on commit 3d93116

Please sign in to comment.
Something went wrong with that request. Please try again.