Changeset 102834 in webkit


Ignore:
Timestamp:
Dec 14, 2011 3:18:26 PM (12 years ago)
Author:
rniwa@webkit.org
Message:

NodeChildList shouldn't be in NodeListNodeData
https://bugs.webkit.org/show_bug.cgi?id=73969

Source/WebCore:

Reviewed by Sam Weinig.

Move NodeChildList out of NodeListNodeData to separate it from the other node lists in order to
resolve the bug 73853. Unlike other DynamicNodeList, we don't need to invalidate NodeChildList
on ancestors when children change. Moving ChildNodeList out of NodeListNodeData makes this difference
apparent and makes DynamicNodeList::Caches in NodeListNodeData always held by a DynamicSubtreeNodeList,
eliminating the need for hasOwnCaches() checks in various places.

Also renamed the existing DynamicNodeList to DynamicSubtreeNodeList and re-introduced DynamicNodeList
from which DynamicSubtreeNodeList and ChildNodeList both inherit to share the code for itemWithName.

In addition, renamed registerDynamicNodeList and unregisterDynamicNodeList, which updates a counter for
TreeScope::hasNodeListCaches, to registerDynamicSubtreeNodeList and unregisterDynamicSubtreeNodeList
respectively. They are no longer called by ChildNodeList in order to avoid walking up the DOM tree
inside invalidateNodeListsCacheAfterAttributeChanged and invalidateNodeListsCacheAfterChildrenChanged.

Test: fast/dom/childnode-item-after-itemname.html

  • bindings/js/JSNodeListCustom.cpp:

(WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):

  • dom/ChildNodeList.cpp:

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

  • dom/ChildNodeList.h:
  • dom/ClassNodeList.cpp:

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

  • dom/ClassNodeList.h:
  • dom/ContainerNode.cpp:

(WebCore::ContainerNode::childrenChanged):

  • dom/DynamicNodeList.cpp:

(WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
(WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList):
(WebCore::DynamicSubtreeNodeList::length):
(WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::item):
(WebCore::DynamicNodeList::itemWithName):
(WebCore::DynamicSubtreeNodeList::isDynamicNodeList):
(WebCore::DynamicSubtreeNodeList::invalidateCache):
(WebCore::DynamicSubtreeNodeList::Caches::Caches):
(WebCore::DynamicSubtreeNodeList::Caches::create):
(WebCore::DynamicSubtreeNodeList::Caches::reset):

  • dom/DynamicNodeList.h:

(WebCore::DynamicNodeList::DynamicNodeList):
(WebCore::DynamicNodeList::~DynamicNodeList):
(WebCore::DynamicNodeList::node):
(WebCore::DynamicSubtreeNodeList::rootNode):

  • dom/NameNodeList.cpp:

(WebCore::NameNodeList::NameNodeList):
(WebCore::NameNodeList::~NameNodeList):

  • dom/NameNodeList.h:
  • dom/Node.cpp:

(WebCore::Node::childNodes):
(WebCore::Node::registerDynamicSubtreeNodeList):
(WebCore::Node::unregisterDynamicSubtreeNodeList):
(WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
(WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
(WebCore::Node::removeCachedClassNodeList):
(WebCore::Node::removeCachedNameNodeList):
(WebCore::Node::removeCachedTagNodeList):
(WebCore::Node::removeCachedLabelsNodeList):
(WebCore::NodeListsNodeData::invalidateCaches):
(WebCore::NodeListsNodeData::isEmpty):
(WebCore::NodeRareData::clearChildNodeListCache):

  • dom/Node.h:
  • dom/NodeRareData.h:

(WebCore::NodeRareData::nodeLists):
(WebCore::NodeRareData::ensureChildNodeListCache):

  • dom/TagNodeList.cpp:

(WebCore::TagNodeList::TagNodeList):
(WebCore::TagNodeList::~TagNodeList):

  • dom/TagNodeList.h:
  • html/LabelsNodeList.cpp:

(WebCore::LabelsNodeList::LabelsNodeList):

  • html/LabelsNodeList.h:

LayoutTests:

Added a regression test for ChildNodeList; it catches a bug caught in the review process.

  • fast/dom/childnode-item-after-itemname-expected.txt: Added.
  • fast/dom/childnode-item-after-itemname.html: Added.
Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r102830 r102834  
     12011-12-14  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        NodeChildList shouldn't be in NodeListNodeData
     4        https://bugs.webkit.org/show_bug.cgi?id=73969
     5
     6        Added a regression test for ChildNodeList; it catches a bug caught in the review process.
     7
     8        * fast/dom/childnode-item-after-itemname-expected.txt: Added.
     9        * fast/dom/childnode-item-after-itemname.html: Added.
     10
    1112011-12-14  Ethan Malasky  <emalasky@adobe.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r102833 r102834  
     12011-12-14  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        NodeChildList shouldn't be in NodeListNodeData
     4        https://bugs.webkit.org/show_bug.cgi?id=73969
     5
     6        Reviewed by Sam Weinig.
     7
     8        Move NodeChildList out of NodeListNodeData to separate it from the other node lists in order to
     9        resolve the bug 73853. Unlike other DynamicNodeList, we don't need to invalidate NodeChildList
     10        on ancestors when children change. Moving ChildNodeList out of NodeListNodeData makes this difference
     11        apparent and makes DynamicNodeList::Caches in NodeListNodeData always held by a DynamicSubtreeNodeList,
     12        eliminating the need for hasOwnCaches() checks in various places.
     13
     14        Also renamed the existing DynamicNodeList to DynamicSubtreeNodeList and re-introduced DynamicNodeList
     15        from which DynamicSubtreeNodeList and ChildNodeList both inherit to share the code for itemWithName.
     16
     17        In addition, renamed registerDynamicNodeList and unregisterDynamicNodeList, which updates a counter for
     18        TreeScope::hasNodeListCaches, to registerDynamicSubtreeNodeList and unregisterDynamicSubtreeNodeList
     19        respectively. They are no longer called by ChildNodeList in order to avoid walking up the DOM tree
     20        inside invalidateNodeListsCacheAfterAttributeChanged and invalidateNodeListsCacheAfterChildrenChanged.
     21
     22        Test: fast/dom/childnode-item-after-itemname.html
     23
     24        * bindings/js/JSNodeListCustom.cpp:
     25        (WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):
     26        * dom/ChildNodeList.cpp:
     27        (WebCore::ChildNodeList::ChildNodeList):
     28        (WebCore::ChildNodeList::length):
     29        (WebCore::ChildNodeList::item):
     30        (WebCore::ChildNodeList::nodeMatches):
     31        * dom/ChildNodeList.h:
     32        * dom/ClassNodeList.cpp:
     33        (WebCore::ClassNodeList::ClassNodeList):
     34        (WebCore::ClassNodeList::~ClassNodeList):
     35        * dom/ClassNodeList.h:
     36        * dom/ContainerNode.cpp:
     37        (WebCore::ContainerNode::childrenChanged):
     38        * dom/DynamicNodeList.cpp:
     39        (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
     40        (WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList):
     41        (WebCore::DynamicSubtreeNodeList::length):
     42        (WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
     43        (WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
     44        (WebCore::DynamicSubtreeNodeList::item):
     45        (WebCore::DynamicNodeList::itemWithName):
     46        (WebCore::DynamicSubtreeNodeList::isDynamicNodeList):
     47        (WebCore::DynamicSubtreeNodeList::invalidateCache):
     48        (WebCore::DynamicSubtreeNodeList::Caches::Caches):
     49        (WebCore::DynamicSubtreeNodeList::Caches::create):
     50        (WebCore::DynamicSubtreeNodeList::Caches::reset):
     51        * dom/DynamicNodeList.h:
     52        (WebCore::DynamicNodeList::DynamicNodeList):
     53        (WebCore::DynamicNodeList::~DynamicNodeList):
     54        (WebCore::DynamicNodeList::node):
     55        (WebCore::DynamicSubtreeNodeList::rootNode):
     56        * dom/NameNodeList.cpp:
     57        (WebCore::NameNodeList::NameNodeList):
     58        (WebCore::NameNodeList::~NameNodeList):
     59        * dom/NameNodeList.h:
     60        * dom/Node.cpp:
     61        (WebCore::Node::childNodes):
     62        (WebCore::Node::registerDynamicSubtreeNodeList):
     63        (WebCore::Node::unregisterDynamicSubtreeNodeList):
     64        (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
     65        (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
     66        (WebCore::Node::removeCachedClassNodeList):
     67        (WebCore::Node::removeCachedNameNodeList):
     68        (WebCore::Node::removeCachedTagNodeList):
     69        (WebCore::Node::removeCachedLabelsNodeList):
     70        (WebCore::NodeListsNodeData::invalidateCaches):
     71        (WebCore::NodeListsNodeData::isEmpty):
     72        (WebCore::NodeRareData::clearChildNodeListCache):
     73        * dom/Node.h:
     74        * dom/NodeRareData.h:
     75        (WebCore::NodeRareData::nodeLists):
     76        (WebCore::NodeRareData::ensureChildNodeListCache):
     77        * dom/TagNodeList.cpp:
     78        (WebCore::TagNodeList::TagNodeList):
     79        (WebCore::TagNodeList::~TagNodeList):
     80        * dom/TagNodeList.h:
     81        * html/LabelsNodeList.cpp:
     82        (WebCore::LabelsNodeList::LabelsNodeList):
     83        * html/LabelsNodeList.h:
     84
    1852011-12-14  Ryosuke Niwa  <rniwa@webkit.org>
    286
  • trunk/Source/WebCore/bindings/js/JSNodeListCustom.cpp

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

    r37037 r102834  
    2828namespace WebCore {
    2929
    30 ChildNodeList::ChildNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Caches* info)
    31     : DynamicNodeList(rootNode, info)
     30ChildNodeList::ChildNodeList(PassRefPtr<Node> node, DynamicNodeList::Caches* caches)
     31    : DynamicNodeList(node)
     32    , m_caches(caches)
    3233{
    3334}
     
    3940
    4041    unsigned len = 0;
    41     for (Node* n = m_rootNode->firstChild(); n; n = n->nextSibling())
     42    for (Node* n = node()->firstChild(); n; n = n->nextSibling())
    4243        len++;
    4344
     
    5152{
    5253    unsigned int pos = 0;
    53     Node* n = m_rootNode->firstChild();
     54    Node* n = node()->firstChild();
    5455
    5556    if (m_caches->isItemCacheValid) {
     
    7273        unsigned dist = abs(diff);
    7374        if (dist > m_caches->cachedLength - 1 - index) {
    74             n = m_rootNode->lastChild();
     75            n = node()->lastChild();
    7576            pos = m_caches->cachedLength - 1;
    7677        }
     
    104105    // this function will be called only by DynamicNodeList::itemWithName,
    105106    // for an element that was located with getElementById.
    106     return testNode->parentNode() == m_rootNode;
     107    return testNode->parentNode() == node();
    107108}
    108109
  • trunk/Source/WebCore/dom/ChildNodeList.h

    r37037 r102834  
    4444
    4545        virtual bool nodeMatches(Element*) const;
     46
     47        mutable RefPtr<DynamicNodeList::Caches> m_caches;
    4648    };
    4749
  • trunk/Source/WebCore/dom/ClassNodeList.cpp

    r66247 r102834  
    3737
    3838ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames)
    39     : DynamicNodeList(rootNode)
    40     , m_classNames(classNames, m_rootNode->document()->inQuirksMode())
     39    : DynamicSubtreeNodeList(rootNode)
     40    , m_classNames(classNames, node()->document()->inQuirksMode())
    4141    , m_originalClassNames(classNames)
    4242{
     
    4545ClassNodeList::~ClassNodeList()
    4646{
    47     m_rootNode->removeCachedClassNodeList(this, m_originalClassNames);
     47    rootNode()->removeCachedClassNodeList(this, m_originalClassNames);
    4848}
    4949
  • trunk/Source/WebCore/dom/ClassNodeList.h

    r69437 r102834  
    3737namespace WebCore {
    3838
    39     class ClassNodeList : public DynamicNodeList {
     39    class ClassNodeList : public DynamicSubtreeNodeList {
    4040    public:
    4141        static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames)
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r102431 r102834  
    845845    if (!changedByParser && childCountDelta)
    846846        document()->updateRangesAfterChildrenChanged(this);
    847     if (treeScope()->hasNodeListCaches())
    848         invalidateNodeListsCacheAfterChildrenChanged();
     847    invalidateNodeListsCacheAfterChildrenChanged();
    849848}
    850849
  • trunk/Source/WebCore/dom/DynamicNodeList.cpp

    r85617 r102834  
    2929namespace WebCore {
    3030
    31 DynamicNodeList::DynamicNodeList(PassRefPtr<Node> rootNode)
    32     : m_rootNode(rootNode)
     31DynamicSubtreeNodeList::DynamicSubtreeNodeList(PassRefPtr<Node> node)
     32    : DynamicNodeList(node)
    3333    , m_caches(Caches::create())
    34     , m_ownsCaches(true)
    3534{
    36     m_rootNode->registerDynamicNodeList(this);
    37 }   
    38 
    39 DynamicNodeList::DynamicNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Caches* caches)
    40     : m_rootNode(rootNode)
    41     , m_caches(caches)
    42     , m_ownsCaches(false)
    43 {
    44     m_rootNode->registerDynamicNodeList(this);
    45 }   
    46 
    47 DynamicNodeList::~DynamicNodeList()
    48 {
    49     m_rootNode->unregisterDynamicNodeList(this);
     35    rootNode()->registerDynamicSubtreeNodeList(this);
    5036}
    5137
    52 unsigned DynamicNodeList::length() const
     38DynamicSubtreeNodeList::~DynamicSubtreeNodeList()
     39{
     40    rootNode()->unregisterDynamicSubtreeNodeList(this);
     41}
     42
     43unsigned DynamicSubtreeNodeList::length() const
    5344{
    5445    if (m_caches->isLengthCacheValid)
     
    5748    unsigned length = 0;
    5849
    59     for (Node* n = m_rootNode->firstChild(); n; n = n->traverseNextNode(m_rootNode.get()))
     50    for (Node* n = node()->firstChild(); n; n = n->traverseNextNode(rootNode()))
    6051        length += n->isElementNode() && nodeMatches(static_cast<Element*>(n));
    6152
     
    6657}
    6758
    68 Node* DynamicNodeList::itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
     59Node* DynamicSubtreeNodeList::itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
    6960{
    7061    ASSERT(remainingOffset >= 0);
    71     for (Node* n = start; n; n = n->traverseNextNode(m_rootNode.get())) {
     62    for (Node* n = start; n; n = n->traverseNextNode(rootNode())) {
    7263        if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
    7364            if (!remainingOffset) {
     
    8475}
    8576
    86 Node* DynamicNodeList::itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
     77Node* DynamicSubtreeNodeList::itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const
    8778{
    8879    ASSERT(remainingOffset < 0);
    89     for (Node* n = start; n; n = n->traversePreviousNode(m_rootNode.get())) {
     80    for (Node* n = start; n; n = n->traversePreviousNode(rootNode())) {
    9081        if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
    9182            if (!remainingOffset) {
     
    10293}
    10394
    104 Node* DynamicNodeList::item(unsigned offset) const
     95Node* DynamicSubtreeNodeList::item(unsigned offset) const
    10596{
    10697    int remainingOffset = offset;
    107     Node* start = m_rootNode->firstChild();
     98    Node* start = node()->firstChild();
    10899    if (m_caches->isItemCacheValid) {
    109100        if (offset == m_caches->lastItemOffset)
     
    122113Node* DynamicNodeList::itemWithName(const AtomicString& elementId) const
    123114{
    124     if (m_rootNode->isDocumentNode() || m_rootNode->inDocument()) {
    125         Element* node = m_rootNode->treeScope()->getElementById(elementId);
    126         if (node && nodeMatches(node)) {
    127             for (ContainerNode* p = node->parentNode(); p; p = p->parentNode()) {
    128                 if (p == m_rootNode)
    129                     return node;
    130             }
    131         }
     115    if (node()->isDocumentNode() || node()->inDocument()) {
     116        Element* node = this->node()->treeScope()->getElementById(elementId);
     117        if (node && nodeMatches(node) && node->isDescendantOf(this->node()))
     118            return node;
    132119        if (!node)
    133120            return 0;
     
    146133}
    147134
    148 bool DynamicNodeList::isDynamicNodeList() const
     135bool DynamicSubtreeNodeList::isDynamicNodeList() const
    149136{
    150137    return true;
    151138}
    152139
    153 void DynamicNodeList::invalidateCache()
     140void DynamicSubtreeNodeList::invalidateCache()
    154141{
    155     // This should only be called for node lists that own their own caches.
    156     ASSERT(m_ownsCaches);
    157142    m_caches->reset();
    158143}
    159144
    160 DynamicNodeList::Caches::Caches()
     145DynamicSubtreeNodeList::Caches::Caches()
    161146    : lastItem(0)
    162147    , isLengthCacheValid(false)
     
    165150}
    166151
    167 PassRefPtr<DynamicNodeList::Caches> DynamicNodeList::Caches::create()
     152PassRefPtr<DynamicSubtreeNodeList::Caches> DynamicSubtreeNodeList::Caches::create()
    168153{
    169154    return adoptRef(new Caches());
    170155}
    171156
    172 void DynamicNodeList::Caches::reset()
     157void DynamicSubtreeNodeList::Caches::reset()
    173158{
    174159    lastItem = 0;
  • trunk/Source/WebCore/dom/DynamicNodeList.h

    r84309 r102834  
    3232namespace WebCore {
    3333
    34     class Element;
    35     class Node;
     34class Element;
     35class Node;
    3636
    37     class DynamicNodeList : public NodeList {
    38     public:
    39         struct Caches : RefCounted<Caches> {
    40             static PassRefPtr<Caches> create();
    41             void reset();
     37class DynamicNodeList : public NodeList {
     38public:
     39    struct Caches : RefCounted<Caches> {
     40        static PassRefPtr<Caches> create();
     41        void reset();
     42       
     43        unsigned cachedLength;
     44        Node* lastItem;
     45        unsigned lastItemOffset;
     46        bool isLengthCacheValid : 1;
     47        bool isItemCacheValid : 1;
     48    protected:
     49        Caches();
     50    };
     51    DynamicNodeList(PassRefPtr<Node> node)
     52        : m_node(node)
     53    { }
     54    virtual ~DynamicNodeList() { }
    4255
    43             unsigned cachedLength;
    44             Node* lastItem;
    45             unsigned lastItemOffset;
    46             bool isLengthCacheValid : 1;
    47             bool isItemCacheValid : 1;
    48         protected:
    49             Caches();
    50         };
     56    // DOM methods & attributes for NodeList
     57    virtual unsigned length() const = 0;
     58    virtual Node* item(unsigned index) const = 0;
     59    virtual Node* itemWithName(const AtomicString&) const;
    5160
    52         virtual ~DynamicNodeList();
     61    // Other methods (not part of DOM)
     62    Node* node() const { return m_node.get(); }
    5363
    54         bool hasOwnCaches() const { return m_ownsCaches; }
     64protected:
     65    virtual bool nodeMatches(Element*) const = 0;
     66    RefPtr<Node> m_node;
     67};
    5568
    56         // DOM methods & attributes for NodeList
    57         virtual unsigned length() const;
    58         virtual Node* item(unsigned index) const;
    59         virtual Node* itemWithName(const AtomicString&) const;
     69class DynamicSubtreeNodeList : public DynamicNodeList {
     70public:
     71    virtual ~DynamicSubtreeNodeList();
     72    virtual unsigned length() const OVERRIDE;
     73    virtual Node* item(unsigned index) const OVERRIDE;
     74    void invalidateCache();
     75    Node* rootNode() const { return node(); }
    6076
    61         // Other methods (not part of DOM)
    62         void invalidateCache();
    63         Node* rootNode() const { return m_rootNode.get(); }
     77protected:
     78    DynamicSubtreeNodeList(PassRefPtr<Node> rootNode);
     79    mutable RefPtr<Caches> m_caches;
    6480
    65     protected:
    66         DynamicNodeList(PassRefPtr<Node> rootNode);
    67         DynamicNodeList(PassRefPtr<Node> rootNode, Caches*);
    68 
    69         virtual bool nodeMatches(Element*) const = 0;
    70 
    71         RefPtr<Node> m_rootNode;
    72         mutable RefPtr<Caches> m_caches;
    73         bool m_ownsCaches;
    74 
    75     private:
    76         virtual bool isDynamicNodeList() const;
    77         Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
    78         Node* itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
    79     };
     81private:
     82    virtual bool isDynamicNodeList() const;
     83    Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
     84    Node* itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
     85};
    8086
    8187} // namespace WebCore
  • trunk/Source/WebCore/dom/NameNodeList.cpp

    r94427 r102834  
    3333
    3434NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name)
    35     : DynamicNodeList(rootNode)
     35    : DynamicSubtreeNodeList(rootNode)
    3636    , m_nodeName(name)
    3737{
     
    4040NameNodeList::~NameNodeList()
    4141{
    42     m_rootNode->removeCachedNameNodeList(this, m_nodeName);
     42    rootNode()->removeCachedNameNodeList(this, m_nodeName);
    4343}
    4444
  • trunk/Source/WebCore/dom/NameNodeList.h

    r65077 r102834  
    3232
    3333    // NodeList which lists all Nodes in a Element with a given "name" attribute
    34     class NameNodeList : public DynamicNodeList {
     34    class NameNodeList : public DynamicSubtreeNodeList {
    3535    public:
    3636        static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name)
  • trunk/Source/WebCore/dom/Node.cpp

    r102721 r102834  
    624624PassRefPtr<NodeList> Node::childNodes()
    625625{
    626     NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);
    627     if (!nodeLists->m_childNodeListCaches)
    628         nodeLists->m_childNodeListCaches = DynamicNodeList::Caches::create();
    629     return ChildNodeList::create(this, nodeLists->m_childNodeListCaches.get());
     626    return ChildNodeList::create(this, ensureRareData()->ensureChildNodeListCache());
    630627}
    631628
     
    10051002}
    10061003
    1007 void Node::registerDynamicNodeList(DynamicNodeList* list)
     1004void Node::registerDynamicSubtreeNodeList(DynamicSubtreeNodeList* list)
    10081005{
    10091006    NodeRareData* data = ensureRareData();
     
    10121009        data->nodeLists()->invalidateCaches();
    10131010
    1014     if (list->hasOwnCaches())
    1015         data->ensureNodeLists(this)->m_listsWithCaches.add(list);
    1016 }
    1017 
    1018 void Node::unregisterDynamicNodeList(DynamicNodeList* list)
    1019 {
    1020     ASSERT(rareData());
     1011    data->ensureNodeLists(this)->m_listsWithCaches.add(list);
     1012}
     1013
     1014void Node::unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList* list)
     1015{
     1016    ASSERT(hasRareData());
    10211017    ASSERT(rareData()->nodeLists());
    1022     if (list->hasOwnCaches()) {
     1018    NodeRareData* data = rareData();
     1019    data->nodeLists()->m_listsWithCaches.remove(list);
     1020    removeNodeListCacheIfPossible(this, data);
     1021}
     1022
     1023void Node::invalidateNodeListsCacheAfterAttributeChanged()
     1024{
     1025    if (hasRareData() && isAttributeNode()) {
    10231026        NodeRareData* data = rareData();
    1024         data->nodeLists()->m_listsWithCaches.remove(list);
    1025         removeNodeListCacheIfPossible(this, data);
    1026     }
    1027 }
    1028 
    1029 void Node::invalidateNodeListsCacheAfterAttributeChanged()
    1030 {
     1027        ASSERT(!data->nodeLists());
     1028        data->clearChildNodeListCache();
     1029    }
     1030
     1031    if (!treeScope()->hasNodeListCaches())
     1032        return;
     1033
     1034    for (Node* node = this; node; node = node->parentNode()) {
     1035        ASSERT(this == node || !node->isAttributeNode());
     1036        if (!node->hasRareData())
     1037            continue;
     1038        NodeRareData* data = node->rareData();
     1039        if (!data->nodeLists())
     1040            continue;
     1041
     1042        data->nodeLists()->invalidateCachesThatDependOnAttributes();
     1043        removeNodeListCacheIfPossible(node, data);
     1044    }
     1045}
     1046
     1047void Node::invalidateNodeListsCacheAfterChildrenChanged()
     1048{
     1049    if (hasRareData())
     1050        rareData()->clearChildNodeListCache();
     1051
     1052    if (!treeScope()->hasNodeListCaches())
     1053        return;
    10311054    for (Node* node = this; node; node = node->parentNode()) {
    10321055        if (!node->hasRareData())
     
    10361059            continue;
    10371060
    1038         // For attribute nodes, we need to invalidate childNodes as well.
    1039         if (node->isAttributeNode())
    1040             data->nodeLists()->invalidateCaches();
    1041         else
    1042             data->nodeLists()->invalidateCachesThatDependOnAttributes();
    1043 
    1044         removeNodeListCacheIfPossible(node, data);
    1045     }
    1046 }
    1047 
    1048 void Node::invalidateNodeListsCacheAfterChildrenChanged()
    1049 {
    1050     for (Node* node = this; node; node = node->parentNode()) {
    1051         if (!node->hasRareData())
    1052             continue;
    1053         NodeRareData* data = node->rareData();
    1054         if (!data->nodeLists())
    1055             continue;
    1056 
    10571061        data->nodeLists()->invalidateCaches();
    10581062
     
    10811085    ASSERT(rareData());
    10821086    ASSERT(rareData()->nodeLists());
    1083     ASSERT_UNUSED(list, list->hasOwnCaches());
    10841087
    10851088    NodeListsNodeData* data = rareData()->nodeLists();
     
    10921095    ASSERT(rareData());
    10931096    ASSERT(rareData()->nodeLists());
    1094     ASSERT_UNUSED(list, list->hasOwnCaches());
    10951097
    10961098    NodeListsNodeData* data = rareData()->nodeLists();
     
    11031105    ASSERT(rareData());
    11041106    ASSERT(rareData()->nodeLists());
    1105     ASSERT_UNUSED(list, list->hasOwnCaches());
    11061107
    11071108    NodeListsNodeData* data = rareData()->nodeLists();
     
    11141115    ASSERT(rareData());
    11151116    ASSERT(rareData()->nodeLists());
    1116     ASSERT_UNUSED(list, list->hasOwnCaches());
    11171117
    11181118    NodeListsNodeData* data = rareData()->nodeLists();
     
    11211121}
    11221122
    1123 void Node::removeCachedLabelsNodeList(DynamicNodeList* list)
     1123void Node::removeCachedLabelsNodeList(DynamicSubtreeNodeList* list)
    11241124{
    11251125    ASSERT(rareData());
    11261126    ASSERT(rareData()->nodeLists());
    1127     ASSERT_UNUSED(list, list->hasOwnCaches());
    1128    
     1127
    11291128    NodeListsNodeData* data = rareData()->nodeLists();
     1129    ASSERT_UNUSED(list, list == data->m_labelsNodeListCache);
    11301130    data->m_labelsNodeListCache = 0;
    11311131}
     
    23902390void NodeListsNodeData::invalidateCaches()
    23912391{
    2392     if (m_childNodeListCaches) {
    2393         if (m_childNodeListCaches->hasOneRef())
    2394             m_childNodeListCaches.clear();
    2395         else
    2396             m_childNodeListCaches->reset();
    2397     }
    2398 
    23992392    if (m_labelsNodeListCache)
    24002393        m_labelsNodeListCache->invalidateCache();
     
    24372430{
    24382431    if (!m_listsWithCaches.isEmpty())
    2439         return false;
    2440 
    2441     if (m_childNodeListCaches)
    24422432        return false;
    24432433
     
    30103000}
    30113001
     3002void NodeRareData::clearChildNodeListCache()
     3003{
     3004    if (!m_childNodeListCache)
     3005        return;
     3006
     3007    if (m_childNodeListCache->hasOneRef())
     3008        m_childNodeListCache.clear();
     3009    else
     3010        m_childNodeListCache->reset();
     3011}
     3012
    30123013} // namespace WebCore
    30133014
  • trunk/Source/WebCore/dom/Node.h

    r102721 r102834  
    5151class DOMSettableTokenList;
    5252class Document;
    53 class DynamicNodeList;
     53class DynamicSubtreeNodeList;
    5454class Element;
    5555class Event;
     
    518518#endif
    519519
    520     void registerDynamicNodeList(DynamicNodeList*);
    521     void unregisterDynamicNodeList(DynamicNodeList*);
     520    void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
     521    void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
    522522    void invalidateNodeListsCacheAfterAttributeChanged();
    523523    void invalidateNodeListsCacheAfterChildrenChanged();
     
    528528    void removeCachedTagNodeList(TagNodeList*, const AtomicString&);
    529529    void removeCachedTagNodeList(TagNodeList*, const QualifiedName&);
    530     void removeCachedLabelsNodeList(DynamicNodeList*);
     530    void removeCachedLabelsNodeList(DynamicSubtreeNodeList*);
    531531
    532532    PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
  • trunk/Source/WebCore/dom/NodeRareData.h

    r102431 r102834  
    2323#define NodeRareData_h
    2424
     25#include "ChildNodeList.h"
    2526#include "ClassNodeList.h"
    2627#include "DOMSettableTokenList.h"
     
    5051    WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED;
    5152public:
    52     typedef HashSet<DynamicNodeList*> NodeListSet;
     53    typedef HashSet<DynamicSubtreeNodeList*> NodeListSet;
    5354    NodeListSet m_listsWithCaches;
    54    
    55     RefPtr<DynamicNodeList::Caches> m_childNodeListCaches;
    56    
     55
    5756    typedef HashMap<String, ClassNodeList*> ClassNodeListCache;
    5857    ClassNodeListCache m_classNodeListCache;
     
    127126    void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
    128127    NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
    129 
    130128    NodeListsNodeData* ensureNodeLists(Node* node)
    131129    {
     
    133131            createNodeLists(node);
    134132        return m_nodeLists.get();
     133    }
     134    void clearChildNodeListCache();
     135    DynamicNodeList::Caches* ensureChildNodeListCache()
     136    {
     137        if (!m_childNodeListCache)
     138            m_childNodeListCache = DynamicNodeList::Caches::create();
     139        return m_childNodeListCache.get();
    135140    }
    136141
     
    237242    TreeScope* m_treeScope;
    238243    OwnPtr<NodeListsNodeData> m_nodeLists;
     244    RefPtr<DynamicNodeList::Caches> m_childNodeListCache;
    239245    OwnPtr<EventTargetData> m_eventTargetData;
    240246    short m_tabIndex;
  • trunk/Source/WebCore/dom/TagNodeList.cpp

    r84586 r102834  
    3131
    3232TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
    33     : DynamicNodeList(rootNode)
     33    : DynamicSubtreeNodeList(rootNode)
    3434    , m_namespaceURI(namespaceURI)
    3535    , m_localName(localName)
     
    4141{
    4242    if (m_namespaceURI == starAtom)
    43         m_rootNode->removeCachedTagNodeList(this, m_localName);
     43        rootNode()->removeCachedTagNodeList(this, m_localName);
    4444    else
    45         m_rootNode->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));
     45        rootNode()->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));
    4646}
    4747
  • trunk/Source/WebCore/dom/TagNodeList.h

    r65077 r102834  
    3131
    3232    // NodeList that limits to a particular tag.
    33     class TagNodeList : public DynamicNodeList {
     33    class TagNodeList : public DynamicSubtreeNodeList {
    3434    public:
    3535        static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
  • trunk/Source/WebCore/html/LabelsNodeList.cpp

    r95901 r102834  
    3434
    3535LabelsNodeList::LabelsNodeList(Node* forNode )
    36     : DynamicNodeList(forNode->document()) , m_forNode(forNode)
     36    : DynamicSubtreeNodeList(forNode->document()) , m_forNode(forNode)
    3737{
    3838}
  • trunk/Source/WebCore/html/LabelsNodeList.h

    r95901 r102834  
    3131namespace WebCore {
    3232
    33 class LabelsNodeList : public DynamicNodeList {
     33class LabelsNodeList : public DynamicSubtreeNodeList {
    3434public:
    3535    static PassRefPtr<LabelsNodeList> create(Node* forNode)
Note: See TracChangeset for help on using the changeset viewer.