Fixes #3308. Use an explicit undefined check to test if logical tree information exists.

This commit is contained in:
Steven Orvell 2016-01-19 11:45:29 -08:00
parent 9cd6b796a1
commit 9106398ccf
3 changed files with 60 additions and 11 deletions

View File

@ -82,28 +82,39 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return node.__dom.childNodes; return node.__dom.childNodes;
}, },
// NOTE: __dom can be created under 2 conditions: (1) an element has a
// logical tree, or (2) an element is in a logical tree. In case (1), the
// element will store firstChild/lastChild, and in case (2), the element
// will store parentNode, nextSibling, previousSibling. This means that
// the mere existence of __dom is not enough to know if the requested
// logical data is available and instead we do an explicit undefined check.
getParentNode: function(node) { getParentNode: function(node) {
return node.__dom && node.__dom.parentNode || node.parentNode; return node.__dom && node.__dom.parentNode !== undefined ?
node.__dom.parentNode : node.parentNode;
}, },
getFirstChild: function(node) { getFirstChild: function(node) {
return node.__dom && node.__dom.firstChild || node.firstChild; return node.__dom && node.__dom.firstChild !== undefined ?
node.__dom.firstChild : node.firstChild;
}, },
getLastChild: function(node) { getLastChild: function(node) {
return node.__dom && node.__dom.lastChild || node.lastChild; return node.__dom && node.__dom.lastChild !== undefined ?
node.__dom.lastChild : node.lastChild;
}, },
getNextSibling: function(node) { getNextSibling: function(node) {
return node.__dom && node.__dom.nextSibling || node.nextSibling; return node.__dom && node.__dom.nextSibling !== undefined ?
node.__dom.nextSibling : node.nextSibling;
}, },
getPreviousSibling: function(node) { getPreviousSibling: function(node) {
return node.__dom && node.__dom.previousSibling || node.previousSibling; return node.__dom && node.__dom.previousSibling !== undefined ?
node.__dom.previousSibling : node.previousSibling;
}, },
getFirstElementChild: function(node) { getFirstElementChild: function(node) {
return node.__dom && node.__dom.firstChild ? return node.__dom && node.__dom.firstChild !== undefined ?
this._getFirstElementChild(node) : node.firstElementChild; this._getFirstElementChild(node) : node.firstElementChild;
}, },
@ -116,8 +127,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
getLastElementChild: function(node) { getLastElementChild: function(node) {
return node.__dom && node.__dom.lastChild ? return node.__dom && node.__dom.lastChild !== undefined ?
this._getLastElementChild(node) : node.firstElementChild; this._getLastElementChild(node) : node.lastElementChild;
}, },
_getLastElementChild: function(node) { _getLastElementChild: function(node) {
@ -129,7 +140,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
getNextElementSibling: function(node) { getNextElementSibling: function(node) {
return node.__dom && node.__dom.nextSibling ? return node.__dom && node.__dom.nextSibling !== undefined ?
this._getNextElementSibling(node) : node.nextElementSibling; this._getNextElementSibling(node) : node.nextElementSibling;
}, },
@ -142,7 +153,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}, },
getPreviousElementSibling: function(node) { getPreviousElementSibling: function(node) {
return node.__dom && node.__dom.previousSibling ? return node.__dom && node.__dom.previousSibling !== undefined ?
this._getPreviousElementSibling(node) : node.previousElementSibling; this._getPreviousElementSibling(node) : node.previousElementSibling;
}, },
@ -241,8 +252,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
if (n) { if (n) {
n.__dom.previousSibling = p; n.__dom.previousSibling = p;
} }
// When an element is removed, logical data is no longer tracked.
// Explicitly set `undefined` here to indicate this. This is disginguished
// from `null` which is set if info is null.
node.__dom.parentNode = node.__dom.previousSibling = node.__dom.parentNode = node.__dom.previousSibling =
node.__dom.nextSibling = null; node.__dom.nextSibling = undefined;
// remove caching of childNodes // remove caching of childNodes
container.__dom.childNodes = null; container.__dom.childNodes = null;
} }

View File

@ -126,6 +126,11 @@
<script>Polymer({is: 'x-echo'});</script> <script>Polymer({is: 'x-echo'});</script>
</dom-module> </dom-module>
<dom-module id="x-simple">
<template><div>simple</div></template>
<script>Polymer({is: 'x-simple'});</script>
</dom-module>
<dom-module id="x-redistribute-a-b"> <dom-module id="x-redistribute-a-b">
<template> <template>

View File

@ -755,6 +755,36 @@ suite('Polymer.dom accessors', function() {
assert.equal(Polymer.dom(child).previousElementSibling, before, 'previousElementSibling incorrect'); assert.equal(Polymer.dom(child).previousElementSibling, before, 'previousElementSibling incorrect');
}); });
test('Polymer.dom node accessors (empty logical tree)', function() {
var element = document.createElement('x-simple');
assert.equal(Polymer.dom(element).parentNode, null, 'parentNode incorrect');
assert.equal(Polymer.dom(element).firstChild, null, 'firstChild incorrect');
assert.equal(Polymer.dom(element).lastChild, null, 'lastChild incorrect');
assert.equal(Polymer.dom(element).nextSibling, null, 'nextSibling incorrect');
assert.equal(Polymer.dom(element).previousSibling, null, 'previousSibling incorrect');
assert.equal(Polymer.dom(element).firstElementChild, null, 'firstElementChild incorrect');
assert.equal(Polymer.dom(element).lastElementChild, null, 'lastElementChild incorrect');
assert.equal(Polymer.dom(element).nextElementSibling, null, 'nextElementSibling incorrect');
assert.equal(Polymer.dom(element).previousElementSibling, null, 'previousElementSibling incorrect');
});
test('Polymer.dom node accessors (unmanaged logical tree)', function() {
var element = document.createElement('div');
var child1 = document.createElement('div');
var child2 = document.createElement('div');
element.appendChild(child1);
element.appendChild(child2);
assert.equal(Polymer.dom(element).parentNode, null, 'parentNode incorrect');
assert.equal(Polymer.dom(element).firstChild, child1, 'firstChild incorrect');
assert.equal(Polymer.dom(element).lastChild, child2, 'lastChild incorrect');
assert.equal(Polymer.dom(element).nextSibling, null, 'nextSibling incorrect');
assert.equal(Polymer.dom(element).previousSibling, null, 'previousSibling incorrect');
assert.equal(Polymer.dom(element).firstElementChild, child1, 'firstElementChild incorrect');
assert.equal(Polymer.dom(element).lastElementChild, child2, 'lastElementChild incorrect');
assert.equal(Polymer.dom(element).nextElementSibling, null, 'nextElementSibling incorrect');
assert.equal(Polymer.dom(element).previousElementSibling, null, 'previousElementSibling incorrect');
});
test('Polymer.dom textContent', function() { test('Polymer.dom textContent', function() {
var testElement = document.createElement('x-project'); var testElement = document.createElement('x-project');
Polymer.dom(testElement).textContent = 'Hello World'; Polymer.dom(testElement).textContent = 'Hello World';