Merge pull request #3322 from Polymer/fix-3321

Fixes 3321
This commit is contained in:
Steve Orvell 2016-01-22 20:05:05 -08:00
commit e13b28143d
5 changed files with 171 additions and 18 deletions

View File

@ -99,8 +99,30 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TreeApi.Logical.recordInsertBefore(node, this.node, ref_node);
}
// if not distributing and not adding to host, do a fast path addition
return (this._maybeDistribute(node) ||
this._tryRemoveUndistributedNode(node));
var handled = this._maybeDistribute(node) ||
this.node.shadyRoot;
// if shady is handling this node,
// the actual dom may not be removed if the node or fragment contents
// remain undistributed so we ensure removal here.
// NOTE: we only remove from existing location iff shady dom is involved.
// This is because a node fragment is passed to the native add method
// which expects to see fragment children. Regular elements must also
// use this check because not doing so causes separation of
// attached/detached and breaks, for example,
// dom-if's attached/detached checks.
if (handled) {
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
while (node.firstChild) {
TreeApi.Composed.removeChild(node, node.firstChild);
}
} else {
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
TreeApi.Composed.removeChild(parent, node);
}
}
}
return handled;
},
/**
@ -117,7 +139,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var container = this.node._isShadyRoot ? this.node.host : this.node;
// not guaranteed to physically be in container; e.g.
// undistributed nodes.
if (container === node.parentNode) {
var parent = TreeApi.Composed.getParentNode(node);
if (container === parent) {
TreeApi.Composed.removeChild(container, node);
}
}
@ -257,16 +280,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return added;
},
_tryRemoveUndistributedNode: function(node) {
if (this.node.shadyRoot) {
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
TreeApi.Composed.removeChild(parent, node);
}
return true;
}
},
_updateInsertionPoints: function(host) {
var i$ = host.shadyRoot._insertionPoints =
dom(host.shadyRoot).querySelectorAll(CONTENT);
@ -306,7 +319,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
for (var j=0; j<dc$.length; j++) {
hostNeedsDist = true;
var node = dc$[j];
var parent = node.parentNode;
var parent = TreeApi.Composed.getParentNode(node);
if (parent) {
TreeApi.Composed.removeChild(parent, node);
}

View File

@ -195,7 +195,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// the act of setting this info can affect patched nodes
// getters; therefore capture childNodes before patching.
for (var n=node.firstChild; n; n=n.nextSibling) {
this._linkNode(n, container, ref_node);
this._linkNode(n, container, ref_node);
}
} else {
this._linkNode(node, container, ref_node);

View File

@ -254,15 +254,20 @@ Then the `observe` property should be configured as follows:
},
detached: function() {
this.__isDetached = true;
for (var i=0; i<this._instances.length; i++) {
this._detachInstance(i);
}
},
attached: function() {
var parent = Polymer.dom(Polymer.dom(this).parentNode);
for (var i=0; i<this._instances.length; i++) {
this._attachInstance(i, parent);
// only perform attachment if the element was previously detached.
if (this.__isDetached) {
this.__isDetached = false;
var parent = Polymer.dom(Polymer.dom(this).parentNode);
for (var i=0; i<this._instances.length; i++) {
this._attachInstance(i, parent);
}
}
},

View File

@ -0,0 +1,62 @@
<!doctype html>
<html>
<head>
<title>distribute dom-repeat</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../polymer.html">
</head>
<body>
<dom-module id="x-container">
<template>
<content select="*"></content>
</template>
<script>
Polymer({
is: 'x-container'
})
</script>
</dom-module>
<dom-module id="x-test">
<template strip-whitespace>
<x-container id="container">
<template class="foo" id="nug" is="dom-repeat" items="{{model}}">
<div class="foo">{{item.id}}</div>
</template>
</x-container>
</template>
<script>
Polymer({
is: 'x-test',
ready: function() {
this.model = [
{id: '1', text: 'How much do you like food?'},
{id: '2', text: 'Where do you buy your groceries?'},
{id: '3', text: 'What is your favourite colour?'}
];
Polymer.dom.flush();
var self = this;
console.log(Polymer.dom(self.$.container).firstElementChild);
setTimeout(function() {
console.log('***');
console.log(Polymer.dom(self.$.container).firstElementChild);
}, 100);
}
})
</script>
</dom-module>
<x-test></x-test>
</body>
</html>

View File

@ -40,6 +40,15 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</script>
</dom-module>
<dom-module id="x-dist-star">
<template><content select="*"></content></template>
<script>
HTMLImports.whenReady(function() {
Polymer({is: 'x-dist-star'});
});
</script>
</dom-module>
<dom-module id="x-dist-inside-deep-tree">
<template>
x-dist-inside-deep-tree
@ -243,6 +252,31 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</script>
</dom-module>
<dom-module id="x-repeat2">
<template>
<x-dist-star id="dist">
<template is="dom-repeat" items="{{items}}">
<div>{{item}}</div>
</template>
</x-dist-star>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-repeat2',
properties: {
items: {
type: Array,
value: ["ITEM1", "ITEM2", "ITEM3"]
}
}
});
});
</script>
</dom-module>
<x-repeat2 id="repeat2"></x-repeat2>
<x-compose-lazy-no-dist><span>Child</span></x-compose-lazy-no-dist>
@ -1396,6 +1430,45 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
Polymer.dom(document.body).removeChild(div);
});
test('dom-repeat that distributes inside a select=* container', function(done) {
var x1 = document.querySelector('#repeat2');
Polymer.dom.flush();
// async due to attachment.
setTimeout(function() {
assert.equal(Polymer.dom(x1.$.dist).children.length, 4);
if (x1.$.dist.shadyRoot) {
assert.equal(x1.$.dist.children.length, 4);
}
done();
});
});
test('adding a document fragment clears nodes in the fragment', function() {
var x = document.createElement('x-dist-star');
var frag = document.createDocumentFragment();
var t = document.createTextNode('hi');
var d = document.createElement('div');
frag.appendChild(t);
frag.appendChild(d);
Polymer.dom(x).appendChild(frag);
Polymer.dom.flush();
assert.equal(Polymer.dom(t).parentNode, x, 'logical parent wrong');
assert.equal(Polymer.dom(d).parentNode, x, 'logical parent wrong');
assert.equal(frag.childNodes.length, 0, 'fragment not empty');
});
test('adding a non-distributing node removes the node from its current location', function() {
var x = document.createElement('x-dist-star');
var t = document.createTextNode('hi');
document.body.appendChild(t);
Polymer.dom(x).appendChild(t);
Polymer.dom.flush();
assert.equal(Polymer.dom(t).parentNode, x);
if (x.shadyRoot) {
assert.isNull(t.parentNode);
}
});
});
suite('multi-content mutations', function() {