diff --git a/src/lib/dom-api-shady.html b/src/lib/dom-api-shady.html
index e1f62ffe41..3e4a216e62 100644
--- a/src/lib/dom-api-shady.html
+++ b/src/lib/dom-api-shady.html
@@ -170,8 +170,8 @@
if (!node) {
return;
}
- if (node._ownerShadyRoot === undefined) {
- var root;
+ var root = node._ownerShadyRoot;
+ if (root === undefined) {
if (node._isShadyRoot) {
root = node;
} else {
@@ -183,9 +183,16 @@
root = null;
}
}
- node._ownerShadyRoot = root;
+ // memo-ize result for performance but only memo-ize a false-y
+ // result if node is in the document. This avoids a problem where a root
+ // can be cached while an element is inside a fragment.
+ // If this happens and we cache the result, the value can become stale
+ // because for perf we avoid processing the subtree of added fragments.
+ if (root || document.contains(node)) {
+ node._ownerShadyRoot = root;
+ }
}
- return node._ownerShadyRoot;
+ return root;
},
_maybeDistribute: function(node) {
diff --git a/test/smoke/owner-root.html b/test/smoke/owner-root.html
new file mode 100644
index 0000000000..f4ef1120fa
--- /dev/null
+++ b/test/smoke/owner-root.html
@@ -0,0 +1,59 @@
+
+
+
+
+ early owner-root
+
+
+
+
+
+
+
+
+
+
+
+
+ where am I?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/unit/polymer-dom.js b/test/unit/polymer-dom.js
index ab9f735d7f..80a330775e 100644
--- a/test/unit/polymer-dom.js
+++ b/test/unit/polymer-dom.js
@@ -1207,6 +1207,24 @@ suite('Polymer.dom non-distributed elements', function() {
assert.equal(Polymer.dom(test).getOwnerRoot(), c1.root, 'getOwnerRoot incorrect for child added to element in root');
});
+ test('getOwnerRoot when out of tree and adding subtree', function() {
+ var container = document.createDocumentFragment();
+ var test = document.createElement('div');
+ container.appendChild(test);
+ assert.notOk(Polymer.dom(test).getOwnerRoot(), 'getOwnerRoot incorrect when not in root');
+ var c1 = document.createElement('x-compose');
+ var project = c1.$.project;
+ Polymer.dom(project).appendChild(container);
+ Polymer.dom.flush();
+ assert.equal(Polymer.dom(test).getOwnerRoot(), c1.root, 'getOwnerRoot incorrect for child added to element in root');
+ Polymer.dom(project).removeChild(test);
+ Polymer.dom.flush();
+ assert.notOk(Polymer.dom(test).getOwnerRoot(), 'getOwnerRoot incorrect for child moved from a root to no root');
+ Polymer.dom(project).appendChild(test);
+ Polymer.dom.flush();
+ assert.equal(Polymer.dom(test).getOwnerRoot(), c1.root, 'getOwnerRoot incorrect for child added to element in root');
+ });
+
test('getOwnerRoot, subtree', function() {
var test = document.createElement('div');
var testChild = document.createElement('div');