Always provoke distribution on any hosts that are redistribution candidates. This prevents invalid logical dom state.

This commit is contained in:
Steven Orvell
2015-05-11 19:59:30 -07:00
parent 1deb578c3b
commit da0cddf5e6
6 changed files with 87 additions and 23 deletions

View File

@@ -191,6 +191,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var p$ = node._insertionPoints;
for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) {
this._distributeInsertionPoint(p, pool);
// provoke redistribution on insertion point parents
// must do this on all candidate hosts since distribution in this
// scope invalidates their distribution.
maybeRedistributeParent(p, this);
}
},
@@ -210,13 +214,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
pool[i] = undefined;
// since at least one node matched, we won't need fallback content
anyDistributed = true;
var parent = content.lightParent;
// dirty a shadyRoot if a change may trigger reprojection!
if (parent && parent.shadyRoot &&
hasInsertionPoint(parent.shadyRoot)) {
parent.shadyRoot._distributionClean = false;
this.shadyRoot._dirtyRoots.push(parent);
}
}
}
// Fallback content if nothing was distributed here
@@ -341,16 +338,28 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
}
function clearDistributedDestinationInsertionPoints(insertionPoint) {
var e$ = insertionPoint._distributedNodes;
function clearDistributedDestinationInsertionPoints(content) {
var e$ = content._distributedNodes;
for (var i=0; i < e$.length; i++) {
var d = e$[i]._destinationInsertionPoints;
if (d) {
d.splice(d.indexOf(insertionPoint)+1, d.length);
// this is +1 because these insertion points are *not* in this scope
d.splice(d.indexOf(content)+1, d.length);
}
}
}
// dirty a shadyRoot if a change may trigger reprojection!
function maybeRedistributeParent(content, host) {
var parent = content.lightParent;
if (parent && parent.shadyRoot &&
hasInsertionPoint(parent.shadyRoot) &&
parent.shadyRoot._distributionClean) {
parent.shadyRoot._distributionClean = false;
host.shadyRoot._dirtyRoots.push(parent);
}
}
function isFinalDestination(insertionPoint, node) {
var points = node._destinationInsertionPoints;
return points && points[points.length - 1] === insertionPoint;
@@ -415,10 +424,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
for (var i=0, c; i < c$.length; i++) {
c = c$[i];
if (c.localName === 'content') {
var s = c.getAttribute('select');
if (s && s !== '*') {
return true;
}
return true;
}
}
}

View File

@@ -11,21 +11,28 @@
<dom-module id="x-outer">
<template>
<x-inner>
<template is="dom-repeat" items="{{items}}">
<div item>{{item}}</div>
</template>
</x-inner>
<!-- <template is="dom-repeat" items="{{items}}"><div item>{{item}}</div></template> -->
<x-inner><div item>A</div><div item>B</div><div item>C</div></x-inner>
</template>
</dom-module>
<dom-module id="x-inner">
<style>
.one, .two {
display: block;
border: 2px solid orange;
margin: 10px;
padding: 10px;
}
.two {
border-color: green;
}
</style>
<template>
<x-inner-most>
<content class="item" select="[item]"></content>
</x-inner-most>
<x-inner-most class="one"><content class="item" select="[item]"></content></x-inner-most>
<content class="notItem" select=":not([item])"></content>
<x-inner-most class="two"><content class="notItem" select=":not([item])"></content></x-inner-most>
</template>
</dom-module>

View File

@@ -118,4 +118,19 @@
<dom-module id="x-select-class1">
<template><x-select-class2 id="select"><content select=".s1"></content></x-select-class2></template>
<script>Polymer({is: 'x-select-class1'});</script>
</dom-module>
<dom-module id="x-echo">
<template><content></content></template>
<script>Polymer({is: 'x-echo'});</script>
</dom-module>
<dom-module id="x-redistribute-a-b">
<template>
<x-echo id="echo1"><content select=".a"></content></x-echo>
<x-echo id="echo2"><content select=".b"></content></x-echo>
</template>
<script>Polymer({is: 'x-redistribute-a-b'});</script>
</dom-module>

View File

@@ -39,6 +39,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<div></div>
</x-select-class1>
<x-redistribute-a-b></x-redistribute-a-b>
<script src="polymer-dom.js"></script>
</body>

View File

@@ -38,6 +38,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<div></div>
</x-select-class1>
<x-redistribute-a-b></x-redistribute-a-b>
<script src="polymer-dom.js"></script>
</body>

View File

@@ -232,6 +232,38 @@ suite('Polymer.dom', function() {
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), []);
});
test('re-distribution results in correct logical tree when outer host remove a node from pool of inner host', function() {
var r = document.querySelector('x-redistribute-a-b');
var rc = Polymer.dom(r.root).querySelectorAll('content');
var ec1 = Polymer.dom(r.$.echo1.root).querySelector('content');
var ec2 = Polymer.dom(r.$.echo2.root).querySelector('content');
var child = document.createElement('div');
child.className = 'a';
Polymer.dom(r).appendChild(child);
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [rc[0], ec1]);
assert.deepEqual(Polymer.dom(rc[0]).getDistributedNodes(), [child]);
assert.deepEqual(Polymer.dom(rc[1]).getDistributedNodes(), []);
assert.deepEqual(Polymer.dom(ec1).getDistributedNodes(), [child]);
assert.deepEqual(Polymer.dom(ec2).getDistributedNodes(), []);
child.className = 'b';
r.distributeContent();
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [rc[1], ec2]);
assert.deepEqual(Polymer.dom(rc[0]).getDistributedNodes(), []);
assert.deepEqual(Polymer.dom(rc[1]).getDistributedNodes(), [child]);
assert.deepEqual(Polymer.dom(ec1).getDistributedNodes(), []);
assert.deepEqual(Polymer.dom(ec2).getDistributedNodes(), [child]);
child.className = 'a';
r.distributeContent();
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [rc[0], ec1]);
assert.deepEqual(Polymer.dom(rc[0]).getDistributedNodes(), [child]);
assert.deepEqual(Polymer.dom(rc[1]).getDistributedNodes(), []);
assert.deepEqual(Polymer.dom(ec1).getDistributedNodes(), [child]);
assert.deepEqual(Polymer.dom(ec2).getDistributedNodes(), []);
});
test('appendChild (light)', function() {
var rere = Polymer.dom(testElement.root).querySelector('x-rereproject');
var s = document.createElement('span');