Changeset 121003 in webkit


Ignore:
Timestamp:
Jun 21, 2012 10:33:58 PM (12 years ago)
Author:
rniwa@webkit.org
Message:

Source/WebCore: LabelsNodeList isn't updated properly after its owner node is adopted into a new document
https://bugs.webkit.org/show_bug.cgi?id=89730

Reviewed by Darin Adler.

When a node is adopted, node lists that are invalidated at document level need to be unregistered
from old document and registered to new document so that DOM mutations in new document will invalidate
caches in the node lists. Done that in NodeListsNodeData::adoptTreeScope, which was extracted from
TreeScopeAdopter::moveTreeToNewScope.

Also renamed DynamicNodeList::node() and m_node to rootNode() and m_ownerNode to better express
their semantics and added ownerNode() to make m_ownerNode private to DynamicNodeList.

Test: fast/forms/label/labels-owner-node-adopted.html

  • bindings/js/JSNodeListCustom.cpp:

(WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):

  • dom/ChildNodeList.cpp:

(WebCore::ChildNodeList::~ChildNodeList):
(WebCore::ChildNodeList::length):
(WebCore::ChildNodeList::item):
(WebCore::ChildNodeList::nodeMatches):

  • dom/ClassNodeList.cpp:

(WebCore::ClassNodeList::ClassNodeList):
(WebCore::ClassNodeList::~ClassNodeList):

  • dom/DynamicNodeList.cpp:

(WebCore::DynamicSubtreeNodeList::length):
(WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::item):
(WebCore::DynamicNodeList::itemWithName):

  • dom/DynamicNodeList.h:

(WebCore::DynamicNodeList::DynamicNodeList):
(WebCore::DynamicNodeList::ownerNode):
(WebCore::DynamicNodeList::rootedAtDocument):
(WebCore::DynamicNodeList::shouldInvalidateOnAttributeChange):
(WebCore::DynamicNodeList::rootNode):
(WebCore::DynamicNodeList::document):
(DynamicNodeList):

  • dom/NameNodeList.cpp:

(WebCore::NameNodeList::~NameNodeList):

  • dom/NodeRareData.h:

(WebCore::NodeListsNodeData::adoptTreeScope):
(NodeListsNodeData):

  • dom/TagNodeList.cpp:

(WebCore::TagNodeList::~TagNodeList):

  • dom/TreeScopeAdopter.cpp:

(WebCore::TreeScopeAdopter::moveTreeToNewScope):

  • html/LabelsNodeList.cpp:

(WebCore::LabelsNodeList::~LabelsNodeList):
(WebCore::LabelsNodeList::nodeMatches):

  • html/RadioNodeList.cpp:

(WebCore::RadioNodeList::~RadioNodeList):
(WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):

LayoutTests: LabelsNostList isn't updated properly after its owner node is adopted into a new document
https://bugs.webkit.org/show_bug.cgi?id=89730

Reviewed by Darin Adler.

  • fast/forms/label/labels-owner-node-adopted-expected.txt: Added.
  • fast/forms/label/labels-owner-node-adopted.html: Added.
Location:
trunk
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r121001 r121003  
     12012-06-21  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        LabelsNostList isn't updated properly after its owner node is adopted into a new document
     4        https://bugs.webkit.org/show_bug.cgi?id=89730
     5
     6        Reviewed by Darin Adler.
     7
     8        * fast/forms/label/labels-owner-node-adopted-expected.txt: Added.
     9        * fast/forms/label/labels-owner-node-adopted.html: Added.
     10
    1112012-06-21  Abhishek Arya  <inferno@chromium.org>
    212
  • trunk/Source/WebCore/ChangeLog

    r121002 r121003  
     12012-06-21  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        LabelsNodeList isn't updated properly after its owner node is adopted into a new document
     4        https://bugs.webkit.org/show_bug.cgi?id=89730
     5
     6        Reviewed by Darin Adler.
     7
     8        When a node is adopted, node lists that are invalidated at document level need to be unregistered
     9        from old document and registered to new document so that DOM mutations in new document will invalidate
     10        caches in the node lists. Done that in NodeListsNodeData::adoptTreeScope, which was extracted from
     11        TreeScopeAdopter::moveTreeToNewScope.
     12
     13        Also renamed DynamicNodeList::node() and m_node to rootNode() and m_ownerNode to better express
     14        their semantics and added ownerNode() to make m_ownerNode private to DynamicNodeList.
     15
     16        Test: fast/forms/label/labels-owner-node-adopted.html
     17
     18        * bindings/js/JSNodeListCustom.cpp:
     19        (WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):
     20        * dom/ChildNodeList.cpp:
     21        (WebCore::ChildNodeList::~ChildNodeList):
     22        (WebCore::ChildNodeList::length):
     23        (WebCore::ChildNodeList::item):
     24        (WebCore::ChildNodeList::nodeMatches):
     25        * dom/ClassNodeList.cpp:
     26        (WebCore::ClassNodeList::ClassNodeList):
     27        (WebCore::ClassNodeList::~ClassNodeList):
     28        * dom/DynamicNodeList.cpp:
     29        (WebCore::DynamicSubtreeNodeList::length):
     30        (WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
     31        (WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
     32        (WebCore::DynamicSubtreeNodeList::item):
     33        (WebCore::DynamicNodeList::itemWithName):
     34        * dom/DynamicNodeList.h:
     35        (WebCore::DynamicNodeList::DynamicNodeList):
     36        (WebCore::DynamicNodeList::ownerNode):
     37        (WebCore::DynamicNodeList::rootedAtDocument):
     38        (WebCore::DynamicNodeList::shouldInvalidateOnAttributeChange):
     39        (WebCore::DynamicNodeList::rootNode):
     40        (WebCore::DynamicNodeList::document):
     41        (DynamicNodeList):
     42        * dom/NameNodeList.cpp:
     43        (WebCore::NameNodeList::~NameNodeList):
     44        * dom/NodeRareData.h:
     45        (WebCore::NodeListsNodeData::adoptTreeScope):
     46        (NodeListsNodeData):
     47        * dom/TagNodeList.cpp:
     48        (WebCore::TagNodeList::~TagNodeList):
     49        * dom/TreeScopeAdopter.cpp:
     50        (WebCore::TreeScopeAdopter::moveTreeToNewScope):
     51        * html/LabelsNodeList.cpp:
     52        (WebCore::LabelsNodeList::~LabelsNodeList):
     53        (WebCore::LabelsNodeList::nodeMatches):
     54        * html/RadioNodeList.cpp:
     55        (WebCore::RadioNodeList::~RadioNodeList):
     56        (WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):
     57
    1582012-06-21  Alexei Filippov  <alexeif@chromium.org>
    259
  • trunk/Source/WebCore/bindings/js/JSNodeListCustom.cpp

    r116828 r121003  
    4444    if (!jsNodeList->impl()->isDynamicNodeList())
    4545        return false;
    46     return visitor.containsOpaqueRoot(root(static_cast<DynamicNodeList*>(jsNodeList->impl())->node()));
     46    return visitor.containsOpaqueRoot(root(static_cast<DynamicNodeList*>(jsNodeList->impl())->ownerNode()));
    4747}
    4848
  • trunk/Source/WebCore/dom/ChildNodeList.cpp

    r120979 r121003  
    3535ChildNodeList::~ChildNodeList()
    3636{
    37     node()->removeCachedChildNodeList();
     37    ownerNode()->removeCachedChildNodeList();
    3838}
    3939
     
    4444
    4545    unsigned len = 0;
    46     for (Node* n = node()->firstChild(); n; n = n->nextSibling())
     46    for (Node* n = rootNode()->firstChild(); n; n = n->nextSibling())
    4747        len++;
    4848
     
    5656{
    5757    unsigned int pos = 0;
    58     Node* n = node()->firstChild();
     58    Node* n = rootNode()->firstChild();
    5959
    6060    if (m_caches.isItemCacheValid) {
     
    7777        unsigned dist = abs(diff);
    7878        if (dist > m_caches.cachedLength - 1 - index) {
    79             n = node()->lastChild();
     79            n = rootNode()->lastChild();
    8080            pos = m_caches.cachedLength - 1;
    8181        }
     
    109109    // this function will be called only by DynamicNodeList::itemWithName,
    110110    // for an element that was located with getElementById.
    111     return testNode->parentNode() == node();
     111    return testNode->parentNode() == rootNode();
    112112}
    113113
  • trunk/Source/WebCore/dom/ClassNodeList.cpp

    r120979 r121003  
    3939ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames)
    4040    : DynamicSubtreeNodeList(rootNode)
    41     , m_classNames(classNames, node()->document()->inQuirksMode())
     41    , m_classNames(classNames, document()->inQuirksMode())
    4242    , m_originalClassNames(classNames)
    4343{
     
    4646ClassNodeList::~ClassNodeList()
    4747{
    48     node()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames);
     48    ownerNode()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames);
    4949}
    5050
  • trunk/Source/WebCore/dom/DynamicNodeList.cpp

    r120979 r121003  
    3939
    4040    unsigned length = 0;
    41     Node* rootNode = node();
     41    Node* rootNode = this->rootNode();
    4242
    4343    for (Node* n = rootNode->firstChild(); n; n = n->traverseNextNode(rootNode))
     
    5353{
    5454    ASSERT(remainingOffset >= 0);
    55     Node* rootNode = node();
     55    Node* rootNode = this->rootNode();
    5656    for (Node* n = start; n; n = n->traverseNextNode(rootNode)) {
    5757        if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
     
    7272{
    7373    ASSERT(remainingOffset < 0);
    74     Node* rootNode = node();
     74    Node* rootNode = this->rootNode();
    7575    for (Node* n = start; n; n = n->traversePreviousNode(rootNode)) {
    7676        if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
     
    9191{
    9292    int remainingOffset = offset;
    93     Node* start = node()->firstChild();
     93    Node* start = rootNode()->firstChild();
    9494    if (m_caches.isItemCacheValid) {
    9595        if (offset == m_caches.lastItemOffset)
     
    108108Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const
    109109{
    110     Node* rootNode = node();
     110    Node* rootNode = this->rootNode();
    111111
    112112    if (rootNode->inDocument()) {
  • trunk/Source/WebCore/dom/DynamicNodeList.h

    r120979 r121003  
    5454        DoNotInvalidateOnAttributeChange,
    5555    };
    56     DynamicNodeList(PassRefPtr<Node> node, RootType rootType, InvalidationType invalidationType)
    57         : m_node(node)
     56    DynamicNodeList(PassRefPtr<Node> ownerNode, RootType rootType, InvalidationType invalidationType)
     57        : m_ownerNode(ownerNode)
    5858        , m_caches(rootType, invalidationType)
    5959    { }
     
    6666
    6767    // Other methods (not part of DOM)
    68     Node* node() const
    69     {
    70         if (m_caches.rootedAtDocument && m_node->inDocument())
    71             return m_node->document();
    72         return m_node.get();
    73     }
    74     Document* document() { return m_node->document(); }
    75 
     68    Node* ownerNode() const { return m_ownerNode.get(); }
     69    bool isRootedAtDocument() const { return m_caches.rootedAtDocument; }
    7670    bool shouldInvalidateOnAttributeChange() const { return m_caches.shouldInvalidateOnAttributeChange; }
    77 
    7871    void invalidateCache() { m_caches.reset(); }
    7972
    8073protected:
     74    Node* rootNode() const
     75    {
     76        if (m_caches.rootedAtDocument && m_ownerNode->inDocument())
     77            return m_ownerNode->document();
     78        return m_ownerNode.get();
     79    }
     80    Document* document() const { return m_ownerNode->document(); }
    8181    virtual bool nodeMatches(Element*) const = 0;
    8282
     
    108108    };
    109109
    110     RefPtr<Node> m_node;
     110    RefPtr<Node> m_ownerNode;
    111111    mutable Caches m_caches;
    112112
  • trunk/Source/WebCore/dom/NameNodeList.cpp

    r120979 r121003  
    4141NameNodeList::~NameNodeList()
    4242{
    43     m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name);
     43    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name);
    4444}
    4545
  • trunk/Source/WebCore/dom/NodeRareData.h

    r120983 r121003  
    120120    }
    121121
     122    void adoptTreeScope(TreeScope* oldTreeScope, TreeScope* newTreeScope, Document* oldDocument, Document* newDocument)
     123    {
     124        invalidateCaches();
     125
     126        if (oldDocument != newDocument) {
     127            NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
     128            for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
     129                DynamicSubtreeNodeList* list = it->second;
     130                if (list->isRootedAtDocument()) {
     131                    oldDocument->unregisterDynamicSubtreeNodeList(list);
     132                    newDocument->registerDynamicSubtreeNodeList(list);
     133                }
     134            }
     135
     136            NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
     137            for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
     138                DynamicSubtreeNodeList* list = it->second;
     139                if (list->isRootedAtDocument()) {
     140                    oldDocument->unregisterDynamicSubtreeNodeList(list);
     141                    newDocument->registerDynamicSubtreeNodeList(list);
     142                }
     143            }
     144        }
     145
     146        if (oldTreeScope)
     147            oldTreeScope->removeNodeListCache();
     148        newTreeScope->addNodeListCache();
     149    }
     150
    122151private:
    123152    NodeListsNodeData() { }
  • trunk/Source/WebCore/dom/TagNodeList.cpp

    r120979 r121003  
    4242{
    4343    if (m_namespaceURI == starAtom)
    44         m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName);
     44        ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName);
    4545    else
    46         m_node->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
     46        ownerNode()->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
    4747}
    4848
  • trunk/Source/WebCore/dom/TreeScopeAdopter.cpp

    r117796 r121003  
    5454    for (Node* node = root; node; node = node->traverseNextNode(root)) {
    5555        NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
    56         if (rareData && rareData->nodeLists()) {
    57             rareData->nodeLists()->invalidateCaches();
    58             if (m_oldScope)
    59                 m_oldScope->removeNodeListCache();
    60             m_newScope->addNodeListCache();
    61         }
     56        if (rareData && rareData->nodeLists())
     57            rareData->nodeLists()->adoptTreeScope(m_oldScope, m_newScope, oldDocument, newDocument);
    6258
    6359        if (willMoveToNewDocument)
  • trunk/Source/WebCore/html/LabelsNodeList.cpp

    r120979 r121003  
    4242LabelsNodeList::~LabelsNodeList()
    4343{
    44     m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
     44    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
    4545    document()->unregisterDynamicSubtreeNodeList(this);
    4646}
     
    4848bool LabelsNodeList::nodeMatches(Element* testNode) const
    4949{
    50     return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_node;
     50    return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == ownerNode();
    5151}
    5252
  • trunk/Source/WebCore/html/RadioNodeList.cpp

    r120979 r121003  
    4747RadioNodeList::~RadioNodeList()
    4848{
    49     m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
     49    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
    5050    document()->unregisterDynamicSubtreeNodeList(this);
    5151}
     
    8787{
    8888    ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement());
    89     if (m_node->hasTagName(formTag)) {
     89    if (ownerNode()->hasTagName(formTag)) {
    9090        HTMLFormElement* formElement = 0;
    9191        if (testElement->hasTagName(objectTag))
     
    9393        else
    9494            formElement = static_cast<HTMLFormControlElement*>(testElement)->form();
    95         if (!formElement || formElement != m_node)
     95        if (!formElement || formElement != ownerNode())
    9696            return false;
    9797    }
Note: See TracChangeset for help on using the changeset viewer.