Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / LiveNodeList.h
index 3314359..422e6bc 100644 (file)
@@ -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"
@@ -43,41 +44,29 @@ enum NodeListRootType {
 
 class LiveNodeListBase {
 public:
-    enum ItemAfterOverrideType {
-        OverridesItemAfter,
-        DoesNotOverrideItemAfter,
-    };
-
     LiveNodeListBase(ContainerNode* ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType,
-        bool shouldOnlyIncludeDirectChildren, CollectionType collectionType, ItemAfterOverrideType itemAfterOverrideType)
+        CollectionType collectionType)
         : m_ownerNode(ownerNode)
-        , m_cachedItem(0)
-        , m_isLengthCacheValid(false)
         , m_rootType(rootType)
         , m_invalidationType(invalidationType)
-        , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren)
         , m_collectionType(collectionType)
-        , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter)
     {
         ASSERT(m_ownerNode);
         ASSERT(m_rootType == static_cast<unsigned>(rootType));
         ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
         ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
-        ASSERT(!m_overridesItemAfter || !isLiveNodeListType(collectionType));
 
-        if (collectionType != ChildNodeListType)
-            document().registerNodeList(this);
+        document().registerNodeList(this);
     }
 
     virtual ~LiveNodeListBase()
     {
-        if (type() != ChildNodeListType)
-            document().unregisterNodeList(this);
+        document().unregisterNodeList(this);
     }
 
-    unsigned length() const;
-    Node* item(unsigned offset) const;
+    ContainerNode& rootNode() const;
 
+    void didMoveToDocument(Document& oldDocument, Document& newDocument);
     ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type()); }
     ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeListIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr; }
     ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
@@ -90,55 +79,27 @@ public:
         else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr))
             invalidateIdNameCacheMaps();
     }
-    virtual void invalidateCache() const;
+    virtual void invalidateCache(Document* oldDocument = 0) 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; }
+
+    template <typename Collection>
+    static Element* iterateForPreviousNode(const Collection&, Node* current);
+    template <typename Collection>
+    static Element* itemBefore(const Collection&, const Element* previousItem);
 
 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;
     const unsigned m_collectionType : 5;
-
-    // From HTMLCollection
-    const unsigned m_overridesItemAfter : 1;
 };
 
 ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType type, const QualifiedName& attrName)
@@ -157,7 +118,6 @@ ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL
             || attrName == HTMLNames::formAttr || attrName == HTMLNames::typeAttr;
     case InvalidateOnHRefAttrChange:
         return attrName == HTMLNames::hrefAttr;
-    case InvalidateOnItemAttrChange:
     case DoNotInvalidateOnAttributeChanges:
         return false;
     case InvalidateOnAnyAttrChange:
@@ -169,22 +129,27 @@ ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL
 class LiveNodeList : public NodeList, public LiveNodeListBase {
 public:
     LiveNodeList(PassRefPtr<ContainerNode> ownerNode, CollectionType collectionType, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
-        : LiveNodeListBase(ownerNode.get(), rootType, invalidationType, collectionType == ChildNodeListType,
-        collectionType, DoesNotOverrideItemAfter)
+        : LiveNodeListBase(ownerNode.get(), rootType, invalidationType,
+        collectionType)
     { }
 
-    virtual unsigned length() const OVERRIDE FINAL { return LiveNodeListBase::length(); }
-    virtual Node* item(unsigned offset) const OVERRIDE FINAL { return LiveNodeListBase::item(offset); }
-    virtual Node* namedItem(const AtomicString&) const OVERRIDE FINAL;
+    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 bool nodeMatches(const Element&) const = 0;
-    // Avoid ambiguity since both NodeList and LiveNodeListBase have an ownerNode() method.
-    using LiveNodeListBase::ownerNode;
 
-    Node* traverseToFirstElement(const ContainerNode& root) const;
-    Node* traverseForwardToOffset(unsigned offset, Node& currentNode, unsigned& currentOffset, const ContainerNode& root) const;
+    virtual void invalidateCache(Document* oldDocument) const OVERRIDE FINAL;
+    bool shouldOnlyIncludeDirectChildren() const { return false; }
+
+    // Collection IndexCache API.
+    bool canTraverseBackward() const { return true; }
+    Element* itemBefore(const Element* previousItem) const;
+    Element* traverseToFirstElement(const ContainerNode& root) const;
+    Element* traverseForwardToOffset(unsigned offset, Element& currentNode, unsigned& currentOffset, const ContainerNode& root) const;
 
 private:
-    virtual bool isLiveNodeList() const OVERRIDE FINAL { return true; }
+    virtual Node* virtualOwnerNode() const OVERRIDE FINAL;
+
+    mutable CollectionIndexCache<LiveNodeList, Element> m_collectionIndexCache;
 };
 
 } // namespace WebCore