Skip to content

Commit 5a482c6

Browse files
committed
Merge pull request #2243 from Polymer/fix-2235
Fixes #2235. Manages logical information in shady distribution more d…
2 parents d55be7d + 45cb150 commit 5a482c6

File tree

6 files changed

+84
-16
lines changed

6 files changed

+84
-16
lines changed

src/lib/dom-api.html

+33-7
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,15 @@
6565
// 3. node is <content> (host of container needs distribution)
6666
appendChild: function(node) {
6767
var handled;
68+
// if a <content> is added, make sure it's parent has logical info.
69+
this._ensureContentLogicalInfo(node);
6870
this._removeNodeFromHost(node, true);
6971
if (this._nodeIsInLogicalTree(this.node)) {
7072
this._addLogicalInfo(node, this.node);
7173
this._addNodeToHost(node);
7274
handled = this._maybeDistribute(node, this.node);
75+
} else {
76+
this._addNodeToHost(node);
7377
}
7478
// if not distributing and not adding to host, do a fast path addition
7579
if (!handled && !this._tryRemoveUndistributedNode(node)) {
@@ -86,9 +90,10 @@
8690
return this.appendChild(node);
8791
}
8892
var handled;
93+
// if a <content> is added, make sure it's parent has logical info.
94+
this._ensureContentLogicalInfo(node);
8995
this._removeNodeFromHost(node, true);
9096
if (this._nodeIsInLogicalTree(this.node)) {
91-
saveLightChildrenIfNeeded(this.node);
9297
var children = this.childNodes;
9398
var index = children.indexOf(ref_node);
9499
if (index < 0) {
@@ -98,6 +103,8 @@
98103
this._addLogicalInfo(node, this.node, index);
99104
this._addNodeToHost(node);
100105
handled = this._maybeDistribute(node, this.node);
106+
} else {
107+
this._addNodeToHost(node);
101108
}
102109
// if not distributing and not adding to host, do a fast path addition
103110
if (!handled && !this._tryRemoveUndistributedNode(node)) {
@@ -125,6 +132,8 @@
125132
if (this._nodeIsInLogicalTree(this.node)) {
126133
this._removeNodeFromHost(node);
127134
handled = this._maybeDistribute(node, this.node);
135+
} else {
136+
this._removeNodeFromHost(node);
128137
}
129138
if (!handled) {
130139
// if removing from a shadyRoot, remove form host instead
@@ -223,18 +232,37 @@
223232
},
224233

225234
_updateInsertionPoints: function(host) {
226-
host.shadyRoot._insertionPoints =
235+
var i$ = host.shadyRoot._insertionPoints =
227236
factory(host.shadyRoot).querySelectorAll(CONTENT);
237+
// ensure <content>'s and their parents have logical dom info.
238+
for (var i=0, c; i < i$.length; i++) {
239+
c = i$[i];
240+
saveLightChildrenIfNeeded(c);
241+
saveLightChildrenIfNeeded(factory(c).parentNode);
242+
}
228243
},
229244

230245
// a node is in a shadyRoot, is a shadyRoot,
231246
// or has a lightParent
232247
_nodeIsInLogicalTree: function(node) {
233248
return Boolean((node._lightParent !== undefined) || node._isShadyRoot ||
234-
this._ownerShadyRootForNode(node) ||
235249
node.shadyRoot);
236250
},
237251

252+
_ensureContentLogicalInfo: function(node) {
253+
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
254+
saveLightChildrenIfNeeded(this.node);
255+
var c$ = Array.prototype.slice.call(node.childNodes);
256+
for (var i=0, n; (i<c$.length) && (n=c$[i]); i++) {
257+
this._ensureContentLogicalInfo(n);
258+
}
259+
} else if (node.localName === CONTENT) {
260+
// should be parent not this.node, but this is before parent is set.
261+
saveLightChildrenIfNeeded(this.node);
262+
saveLightChildrenIfNeeded(node);
263+
}
264+
},
265+
238266
_parentNeedsDistribution: function(parent) {
239267
return parent && parent.shadyRoot && hasInsertionPoint(parent.shadyRoot);
240268
},
@@ -292,17 +320,15 @@
292320
}
293321
},
294322

323+
// a node being added is always in this same host as this.node.
295324
_addNodeToHost: function(node) {
296-
var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ?
297-
node.firstChild : node;
298-
var root = this._ownerShadyRootForNode(checkNode);
325+
var root = this.getOwnerRoot();
299326
if (root) {
300327
root.host._elementAdd(node);
301328
}
302329
},
303330

304331
_addLogicalInfo: function(node, container, index) {
305-
saveLightChildrenIfNeeded(container);
306332
var children = factory(container).childNodes;
307333
index = index === undefined ? children.length : index;
308334
// handle document fragments

src/mini/shady.html

+10-8
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,19 @@
5353
this.shadyRoot._isShadyRoot = true;
5454
this.shadyRoot._dirtyRoots = [];
5555
// capture insertion point list
56-
this.shadyRoot._insertionPoints = !this._notes ||
56+
var i$ = this.shadyRoot._insertionPoints = !this._notes ||
5757
this._notes._hasContent ?
5858
this.shadyRoot.querySelectorAll('content') : [];
59-
// save logical tree info for shadyRoot.
59+
// save logical tree info
60+
// a. for shadyRoot
61+
// b. for insertion points (fallback)
62+
// c. for parents of insertion points
6063
saveLightChildrenIfNeeded(this.shadyRoot);
64+
for (var i=0, c; i < i$.length; i++) {
65+
c = i$[i];
66+
saveLightChildrenIfNeeded(c);
67+
saveLightChildrenIfNeeded(c.parentNode);
68+
}
6169
this.shadyRoot.host = this;
6270
},
6371

@@ -406,9 +414,6 @@
406414
}
407415
// remove child from its old parent first
408416
remove(newChild);
409-
// make sure we never lose logical DOM information:
410-
// if the parentNode doesn't have lightChildren, save that information now.
411-
saveLightChildrenIfNeeded(parentNode);
412417
// insert it into the real DOM
413418
nativeInsertBefore.call(parentNode, newChild, refChild || null);
414419
newChild._composedParent = parentNode;
@@ -417,9 +422,6 @@
417422
function remove(node) {
418423
var parentNode = getComposedParent(node);
419424
if (parentNode) {
420-
// make sure we never lose logical DOM information:
421-
// if the parentNode doesn't have lightChildren, save that information now.
422-
saveLightChildrenIfNeeded(parentNode);
423425
node._composedParent = null;
424426
// remove it from the real DOM
425427
nativeRemoveChild.call(parentNode, node);

test/unit/polymer-dom-shadow.html

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
<x-redistribute-a-b></x-redistribute-a-b>
4949

50+
<div id="container">
51+
<x-echo></x-echo>
52+
<span>1</span>
53+
<span>2</span>
54+
</div>
55+
5056
<script src="polymer-dom.js"></script>
5157

5258
</body>

test/unit/polymer-dom.html

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747

4848
<x-redistribute-a-b></x-redistribute-a-b>
4949

50+
<div id="container">
51+
<x-echo></x-echo>
52+
<span>1</span>
53+
<span>2</span>
54+
</div>
55+
5056
<script src="polymer-dom.js"></script>
5157

5258
</body>

test/unit/polymer-dom.js

+28
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,34 @@ suite('Polymer.dom', function() {
424424
assert.equal(Polymer.dom(rere.root).querySelectorAll('span').length, 0);
425425
});
426426

427+
test('appendChild interacts with unmanaged parent tree', function() {
428+
var container = document.querySelector('#container');
429+
var echo = Polymer.dom(container).firstElementChild;
430+
assert.equal(echo.localName, 'x-echo');
431+
var s1 = Polymer.dom(echo).nextElementSibling;
432+
assert.equal(s1.textContent, '1');
433+
var s2 = Polymer.dom(s1).nextElementSibling;
434+
assert.equal(s2.textContent, '2');
435+
assert.equal(Polymer.dom(container).children.length, 3);
436+
Polymer.dom(echo).appendChild(s1);
437+
Polymer.dom.flush();
438+
assert.equal(Polymer.dom(container).children.length, 2);
439+
assert.equal(Polymer.dom(echo).nextElementSibling, s2);
440+
Polymer.dom(echo).appendChild(s2);
441+
Polymer.dom.flush();
442+
assert.equal(Polymer.dom(container).children.length, 1);
443+
assert.equal(Polymer.dom(echo).nextElementSibling, null);
444+
Polymer.dom(container).appendChild(s1);
445+
Polymer.dom.flush();
446+
assert.equal(Polymer.dom(container).children.length, 2);
447+
assert.equal(Polymer.dom(echo).nextElementSibling, s1);
448+
Polymer.dom(container).appendChild(s2);
449+
Polymer.dom.flush();
450+
assert.equal(Polymer.dom(container).children.length, 3);
451+
assert.equal(Polymer.dom(echo).nextElementSibling, s1);
452+
assert.equal(Polymer.dom(s1).nextElementSibling, s2);
453+
});
454+
427455
test('distribute (forced)', function() {
428456
var rere = Polymer.dom(testElement.root).querySelector('x-rereproject');
429457
var re = Polymer.dom(rere.root).querySelector('x-reproject');

test/unit/shady.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@
473473
}
474474

475475
function updateRootInsertionPoints(root) {
476-
root._insertionPoints = root.querySelectorAll('content');
476+
Polymer.dom(root.host)._updateInsertionPoints(root.host);
477477
}
478478

479479
function getComposedHTML(node) {

0 commit comments

Comments
 (0)