| Index: Source/core/dom/LiveNodeList.h
|
| diff --git a/Source/core/dom/LiveNodeList.h b/Source/core/dom/LiveNodeList.h
|
| index 331435982b6ada5e220fcd2713859ba15ba3e063..e7026bf381edd4d6e5496023b1c191e2b7c3b121 100644
|
| --- a/Source/core/dom/LiveNodeList.h
|
| +++ b/Source/core/dom/LiveNodeList.h
|
| @@ -27,6 +27,7 @@
|
| #include "HTMLNames.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/NodeList.h"
|
| +#include "core/html/CollectionIndexCache.h"
|
| #include "core/html/CollectionType.h"
|
| #include "wtf/Forward.h"
|
| #include "wtf/RefPtr.h"
|
| @@ -51,8 +52,6 @@ public:
|
| LiveNodeListBase(ContainerNode* ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
|
| bool shouldOnlyIncludeDirectChildren, CollectionType collectionType, ItemAfterOverrideType itemAfterOverrideType)
|
| : m_ownerNode(ownerNode)
|
| - , m_cachedItem(0)
|
| - , m_isLengthCacheValid(false)
|
| , m_rootType(rootType)
|
| , m_invalidationType(invalidationType)
|
| , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren)
|
| @@ -75,8 +74,9 @@ public:
|
| document().unregisterNodeList(this);
|
| }
|
|
|
| - unsigned length() const;
|
| - Node* item(unsigned offset) const;
|
| + ContainerNode& rootNode() const;
|
| + bool overridesItemAfter() const { return m_overridesItemAfter; }
|
| + Node* itemBefore(const Node* previousItem) const;
|
|
|
| ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type()); }
|
| ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr; }
|
| @@ -90,48 +90,21 @@ public:
|
| else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
|
| invalidateIdNameCacheMaps();
|
| }
|
| - virtual void invalidateCache() const;
|
| + virtual void invalidateCache() const = 0;
|
|
|
| static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
|
|
|
| protected:
|
| Document& document() const { return m_ownerNode->document(); }
|
| - ContainerNode& rootNode() const;
|
| - bool overridesItemAfter() const { return m_overridesItemAfter; }
|
| -
|
| - ALWAYS_INLINE Node* cachedItem() const { return m_cachedItem; }
|
| - ALWAYS_INLINE unsigned cachedItemOffset() const { ASSERT(cachedItem()); return m_cachedItemOffset; }
|
| -
|
| - ALWAYS_INLINE bool isLengthCacheValid() const { return m_isLengthCacheValid; }
|
| - ALWAYS_INLINE unsigned cachedLength() const { return m_cachedLength; }
|
| - ALWAYS_INLINE void setLengthCache(unsigned length) const
|
| - {
|
| - m_cachedLength = length;
|
| - m_isLengthCacheValid = true;
|
| - }
|
| - ALWAYS_INLINE void setItemCache(Node* item, unsigned offset) const
|
| - {
|
| - ASSERT(item);
|
| - m_cachedItem = item;
|
| - m_cachedItemOffset = offset;
|
| - }
|
|
|
| ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); }
|
| bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
|
|
|
| private:
|
| - Node* itemBeforeOrAfterCachedItem(unsigned offset, const ContainerNode& root) const;
|
| - bool isLastItemCloserThanLastOrCachedItem(unsigned offset) const;
|
| - bool isFirstItemCloserThanCachedItem(unsigned offset) const;
|
| Node* iterateForPreviousNode(Node* current) const;
|
| - Node* itemBefore(const Node* previousItem) const;
|
| void invalidateIdNameCacheMaps() const;
|
|
|
| RefPtr<ContainerNode> m_ownerNode; // Cannot be null.
|
| - mutable Node* m_cachedItem;
|
| - mutable unsigned m_cachedLength;
|
| - mutable unsigned m_cachedItemOffset;
|
| - mutable unsigned m_isLengthCacheValid : 1;
|
| const unsigned m_rootType : 2;
|
| const unsigned m_invalidationType : 4;
|
| const unsigned m_shouldOnlyIncludeDirectChildren : 1;
|
| @@ -173,18 +146,23 @@ public:
|
| collectionType, DoesNotOverrideItemAfter)
|
| { }
|
|
|
| - virtual unsigned length() const OVERRIDE FINAL { return LiveNodeListBase::length(); }
|
| - virtual Node* item(unsigned offset) const OVERRIDE FINAL { return LiveNodeListBase::item(offset); }
|
| + virtual unsigned length() const OVERRIDE FINAL { return m_collectionIndexCache.nodeCount(*this); }
|
| + virtual Node* item(unsigned offset) const OVERRIDE FINAL { return m_collectionIndexCache.nodeAt(*this, offset); }
|
| virtual Node* namedItem(const AtomicString&) const OVERRIDE FINAL;
|
| virtual bool nodeMatches(const Element&) const = 0;
|
| // Avoid ambiguity since both NodeList and LiveNodeListBase have an ownerNode() method.
|
| using LiveNodeListBase::ownerNode;
|
|
|
| + virtual void invalidateCache() const OVERRIDE FINAL;
|
| +
|
| + // Collection IndexCache API.
|
| Node* traverseToFirstElement(const ContainerNode& root) const;
|
| Node* traverseForwardToOffset(unsigned offset, Node& currentNode, unsigned& currentOffset, const ContainerNode& root) const;
|
|
|
| private:
|
| virtual bool isLiveNodeList() const OVERRIDE FINAL { return true; }
|
| +
|
| + mutable CollectionIndexCache<LiveNodeList> m_collectionIndexCache;
|
| };
|
|
|
| } // namespace WebCore
|
|
|