diff options
Diffstat (limited to 'Source/WebCore/dom/LiveNodeList.cpp')
-rw-r--r-- | Source/WebCore/dom/LiveNodeList.cpp | 150 |
1 files changed, 12 insertions, 138 deletions
diff --git a/Source/WebCore/dom/LiveNodeList.cpp b/Source/WebCore/dom/LiveNodeList.cpp index 0a15793b9..169d6de33 100644 --- a/Source/WebCore/dom/LiveNodeList.cpp +++ b/Source/WebCore/dom/LiveNodeList.cpp @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2006, 2007, 2008, 2010, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006-2008, 2010, 2013-2014 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,157 +23,31 @@ #include "config.h" #include "LiveNodeList.h" -#include "ClassNodeList.h" +#include "ClassCollection.h" #include "Element.h" #include "ElementTraversal.h" #include "HTMLCollection.h" -#include "TagNodeList.h" namespace WebCore { -ContainerNode& LiveNodeList::rootNode() const +LiveNodeList::LiveNodeList(ContainerNode& ownerNode, NodeListInvalidationType invalidationType) + : m_ownerNode(ownerNode) + , m_invalidationType(invalidationType) + , m_isRegisteredForInvalidationAtDocument(false) { - if (isRootedAtDocument() && ownerNode().inDocument()) - return ownerNode().document(); - - return ownerNode(); + ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType)); } -template <class NodeListType> -inline bool isMatchingElement(const NodeListType*, Element*); - -template <> inline bool isMatchingElement(const LiveNodeList* nodeList, Element* element) +LiveNodeList::~LiveNodeList() { - return nodeList->nodeMatches(element); } -template <> inline bool isMatchingElement(const HTMLTagNodeList* nodeList, Element* element) -{ - return nodeList->nodeMatchesInlined(element); -} - -template <> inline bool isMatchingElement(const ClassNodeList* nodeList, Element* element) -{ - return nodeList->nodeMatchesInlined(element); -} - -ALWAYS_INLINE Element* LiveNodeList::iterateForPreviousElement(Element* current) const -{ - ContainerNode& rootNode = this->rootNode(); - for (; current; current = ElementTraversal::previous(current, &rootNode)) { - if (isMatchingElement(static_cast<const LiveNodeList*>(this), current)) - return current; - } - return 0; -} - -template <class NodeListType> -inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode& root) -{ - Element* element = ElementTraversal::firstWithin(&root); - while (element && !isMatchingElement(nodeList, element)) - element = ElementTraversal::next(element, &root); - return element; -} - -template <class NodeListType> -inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root) -{ - do { - current = ElementTraversal::next(current, &root); - } while (current && !isMatchingElement(nodeList, current)); - return current; -} - -template <class NodeListType> -inline Element* traverseMatchingElementsForward(const NodeListType* nodeList, Element& current, unsigned count, unsigned& traversedCount, ContainerNode& root) -{ - Element* element = ¤t; - for (traversedCount = 0; traversedCount < count; ++traversedCount) { - element = nextMatchingElement(nodeList, element, root); - if (!element) - return nullptr; - } - return element; -} - -Element* LiveNodeList::collectionFirst() const -{ - auto& root = rootNode(); - if (type() == HTMLTagNodeListType) - return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), root); - if (type() == ClassNodeListType) - return firstMatchingElement(static_cast<const ClassNodeList*>(this), root); - return firstMatchingElement(static_cast<const LiveNodeList*>(this), root); -} - -Element* LiveNodeList::collectionLast() const -{ - // FIXME: This should be optimized similarly to the forward case. - return iterateForPreviousElement(ElementTraversal::lastWithin(&rootNode())); -} - -Element* LiveNodeList::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const -{ - auto& root = rootNode(); - if (type() == HTMLTagNodeListType) - return traverseMatchingElementsForward(static_cast<const HTMLTagNodeList*>(this), current, count, traversedCount, root); - if (type() == ClassNodeListType) - return traverseMatchingElementsForward(static_cast<const ClassNodeList*>(this), current, count, traversedCount, root); - return traverseMatchingElementsForward(static_cast<const LiveNodeList*>(this), current, count, traversedCount, root); -} - -Element* LiveNodeList::collectionTraverseBackward(Element& current, unsigned count) const -{ - // FIXME: This should be optimized similarly to the forward case. - auto& root = rootNode(); - Element* element = ¤t; - for (; count && element ; --count) - element = iterateForPreviousElement(ElementTraversal::previous(element, &root)); - return element; -} - -unsigned LiveNodeList::length() const -{ - return m_indexCache.nodeCount(*this); -} - -Node* LiveNodeList::item(unsigned offset) const -{ - return m_indexCache.nodeAt(*this, offset); -} - -void LiveNodeList::invalidateCache() const -{ - m_indexCache.invalidate(); -} - -Node* LiveNodeList::namedItem(const AtomicString& elementId) const +ContainerNode& LiveNodeList::rootNode() const { - // FIXME: Why doesn't this look into the name attribute like HTMLCollection::namedItem does? - Node& rootNode = this->rootNode(); - - if (rootNode.inDocument()) { - Element* element = rootNode.treeScope().getElementById(elementId); - if (element && nodeMatches(element) && element->isDescendantOf(&rootNode)) - return element; - if (!element) - return 0; - // In the case of multiple nodes with the same name, just fall through. - } - - unsigned length = this->length(); - for (unsigned i = 0; i < length; i++) { - Node* node = item(i); - if (!node->isElementNode()) - continue; - Element* element = toElement(node); - // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution. - if (element->hasID() && element->idForStyleResolution() == elementId) - return node; - } + if (isRootedAtDocument() && ownerNode().isConnected()) + return ownerNode().document(); - return 0; + return ownerNode(); } } // namespace WebCore |