Diff
Copied: branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted-expected.txt (from rev 121003, trunk/LayoutTests/fast/forms/label/labels-owner-node-adopted-expected.txt) (0 => 122248)
--- branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted-expected.txt (rev 0)
+++ branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted-expected.txt 2012-07-10 19:36:48 UTC (rev 122248)
@@ -0,0 +1,13 @@
+This tests moving a node with labels property from one document to another. The labels node list should be updated when labels are modified in the new document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+The input element initially have two label elements #label1 and #label2.
+PASS labels = input.labels; labels.length is 2
+PASS label0 = labels[0]; label1 = labels[1]; iframe.contentDocument.body.appendChild(form); labels.length; label1.parentNode.removeChild(label1); labels.length is 1
+PASS labels[0] is label0
+PASS label0.parentNode.appendChild(label1); labels.length is 2
+PASS labels[0] is label0
+PASS labels[1] is label1
+
Copied: branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted.html (from rev 121003, trunk/LayoutTests/fast/forms/label/labels-owner-node-adopted.html) (0 => 122248)
--- branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted.html (rev 0)
+++ branches/chromium/1180/LayoutTests/fast/forms/label/labels-owner-node-adopted.html 2012-07-10 19:36:48 UTC (rev 122248)
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<body>
+<form>
+<label id="label1" for=""
+<label id="label2" for=""
+<input id="input" type="text">
+</form>
+<script src=""
+<script>
+
+var form = document.querySelector('form');
+var input = document.querySelector('input');
+
+var iframe = document.createElement('iframe');
+document.body.appendChild(iframe);
+var labels, label0, label1;
+
+description("This tests moving a node with labels property from one document to another.\n"
+ + "The labels node list should be updated when labels are modified in the new document.")
+
+debug('The input element initially have two label elements #label1 and #label2.');
+shouldBe("labels = input.labels; labels.length", "2");
+shouldBe("label0 = labels[0]; label1 = labels[1]; iframe.contentDocument.body.appendChild(form); labels.length; label1.parentNode.removeChild(label1); labels.length", "1");
+shouldBe("labels[0]", "label0");
+shouldBe("label0.parentNode.appendChild(label1); labels.length", "2");
+shouldBe("labels[0]", "label0");
+shouldBe("labels[1]", "label1");
+
+form.style.display = 'none';
+
+var successfullyParsed = true;
+
+</script>
+</body>
+</html>
Modified: branches/chromium/1180/Source/WebCore/bindings/js/JSNodeListCustom.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/bindings/js/JSNodeListCustom.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/bindings/js/JSNodeListCustom.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -43,7 +43,7 @@
return false;
if (!jsNodeList->impl()->isDynamicNodeList())
return false;
- return visitor.containsOpaqueRoot(root(static_cast<DynamicNodeList*>(jsNodeList->impl())->node()));
+ return visitor.containsOpaqueRoot(root(static_cast<DynamicNodeList*>(jsNodeList->impl())->ownerNode()));
}
bool JSNodeList::canGetItemsForName(ExecState*, NodeList* impl, PropertyName propertyName)
Modified: branches/chromium/1180/Source/WebCore/dom/ChildNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/ChildNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/ChildNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -34,7 +34,7 @@
ChildNodeList::~ChildNodeList()
{
- node()->removeCachedChildNodeList();
+ ownerNode()->removeCachedChildNodeList();
}
unsigned ChildNodeList::length() const
@@ -43,7 +43,7 @@
return m_caches.cachedLength;
unsigned len = 0;
- for (Node* n = node()->firstChild(); n; n = n->nextSibling())
+ for (Node* n = rootNode()->firstChild(); n; n = n->nextSibling())
len++;
m_caches.cachedLength = len;
@@ -55,7 +55,7 @@
Node* ChildNodeList::item(unsigned index) const
{
unsigned int pos = 0;
- Node* n = node()->firstChild();
+ Node* n = rootNode()->firstChild();
if (m_caches.isItemCacheValid) {
if (index == m_caches.lastItemOffset)
@@ -76,7 +76,7 @@
int diff = index - pos;
unsigned dist = abs(diff);
if (dist > m_caches.cachedLength - 1 - index) {
- n = node()->lastChild();
+ n = rootNode()->lastChild();
pos = m_caches.cachedLength - 1;
}
}
@@ -108,7 +108,7 @@
// Note: Due to the overrides of the length and item functions above,
// this function will be called only by DynamicNodeList::itemWithName,
// for an element that was located with getElementById.
- return testNode->parentNode() == node();
+ return testNode->parentNode() == rootNode();
}
} // namespace WebCore
Modified: branches/chromium/1180/Source/WebCore/dom/ClassNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/ClassNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/ClassNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -38,14 +38,14 @@
ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames)
: DynamicSubtreeNodeList(rootNode)
- , m_classNames(classNames, node()->document()->inQuirksMode())
+ , m_classNames(classNames, document()->inQuirksMode())
, m_originalClassNames(classNames)
{
}
ClassNodeList::~ClassNodeList()
{
- node()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames);
+ ownerNode()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames);
}
bool ClassNodeList::nodeMatches(Element* testNode) const
Modified: branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -38,7 +38,7 @@
return m_caches.cachedLength;
unsigned length = 0;
- Node* rootNode = node();
+ Node* rootNode = this->rootNode();
for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode))
length += n->isElementNode() && nodeMatches(static_cast<Element*>(n));
@@ -52,7 +52,7 @@
Node* DynamicSubtreeNodeList::itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
{
ASSERT(remainingOffset >= 0);
- Node* rootNode = node();
+ Node* rootNode = this->rootNode();
for (Node* n = start; n; n = n->traverseNextNode(rootNode)) {
if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
if (!remainingOffset) {
@@ -71,7 +71,7 @@
Node* DynamicSubtreeNodeList::itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
{
ASSERT(remainingOffset < 0);
- Node* rootNode = node();
+ Node* rootNode = this->rootNode();
for (Node* n = start; n; n = n->traversePreviousNode(rootNode)) {
if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
if (!remainingOffset) {
@@ -90,7 +90,7 @@
Node* DynamicSubtreeNodeList::item(unsigned offset) const
{
int remainingOffset = offset;
- Node* start = node()->firstChild();
+ Node* start = rootNode()->firstChild();
if (m_caches.isItemCacheValid) {
if (offset == m_caches.lastItemOffset)
return m_caches.lastItem;
@@ -107,7 +107,7 @@
Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const
{
- Node* rootNode = node();
+ Node* rootNode = this->rootNode();
if (rootNode->inDocument()) {
Element* element = rootNode->treeScope()->getElementById(elementId);
Modified: branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.h (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.h 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/DynamicNodeList.h 2012-07-10 19:36:48 UTC (rev 122248)
@@ -53,8 +53,8 @@
AlwaysInvalidate,
DoNotInvalidateOnAttributeChange,
};
- DynamicNodeList(PassRefPtr<Node> node, RootType rootType, InvalidationType invalidationType)
- : m_node(node)
+ DynamicNodeList(PassRefPtr<Node> ownerNode, RootType rootType, InvalidationType invalidationType)
+ : m_ownerNode(ownerNode)
, m_caches(rootType, invalidationType)
{ }
virtual ~DynamicNodeList() { }
@@ -65,19 +65,19 @@
virtual Node* itemWithName(const AtomicString&) const;
// Other methods (not part of DOM)
- Node* node() const
- {
- if (m_caches.rootedAtDocument && m_node->inDocument())
- return m_node->document();
- return m_node.get();
- }
- Document* document() { return m_node->document(); }
-
+ Node* ownerNode() const { return m_ownerNode.get(); }
+ bool isRootedAtDocument() const { return m_caches.rootedAtDocument; }
bool shouldInvalidateOnAttributeChange() const { return m_caches.shouldInvalidateOnAttributeChange; }
-
void invalidateCache() { m_caches.reset(); }
protected:
+ Node* rootNode() const
+ {
+ if (m_caches.rootedAtDocument && m_ownerNode->inDocument())
+ return m_ownerNode->document();
+ return m_ownerNode.get();
+ }
+ Document* document() const { return m_ownerNode->document(); }
virtual bool nodeMatches(Element*) const = 0;
struct Caches {
@@ -107,7 +107,7 @@
unsigned shouldInvalidateOnAttributeChange : 1;
};
- RefPtr<Node> m_node;
+ RefPtr<Node> m_ownerNode;
mutable Caches m_caches;
private:
Modified: branches/chromium/1180/Source/WebCore/dom/NameNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/NameNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/NameNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -40,7 +40,7 @@
NameNodeList::~NameNodeList()
{
- m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name);
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name);
}
bool NameNodeList::nodeMatches(Element* testNode) const
Modified: branches/chromium/1180/Source/WebCore/dom/NodeRareData.h (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/NodeRareData.h 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/NodeRareData.h 2012-07-10 19:36:48 UTC (rev 122248)
@@ -119,6 +119,35 @@
return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagNodeListCacheNS.isEmpty();
}
+ void adoptTreeScope(TreeScope* oldTreeScope, TreeScope* newTreeScope, Document* oldDocument, Document* newDocument)
+ {
+ invalidateCaches();
+
+ if (oldDocument != newDocument) {
+ NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+ for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
+ DynamicSubtreeNodeList* list = it->second;
+ if (list->isRootedAtDocument()) {
+ oldDocument->unregisterDynamicSubtreeNodeList(list);
+ newDocument->registerDynamicSubtreeNodeList(list);
+ }
+ }
+
+ NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+ for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
+ DynamicSubtreeNodeList* list = it->second;
+ if (list->isRootedAtDocument()) {
+ oldDocument->unregisterDynamicSubtreeNodeList(list);
+ newDocument->registerDynamicSubtreeNodeList(list);
+ }
+ }
+ }
+
+ if (oldTreeScope)
+ oldTreeScope->removeNodeListCache();
+ newTreeScope->addNodeListCache();
+ }
+
private:
NodeListsNodeData() { }
Modified: branches/chromium/1180/Source/WebCore/dom/TagNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/TagNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/TagNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -41,9 +41,9 @@
TagNodeList::~TagNodeList()
{
if (m_namespaceURI == starAtom)
- m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName);
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName);
else
- m_node->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
+ ownerNode()->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
}
bool TagNodeList::nodeMatches(Element* testNode) const
Modified: branches/chromium/1180/Source/WebCore/dom/TreeScopeAdopter.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/dom/TreeScopeAdopter.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/dom/TreeScopeAdopter.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -53,12 +53,8 @@
for (Node* node = root; node; node = node->traverseNextNode(root)) {
NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
- if (rareData && rareData->nodeLists()) {
- rareData->nodeLists()->invalidateCaches();
- if (m_oldScope)
- m_oldScope->removeNodeListCache();
- m_newScope->addNodeListCache();
- }
+ if (rareData && rareData->nodeLists())
+ rareData->nodeLists()->adoptTreeScope(m_oldScope, m_newScope, oldDocument, newDocument);
if (willMoveToNewDocument)
moveNodeToNewDocument(node, oldDocument, newDocument);
Modified: branches/chromium/1180/Source/WebCore/html/LabelsNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/html/LabelsNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/html/LabelsNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -41,13 +41,13 @@
LabelsNodeList::~LabelsNodeList()
{
- m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
document()->unregisterDynamicSubtreeNodeList(this);
}
bool LabelsNodeList::nodeMatches(Element* testNode) const
{
- return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_node;
+ return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == ownerNode();
}
} // namespace WebCore
Modified: branches/chromium/1180/Source/WebCore/html/RadioNodeList.cpp (122247 => 122248)
--- branches/chromium/1180/Source/WebCore/html/RadioNodeList.cpp 2012-07-10 19:21:19 UTC (rev 122247)
+++ branches/chromium/1180/Source/WebCore/html/RadioNodeList.cpp 2012-07-10 19:36:48 UTC (rev 122248)
@@ -46,7 +46,7 @@
RadioNodeList::~RadioNodeList()
{
- m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
+ ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
document()->unregisterDynamicSubtreeNodeList(this);
}
@@ -86,13 +86,13 @@
bool RadioNodeList::checkElementMatchesRadioNodeListFilter(Element* testElement) const
{
ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement());
- if (m_node->hasTagName(formTag)) {
+ if (ownerNode()->hasTagName(formTag)) {
HTMLFormElement* formElement = 0;
if (testElement->hasTagName(objectTag))
formElement = static_cast<HTMLObjectElement*>(testElement)->form();
else
formElement = static_cast<HTMLFormControlElement*>(testElement)->form();
- if (!formElement || formElement != m_node)
+ if (!formElement || formElement != ownerNode())
return false;
}