Changeset 158536 in webkit


Ignore:
Timestamp:
Nov 3, 2013 11:52:40 AM (10 years ago)
Author:
Antti Koivisto
Message:

ChildNodeList should not be LiveNodeList
https://bugs.webkit.org/show_bug.cgi?id=123708

Reviewed by Sam Weinig.

ChildNodeList is a poor fit to be a LiveNodeList. It is heavily special-cased. It is also
the only subtype that returns non-Elements thus preventing tightening.

  • bindings/js/JSNodeListCustom.cpp:

(WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):

Support new types.

  • dom/ChildNodeList.cpp:

(WebCore::EmptyNodeList::~EmptyNodeList):
(WebCore::ChildNodeList::ChildNodeList):
(WebCore::ChildNodeList::~ChildNodeList):
(WebCore::ChildNodeList::length):
(WebCore::childFromFirst):
(WebCore::childFromLast):
(WebCore::ChildNodeList::nodeBeforeCached):
(WebCore::ChildNodeList::nodeAfterCached):
(WebCore::ChildNodeList::item):
(WebCore::ChildNodeList::namedItem):
(WebCore::ChildNodeList::invalidateCache):

Implement the same caching optimizations as LiveNodeList with tighter, less generic code.

  • dom/ChildNodeList.h:


Inherit ChildNodeList directly from NodeList.

Add new EmptyNodeList type. This is only ever used if NodeList is requested for a non-container node.
It allows tighter typing in ChildNodeList.

  • dom/LiveNodeList.cpp:

(WebCore::LiveNodeList::namedItem):

  • dom/LiveNodeList.h:

(WebCore::LiveNodeListBase::LiveNodeListBase):
(WebCore::LiveNodeListBase::~LiveNodeListBase):
(WebCore::LiveNodeList::LiveNodeList):

Remove ChildNodeList specific code and branches.

  • dom/Node.cpp:

(WebCore::Node::childNodes):

Return EmptyNodeList for non-containers.

  • dom/NodeList.h:

(WebCore::NodeList::~NodeList):
(WebCore::NodeList::isLiveNodeList):
(WebCore::NodeList::isChildNodeList):
(WebCore::NodeList::isEmptyNodeList):

For isReachableFromOpaqueRoots.

  • dom/NodeRareData.h:

(WebCore::NodeListsNodeData::ensureChildNodeList):
(WebCore::NodeListsNodeData::removeChildNodeList):
(WebCore::NodeListsNodeData::ensureEmptyChildNodeList):
(WebCore::NodeListsNodeData::removeEmptyChildNodeList):
(WebCore::NodeListsNodeData::NodeListsNodeData):
(WebCore::NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList):

EmptyNodeList support.

  • html/CollectionType.h:
  • html/HTMLCollection.cpp:

(WebCore::shouldOnlyIncludeDirectChildren):
(WebCore::rootTypeFromCollectionType):
(WebCore::invalidationTypeExcludingIdAndNameAttributes):
(WebCore::isMatchingElement):
(WebCore::LiveNodeListBase::itemBefore):
(WebCore::LiveNodeListBase::traverseLiveNodeListFirstElement):
(WebCore::LiveNodeListBase::traverseLiveNodeListForwardToOffset):
(WebCore::LiveNodeListBase::item):
(WebCore::LiveNodeListBase::itemBeforeOrAfterCachedItem):

Remove ChildNodeList specific code and branches.

Location:
trunk/Source/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r158533 r158536  
     12013-11-03  Antti Koivisto  <antti@apple.com>
     2
     3        ChildNodeList should not be LiveNodeList
     4        https://bugs.webkit.org/show_bug.cgi?id=123708
     5
     6        Reviewed by Sam Weinig.
     7
     8        ChildNodeList is a poor fit to be a LiveNodeList. It is heavily special-cased. It is also
     9        the only subtype that returns non-Elements thus preventing tightening.
     10
     11        * bindings/js/JSNodeListCustom.cpp:
     12        (WebCore::JSNodeListOwner::isReachableFromOpaqueRoots):
     13       
     14            Support new types.
     15
     16        * dom/ChildNodeList.cpp:
     17        (WebCore::EmptyNodeList::~EmptyNodeList):
     18        (WebCore::ChildNodeList::ChildNodeList):
     19        (WebCore::ChildNodeList::~ChildNodeList):
     20        (WebCore::ChildNodeList::length):
     21        (WebCore::childFromFirst):
     22        (WebCore::childFromLast):
     23        (WebCore::ChildNodeList::nodeBeforeCached):
     24        (WebCore::ChildNodeList::nodeAfterCached):
     25        (WebCore::ChildNodeList::item):
     26        (WebCore::ChildNodeList::namedItem):
     27        (WebCore::ChildNodeList::invalidateCache):
     28       
     29            Implement the same caching optimizations as LiveNodeList with tighter, less generic code.
     30
     31        * dom/ChildNodeList.h:
     32       
     33            Inherit ChildNodeList directly from NodeList.
     34
     35            Add new EmptyNodeList type. This is only ever used if NodeList is requested for a non-container node.
     36            It allows tighter typing in ChildNodeList.
     37
     38        * dom/LiveNodeList.cpp:
     39        (WebCore::LiveNodeList::namedItem):
     40        * dom/LiveNodeList.h:
     41        (WebCore::LiveNodeListBase::LiveNodeListBase):
     42        (WebCore::LiveNodeListBase::~LiveNodeListBase):
     43        (WebCore::LiveNodeList::LiveNodeList):
     44       
     45            Remove ChildNodeList specific code and branches.
     46
     47        * dom/Node.cpp:
     48        (WebCore::Node::childNodes):
     49       
     50            Return EmptyNodeList for non-containers.
     51
     52        * dom/NodeList.h:
     53        (WebCore::NodeList::~NodeList):
     54        (WebCore::NodeList::isLiveNodeList):
     55        (WebCore::NodeList::isChildNodeList):
     56        (WebCore::NodeList::isEmptyNodeList):
     57       
     58            For isReachableFromOpaqueRoots.
     59
     60        * dom/NodeRareData.h:
     61        (WebCore::NodeListsNodeData::ensureChildNodeList):
     62        (WebCore::NodeListsNodeData::removeChildNodeList):
     63        (WebCore::NodeListsNodeData::ensureEmptyChildNodeList):
     64        (WebCore::NodeListsNodeData::removeEmptyChildNodeList):
     65        (WebCore::NodeListsNodeData::NodeListsNodeData):
     66        (WebCore::NodeListsNodeData::deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList):
     67       
     68            EmptyNodeList support.
     69
     70        * html/CollectionType.h:
     71        * html/HTMLCollection.cpp:
     72        (WebCore::shouldOnlyIncludeDirectChildren):
     73        (WebCore::rootTypeFromCollectionType):
     74        (WebCore::invalidationTypeExcludingIdAndNameAttributes):
     75        (WebCore::isMatchingElement):
     76        (WebCore::LiveNodeListBase::itemBefore):
     77        (WebCore::LiveNodeListBase::traverseLiveNodeListFirstElement):
     78        (WebCore::LiveNodeListBase::traverseLiveNodeListForwardToOffset):
     79        (WebCore::LiveNodeListBase::item):
     80        (WebCore::LiveNodeListBase::itemBeforeOrAfterCachedItem):
     81       
     82            Remove ChildNodeList specific code and branches.
     83
    1842013-11-03  Patrick Gansterer  <paroga@webkit.org>
    285
  • trunk/Source/WebCore/bindings/js/JSNodeListCustom.cpp

    r157215 r158536  
    2727#include "JSNodeList.h"
    2828
     29#include "ChildNodeList.h"
    2930#include "JSNode.h"
    3031#include "LiveNodeList.h"
     
    4243    if (!jsNodeList->hasCustomProperties())
    4344        return false;
    44     if (!jsNodeList->impl().isLiveNodeList())
    45         return false;
    46     return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->impl()).ownerNode()));
     45    if (jsNodeList->impl().isLiveNodeList())
     46        return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->impl()).ownerNode()));
     47    if (jsNodeList->impl().isChildNodeList())
     48        return visitor.containsOpaqueRoot(root(static_cast<ChildNodeList&>(jsNodeList->impl()).ownerNode()));
     49    if (jsNodeList->impl().isEmptyNodeList())
     50        return visitor.containsOpaqueRoot(root(static_cast<EmptyNodeList&>(jsNodeList->impl()).ownerNode()));
     51    return false;
    4752}
    4853
  • trunk/Source/WebCore/dom/ChildNodeList.cpp

    r157365 r158536  
    2525
    2626#include "Element.h"
     27#include "ElementIterator.h"
    2728#include "NodeRareData.h"
    2829
    2930namespace WebCore {
    3031
    31 ChildNodeList::ChildNodeList(Node& node)
    32     : LiveNodeList(node, ChildNodeListType, DoNotInvalidateOnAttributeChanges)
     32EmptyNodeList::~EmptyNodeList()
     33{
     34    m_owner.get().nodeLists()->removeEmptyChildNodeList(this);
     35}
     36
     37ChildNodeList::ChildNodeList(ContainerNode& parent)
     38    : m_parent(parent)
     39    , m_cachedLength(0)
     40    , m_cachedLengthValid(false)
     41    , m_cachedCurrentPosition(0)
     42    , m_cachedCurrentNode(nullptr)
    3343{
    3444}
     
    3646ChildNodeList::~ChildNodeList()
    3747{
    38     ownerNode().nodeLists()->removeChildNodeList(this);
     48    m_parent.get().nodeLists()->removeChildNodeList(this);
    3949}
    4050
    41 bool ChildNodeList::nodeMatches(Element* testNode) const
     51unsigned ChildNodeList::length() const
    4252{
    43     // This function will be called only by LiveNodeList::namedItem,
    44     // for an element that was located with getElementById.
    45     return testNode->parentNode() == &rootNode();
     53    if (!m_cachedLengthValid) {
     54        m_cachedLength = m_parent->childNodeCount();
     55        m_cachedLengthValid = true;
     56    }
     57    return m_cachedLength;
     58}
     59
     60static Node* childFromFirst(const ContainerNode& parent, unsigned delta)
     61{
     62    Node* child = parent.firstChild();
     63    for (; delta && child; --delta)
     64        child = child->nextSibling();
     65    return child;
     66}
     67
     68static Node* childFromLast(const ContainerNode& parent, unsigned delta)
     69{
     70    Node* child = parent.lastChild();
     71    for (; delta; --delta)
     72        child = child->previousSibling();
     73    ASSERT(child);
     74    return child;
     75}
     76
     77Node* ChildNodeList::nodeBeforeCached(unsigned index) const
     78{
     79    ASSERT(m_cachedCurrentNode);
     80    ASSERT(index < m_cachedCurrentPosition);
     81    if (index < m_cachedCurrentPosition - index) {
     82        m_cachedCurrentNode = childFromFirst(m_parent.get(), index);
     83        m_cachedCurrentPosition = index;
     84        return m_cachedCurrentNode;
     85    }
     86    while (m_cachedCurrentNode && m_cachedCurrentPosition > index) {
     87        m_cachedCurrentNode = m_cachedCurrentNode->previousSibling();
     88        --m_cachedCurrentPosition;
     89    }
     90    return m_cachedCurrentNode;
     91}
     92
     93Node* ChildNodeList::nodeAfterCached(unsigned index) const
     94{
     95    ASSERT(m_cachedCurrentNode);
     96    ASSERT(index > m_cachedCurrentPosition);
     97    ASSERT(!m_cachedLengthValid || index < m_cachedLength);
     98    if (m_cachedLengthValid && m_cachedLength - index < index - m_cachedCurrentPosition) {
     99        m_cachedCurrentNode = childFromLast(m_parent.get(), m_cachedLength - index - 1);
     100        m_cachedCurrentPosition = index;
     101        return m_cachedCurrentNode;
     102    }
     103    while (m_cachedCurrentNode && m_cachedCurrentPosition < index) {
     104        m_cachedCurrentNode = m_cachedCurrentNode->nextSibling();
     105        ++m_cachedCurrentPosition;
     106    }
     107    if (!m_cachedCurrentNode && !m_cachedLengthValid) {
     108        m_cachedLength = m_cachedCurrentPosition;
     109        m_cachedLengthValid = true;
     110    }
     111    return m_cachedCurrentNode;
     112}
     113
     114Node* ChildNodeList::item(unsigned index) const
     115{
     116    if (m_cachedLengthValid && index >= m_cachedLength)
     117        return nullptr;
     118    if (m_cachedCurrentNode) {
     119        if (index > m_cachedCurrentPosition)
     120            return nodeAfterCached(index);
     121        if (index < m_cachedCurrentPosition)
     122            return nodeBeforeCached(index);
     123        return m_cachedCurrentNode;
     124    }
     125    if (m_cachedLengthValid && m_cachedLength - index < index)
     126        m_cachedCurrentNode = childFromLast(m_parent.get(), m_cachedLength - index - 1);
     127    else
     128        m_cachedCurrentNode = childFromFirst(m_parent.get(), index);
     129    m_cachedCurrentPosition = index;
     130    return m_cachedCurrentNode;
     131}
     132
     133Node* ChildNodeList::namedItem(const AtomicString& name) const
     134{
     135    // FIXME: According to the spec child node list should not have namedItem().
     136    if (m_parent.get().inDocument()) {
     137        Element* element = m_parent.get().treeScope().getElementById(name);
     138        if (element && element->parentNode() == &m_parent.get())
     139            return element;
     140        if (!element || !m_parent.get().treeScope().containsMultipleElementsWithId(name))
     141            return nullptr;
     142    }
     143    auto children = elementChildren(m_parent.get());
     144    for (auto it = children.begin(), end = children.end(); it != end; ++it) {
     145        auto& element = *it;
     146        if (element.hasID() && element.idForStyleResolution() == name)
     147            return const_cast<Element*>(&element);
     148    }
     149    return nullptr;
     150}
     151
     152void ChildNodeList::invalidateCache()
     153{
     154    m_cachedCurrentNode = nullptr;
     155    m_cachedLengthValid = false;
    46156}
    47157
  • trunk/Source/WebCore/dom/ChildNodeList.h

    r157065 r158536  
    2525#define ChildNodeList_h
    2626
    27 #include "LiveNodeList.h"
    28 #include <wtf/PassRefPtr.h>
     27#include "NodeList.h"
     28#include <wtf/Ref.h>
     29#include <wtf/RefPtr.h>
    2930
    3031namespace WebCore {
    3132
    32     class ChildNodeList : public LiveNodeList {
    33     public:
    34         static PassRefPtr<ChildNodeList> create(Node& rootNode)
    35         {
    36             return adoptRef(new ChildNodeList(rootNode));
    37         }
     33class ContainerNode;
    3834
    39         virtual ~ChildNodeList();
     35class EmptyNodeList FINAL : public NodeList {
     36public:
     37    static PassRefPtr<EmptyNodeList> create(Node& owner)
     38    {
     39        return adoptRef(new EmptyNodeList(owner));
     40    }
     41    virtual ~EmptyNodeList();
    4042
    41     protected:
    42         explicit ChildNodeList(Node& rootNode);
     43    Node& ownerNode() { return m_owner.get(); }
    4344
    44         virtual bool nodeMatches(Element*) const OVERRIDE;
    45     };
     45private:
     46    explicit EmptyNodeList(Node& owner) : m_owner(owner) { }
     47
     48    virtual unsigned length() const OVERRIDE { return 0; }
     49    virtual Node* item(unsigned) const OVERRIDE { return nullptr; }
     50    virtual Node* namedItem(const AtomicString&) const OVERRIDE { return nullptr; }
     51
     52    virtual bool isEmptyNodeList() const OVERRIDE { return true; }
     53
     54    Ref<Node> m_owner;
     55};
     56
     57class ChildNodeList FINAL : public NodeList {
     58public:
     59    static PassRefPtr<ChildNodeList> create(ContainerNode& parent)
     60    {
     61        return adoptRef(new ChildNodeList(parent));
     62    }
     63
     64    virtual ~ChildNodeList();
     65
     66    ContainerNode& ownerNode() { return m_parent.get(); }
     67
     68    void invalidateCache();
     69
     70private:
     71    explicit ChildNodeList(ContainerNode& parent);
     72
     73    virtual unsigned length() const OVERRIDE;
     74    virtual Node* item(unsigned index) const OVERRIDE;
     75    virtual Node* namedItem(const AtomicString&) const OVERRIDE;
     76
     77    virtual bool isChildNodeList() const OVERRIDE { return true; }
     78
     79    Node* nodeBeforeCached(unsigned) const;
     80    Node* nodeAfterCached(unsigned) const;
     81
     82    Ref<ContainerNode> m_parent;
     83    mutable unsigned m_cachedLength : 31;
     84    mutable unsigned m_cachedLengthValid : 1;
     85    mutable unsigned m_cachedCurrentPosition;
     86    mutable Node* m_cachedCurrentNode;
     87};
    4688
    4789} // namespace WebCore
  • trunk/Source/WebCore/dom/LiveNodeList.cpp

    r157365 r158536  
    7272Node* LiveNodeList::namedItem(const AtomicString& elementId) const
    7373{
     74    // FIXME: Why doesn't this look into the name attribute like HTMLCollection::namedItem does?
    7475    Node& rootNode = this->rootNode();
    7576
  • trunk/Source/WebCore/dom/LiveNodeList.h

    r157365 r158536  
    6868        ASSERT(!m_overridesItemAfter || !isNodeList(collectionType));
    6969
    70         if (collectionType != ChildNodeListType)
    71             document().registerNodeList(this);
     70        document().registerNodeList(this);
    7271    }
    7372
    7473    virtual ~LiveNodeListBase()
    7574    {
    76         if (type() != ChildNodeListType)
    77             document().unregisterNodeList(this);
     75        document().unregisterNodeList(this);
    7876    }
    7977
     
    137135private:
    138136    Node* itemBeforeOrAfterCachedItem(unsigned offset, ContainerNode* root) const;
    139     Node* traverseChildNodeListForwardToOffset(unsigned offset, Node* currentNode, unsigned& currentOffset) const;
    140137    Element* traverseLiveNodeListFirstElement(ContainerNode* root) const;
    141138    Element* traverseLiveNodeListForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) const;
     
    189186public:
    190187    LiveNodeList(Node& ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
    191         : LiveNodeListBase(ownerNode, rootType, invalidationType, collectionType == ChildNodeListType,
    192         collectionType, DoesNotOverrideItemAfter)
     188        : LiveNodeListBase(ownerNode, rootType, invalidationType, /*shouldOnlyIncludeDirectChildren*/ false, collectionType, DoesNotOverrideItemAfter)
    193189    { }
    194190
  • trunk/Source/WebCore/dom/Node.cpp

    r158163 r158536  
    427427PassRefPtr<NodeList> Node::childNodes()
    428428{
    429     return ensureRareData().ensureNodeLists().ensureChildNodeList(*this);
     429    if (isContainerNode())
     430        return ensureRareData().ensureNodeLists().ensureChildNodeList(toContainerNode(*this));
     431    return ensureRareData().ensureNodeLists().ensureEmptyChildNodeList(*this);
    430432}
    431433
  • trunk/Source/WebCore/dom/NodeList.h

    r135671 r158536  
    3131namespace WebCore {
    3232
    33     class Node;
     33class Node;
    3434
    35     class NodeList : public ScriptWrappable, public RefCounted<NodeList> {
    36     public:
    37         virtual ~NodeList() { }
     35class NodeList : public ScriptWrappable, public RefCounted<NodeList> {
     36public:
     37    virtual ~NodeList() { }
    3838
    39         // DOM methods & attributes for NodeList
    40         virtual unsigned length() const = 0;
    41         virtual Node* item(unsigned index) const = 0;
    42         virtual Node* namedItem(const AtomicString&) const = 0;
     39    // DOM methods & attributes for NodeList
     40    virtual unsigned length() const = 0;
     41    virtual Node* item(unsigned index) const = 0;
     42    virtual Node* namedItem(const AtomicString&) const = 0;
    4343
    44         // Other methods (not part of DOM)
    45         virtual bool isLiveNodeList() const { return false; }
    46     };
     44    // Other methods (not part of DOM)
     45    virtual bool isLiveNodeList() const { return false; }
     46    virtual bool isChildNodeList() const { return false; }
     47    virtual bool isEmptyNodeList() const { return false; }
     48};
    4749
    4850} // namespace WebCore
  • trunk/Source/WebCore/dom/NodeRareData.h

    r157653 r158536  
    5656    }
    5757
    58     PassRefPtr<ChildNodeList> ensureChildNodeList(Node& node)
    59     {
     58    PassRefPtr<ChildNodeList> ensureChildNodeList(ContainerNode& node)
     59    {
     60        ASSERT(!m_emptyChildNodeList);
    6061        if (m_childNodeList)
    6162            return m_childNodeList;
     
    6768    void removeChildNodeList(ChildNodeList* list)
    6869    {
    69         ASSERT(m_childNodeList = list);
    70         if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
    71             return;
    72         m_childNodeList = 0;
     70        ASSERT(m_childNodeList == list);
     71        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
     72            return;
     73        m_childNodeList = nullptr;
     74    }
     75
     76    PassRefPtr<EmptyNodeList> ensureEmptyChildNodeList(Node& node)
     77    {
     78        ASSERT(!m_childNodeList);
     79        if (m_emptyChildNodeList)
     80            return m_emptyChildNodeList;
     81        RefPtr<EmptyNodeList> list = EmptyNodeList::create(node);
     82        m_emptyChildNodeList = list.get();
     83        return list.release();
     84    }
     85
     86    void removeEmptyChildNodeList(EmptyNodeList* list)
     87    {
     88        ASSERT(m_emptyChildNodeList == list);
     89        if (deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(list->ownerNode()))
     90            return;
     91        m_emptyChildNodeList = nullptr;
    7392    }
    7493
     
    214233private:
    215234    NodeListsNodeData()
    216         : m_childNodeList(0)
     235        : m_childNodeList(nullptr)
     236        , m_emptyChildNodeList(nullptr)
    217237    { }
    218238
     
    229249    bool deleteThisAndUpdateNodeRareDataIfAboutToRemoveLastList(Node&);
    230250
    231     // FIXME: m_childNodeList should be merged into m_atomicNameCaches or at least be shared with HTMLCollection returned by Element::children
    232     // but it's tricky because invalidateCaches shouldn't invalidate this cache and adoptTreeScope shouldn't call registerNodeList or unregisterNodeList.
     251    // These two are currently mutually exclusive and could be unioned. Not very important as this class is large anyway.
    233252    ChildNodeList* m_childNodeList;
     253    EmptyNodeList* m_emptyChildNodeList;
     254
    234255    NodeListAtomicNameCacheMap m_atomicNameCaches;
    235256    NodeListNameCacheMap m_nameCaches;
     
    299320{
    300321    ASSERT(ownerNode.nodeLists() == this);
    301     if ((m_childNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_nameCaches.size() + m_tagNodeListCacheNS.size() != 1)
     322    if ((m_childNodeList ? 1 : 0) + (m_emptyChildNodeList ? 1 : 0) + m_atomicNameCaches.size() + m_nameCaches.size() + m_tagNodeListCacheNS.size() != 1)
    302323        return false;
    303324    ownerNode.clearNodeLists();
  • trunk/Source/WebCore/html/CollectionType.h

    r153772 r158536  
    5454
    5555    // Live NodeList.
    56     ChildNodeListType,
    5756    ClassNodeListType,
    5857    NameNodeListType,
     
    6362};
    6463
    65 static const CollectionType FirstNodeListType = ChildNodeListType;
     64static const CollectionType FirstNodeListType = ClassNodeListType;
    6665
    6766inline bool isNodeList(CollectionType type)
  • trunk/Source/WebCore/html/HTMLCollection.cpp

    r157653 r158536  
    6464    case TableTBodies:
    6565        return true;
    66     case ChildNodeListType:
    6766    case ClassNodeListType:
    6867    case NameNodeListType:
     
    102101    case MapAreas:
    103102        return NodeListIsRootedAtNode;
    104     case ChildNodeListType:
    105103    case ClassNodeListType:
    106104    case NameNodeListType:
     
    146144    case FormControls:
    147145        return InvalidateForFormControls;
    148     case ChildNodeListType:
    149146    case ClassNodeListType:
    150147    case NameNodeListType:
     
    229226    case FormControls:
    230227    case TableRows:
    231     case ChildNodeListType:
    232228    case ClassNodeListType:
    233229    case NameNodeListType:
     
    291287        current = lastNode(rootNode(), shouldOnlyIncludeDirectChildren());
    292288
    293     if (type() == ChildNodeListType)
    294         return current;
    295289    return iterateForPreviousNode(current);
    296290}
     
    325319}
    326320
    327 // FIXME: This should be in ChildNodeList
    328 inline Node* LiveNodeListBase::traverseChildNodeListForwardToOffset(unsigned offset, Node* currentNode, unsigned& currentOffset) const
    329 {
    330     ASSERT(type() == ChildNodeListType);
    331     ASSERT_WITH_SECURITY_IMPLICATION(currentOffset < offset);
    332     while ((currentNode = currentNode->nextSibling())) {
    333         if (++currentOffset == offset)
    334             return currentNode;
    335     }
    336     return 0;
    337 }
    338 
    339321// FIXME: This should be in LiveNodeList
    340322inline Element* LiveNodeListBase::traverseLiveNodeListFirstElement(ContainerNode* root) const
    341323{
    342324    ASSERT(isNodeList(type()));
    343     ASSERT(type() != ChildNodeListType);
    344325    if (type() == HTMLTagNodeListType)
    345326        return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), root);
     
    353334{
    354335    ASSERT(isNodeList(type()));
    355     ASSERT(type() != ChildNodeListType);
    356336    if (type() == HTMLTagNodeListType)
    357337        return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTagNodeList*>(this), offset, currentElement, currentOffset, root);
     
    425405        unsigned offsetInArray = 0;
    426406        Node* firstItem;
    427         if (type() == ChildNodeListType)
    428             firstItem = root->firstChild();
    429         else if (isNodeList(type()))
     407        if (isNodeList(type()))
    430408            firstItem = traverseLiveNodeListFirstElement(root);
    431409        else
     
    468446
    469447    unsigned offsetInArray = 0;
    470     if (type() == ChildNodeListType)
    471         currentItem = traverseChildNodeListForwardToOffset(offset, currentItem, currentOffset);
    472     else if (isNodeList(type()))
     448    if (isNodeList(type()))
    473449        currentItem = traverseLiveNodeListForwardToOffset(offset, toElement(currentItem), currentOffset, root);
    474450    else
Note: See TracChangeset for help on using the changeset viewer.