Index: Source/core/dom/LiveNodeListBase.h |
diff --git a/Source/core/dom/LiveNodeListBase.h b/Source/core/dom/LiveNodeListBase.h |
index 098d8ddfcce190a3990ec3465e337ff0c38c3ca4..d87d19b25e89ebb2244f219e20b1addd67b1bbb3 100644 |
--- a/Source/core/dom/LiveNodeListBase.h |
+++ b/Source/core/dom/LiveNodeListBase.h |
@@ -27,6 +27,8 @@ |
#include "HTMLNames.h" |
#include "core/dom/Document.h" |
+#include "core/dom/Element.h" |
+#include "core/dom/NodeTraversal.h" |
#include "core/html/CollectionType.h" |
namespace WebCore { |
@@ -84,12 +86,15 @@ protected: |
ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); } |
template <typename Collection> |
- static Element* iterateForPreviousNode(const Collection&, Node* current); |
- template <typename Collection> |
static Element* itemBefore(const Collection&, const Element* previousItem); |
private: |
void invalidateIdNameCacheMaps() const; |
+ template <typename Collection> |
+ static Element* iterateForPreviousNode(const Collection&, Node* current); |
+ static Node* previousNode(const ContainerNode&, const Node& previous, bool onlyIncludeDirectChildren); |
+ static Node* lastDescendant(const ContainerNode&); |
+ static Node* lastNode(const ContainerNode&, bool onlyIncludeDirectChildren); |
RefPtr<ContainerNode> m_ownerNode; // Cannot be null. |
const unsigned m_rootType : 2; |
@@ -121,6 +126,48 @@ ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL |
return false; |
} |
+inline Node* LiveNodeListBase::previousNode(const ContainerNode& base, const Node& previous, bool onlyIncludeDirectChildren) |
+{ |
+ return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversal::previous(previous, &base); |
+} |
+ |
+inline Node* LiveNodeListBase::lastDescendant(const ContainerNode& node) |
+{ |
+ Node* descendant = node.lastChild(); |
+ for (Node* current = descendant; current; current = current->lastChild()) |
+ descendant = current; |
+ return descendant; |
+} |
+ |
+inline Node* LiveNodeListBase::lastNode(const ContainerNode& rootNode, bool onlyIncludeDirectChildren) |
+{ |
+ return onlyIncludeDirectChildren ? rootNode.lastChild() : lastDescendant(rootNode); |
+} |
+ |
+template <typename Collection> |
+inline Element* LiveNodeListBase::iterateForPreviousNode(const Collection& collection, Node* current) |
adamk
2014/02/25 22:05:40
I take it you're hoping the ALWAYS_INLINE wasn't n
Inactive
2014/02/25 22:32:45
I dropped the inline as it shouldn't be needed for
|
+{ |
+ bool onlyIncludeDirectChildren = collection.shouldOnlyIncludeDirectChildren(); |
+ ContainerNode& rootNode = collection.rootNode(); |
+ for (; current; current = previousNode(rootNode, *current, onlyIncludeDirectChildren)) { |
+ if (current->isElementNode() && isMatchingElement(collection, toElement(*current))) |
+ return toElement(current); |
+ } |
+ return 0; |
+} |
+ |
+template <typename Collection> |
+Element* LiveNodeListBase::itemBefore(const Collection& collection, const Element* previous) |
+{ |
+ Node* current; |
+ if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 10% slower. |
+ current = previousNode(collection.rootNode(), *previous, collection.shouldOnlyIncludeDirectChildren()); |
+ else |
+ current = lastNode(collection.rootNode(), collection.shouldOnlyIncludeDirectChildren()); |
+ |
+ return iterateForPreviousNode(collection, current); |
+} |
+ |
} // namespace WebCore |
#endif // LiveNodeListBase_h |