| Index: Source/core/html/HTMLCollection.cpp
|
| diff --git a/Source/core/html/HTMLCollection.cpp b/Source/core/html/HTMLCollection.cpp
|
| index 6402d501849435ac64123ad87c3b3f89c9e09bd0..e9852fd019d507cc420b8ce4e06ba05a9d88bc8d 100644
|
| --- a/Source/core/html/HTMLCollection.cpp
|
| +++ b/Source/core/html/HTMLCollection.cpp
|
| @@ -255,43 +255,53 @@ static inline bool isMatchingHTMLElement(const HTMLCollection& htmlCollection, c
|
| return false;
|
| }
|
|
|
| -template <class NodeListType>
|
| -inline bool isMatchingElement(const NodeListType&, const Element&);
|
| -
|
| -template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element)
|
| +inline bool HTMLCollection::elementMatches(const Element& element) const
|
| {
|
| // These collections apply to any kind of Elements, not just HTMLElements.
|
| - switch (htmlCollection.type()) {
|
| + switch (type()) {
|
| case DocAll:
|
| case NodeChildren:
|
| return true;
|
| case ClassCollectionType:
|
| - return toClassCollection(htmlCollection).elementMatches(element);
|
| + return toClassCollection(*this).elementMatches(element);
|
| case TagCollectionType:
|
| - return toTagCollection(htmlCollection).elementMatches(element);
|
| + return toTagCollection(*this).elementMatches(element);
|
| case HTMLTagCollectionType:
|
| - return toHTMLTagCollection(htmlCollection).elementMatches(element);
|
| + return toHTMLTagCollection(*this).elementMatches(element);
|
| case DocumentNamedItems:
|
| - return toDocumentNameCollection(htmlCollection).elementMatches(element);
|
| + return toDocumentNameCollection(*this).elementMatches(element);
|
| case WindowNamedItems:
|
| - return toWindowNameCollection(htmlCollection).elementMatches(element);
|
| + return toWindowNameCollection(*this).elementMatches(element);
|
| default:
|
| break;
|
| }
|
|
|
| // The following only applies to HTMLElements.
|
| - return element.isHTMLElement() && isMatchingHTMLElement(htmlCollection, toHTMLElement(element));
|
| + return element.isHTMLElement() && isMatchingHTMLElement(*this, toHTMLElement(element));
|
| }
|
|
|
| -template <> inline bool isMatchingElement(const ClassCollection& collection, const Element& element)
|
| -{
|
| - return collection.elementMatches(element);
|
| -}
|
| +namespace {
|
|
|
| -template <> inline bool isMatchingElement(const HTMLTagCollection& collection, const Element& element)
|
| -{
|
| - return collection.elementMatches(element);
|
| -}
|
| +template <class HTMLCollectionType>
|
| +class IsMatch {
|
| +public:
|
| + IsMatch(const HTMLCollectionType& list)
|
| + : m_list(list)
|
| + { }
|
| +
|
| + bool operator() (const Element& element) const
|
| + {
|
| + return m_list.elementMatches(element);
|
| + }
|
| +
|
| +private:
|
| + const HTMLCollectionType& m_list;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +template <class HTMLCollectionType>
|
| +static inline IsMatch<HTMLCollectionType> makeIsMatch(const HTMLCollectionType& list) { return IsMatch<HTMLCollectionType>(list); }
|
|
|
| Element* HTMLCollection::virtualItemAfter(Element*) const
|
| {
|
| @@ -318,53 +328,19 @@ static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element)
|
| || element.hasTagName(selectTag);
|
| }
|
|
|
| -inline Element* firstMatchingChildElement(const HTMLCollection& nodeList)
|
| -{
|
| - Element* element = ElementTraversal::firstChild(nodeList.rootNode());
|
| - while (element && !isMatchingElement(nodeList, *element))
|
| - element = ElementTraversal::nextSibling(*element);
|
| - return element;
|
| -}
|
| -
|
| -inline Element* lastMatchingChildElement(const HTMLCollection& nodeList)
|
| -{
|
| - Element* element = ElementTraversal::lastChild(nodeList.rootNode());
|
| - while (element && !isMatchingElement(nodeList, *element))
|
| - element = ElementTraversal::previousSibling(*element);
|
| - return element;
|
| -}
|
| -
|
| -inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element& current)
|
| -{
|
| - Element* next = ¤t;
|
| - do {
|
| - next = ElementTraversal::nextSibling(*next);
|
| - } while (next && !isMatchingElement(nodeList, *next));
|
| - return next;
|
| -}
|
| -
|
| -inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Element& current)
|
| -{
|
| - Element* previous = ¤t;
|
| - do {
|
| - previous = ElementTraversal::previousSibling(*previous);
|
| - } while (previous && !isMatchingElement(nodeList, *previous));
|
| - return previous;
|
| -}
|
| -
|
| Element* HTMLCollection::traverseToFirstElement() const
|
| {
|
| switch (type()) {
|
| case HTMLTagCollectionType:
|
| - return firstMatchingElement(toHTMLTagCollection(*this));
|
| + return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toHTMLTagCollection(*this)));
|
| case ClassCollectionType:
|
| - return firstMatchingElement(toClassCollection(*this));
|
| + return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toClassCollection(*this)));
|
| default:
|
| if (overridesItemAfter())
|
| return virtualItemAfter(0);
|
| if (shouldOnlyIncludeDirectChildren())
|
| - return firstMatchingChildElement(*this);
|
| - return firstMatchingElement(*this);
|
| + return ElementTraversal::firstChild(rootNode(), makeIsMatch(*this));
|
| + return ElementTraversal::firstWithin(rootNode(), makeIsMatch(*this));
|
| }
|
| }
|
|
|
| @@ -372,8 +348,8 @@ Element* HTMLCollection::traverseToLastElement() const
|
| {
|
| ASSERT(canTraverseBackward());
|
| if (shouldOnlyIncludeDirectChildren())
|
| - return lastMatchingChildElement(*this);
|
| - return lastMatchingElement(*this);
|
| + return ElementTraversal::lastChild(rootNode(), makeIsMatch(*this));
|
| + return ElementTraversal::lastWithin(rootNode(), makeIsMatch(*this));
|
| }
|
|
|
| Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const
|
| @@ -381,9 +357,9 @@ Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre
|
| ASSERT(currentOffset < offset);
|
| switch (type()) {
|
| case HTMLTagCollectionType:
|
| - return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this), offset, currentElement, currentOffset);
|
| + return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(toHTMLTagCollection(*this)));
|
| case ClassCollectionType:
|
| - return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset);
|
| + return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(toClassCollection(*this)));
|
| default:
|
| if (overridesItemAfter()) {
|
| for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) {
|
| @@ -393,13 +369,14 @@ Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre
|
| return 0;
|
| }
|
| if (shouldOnlyIncludeDirectChildren()) {
|
| - for (Element* next = nextMatchingChildElement(*this, currentElement); next; next = nextMatchingChildElement(*this, *next)) {
|
| + IsMatch<HTMLCollection> isMatch(*this);
|
| + for (Element* next = ElementTraversal::nextSibling(currentElement, isMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) {
|
| if (++currentOffset == offset)
|
| return next;
|
| }
|
| return 0;
|
| }
|
| - return traverseMatchingElementsForwardToOffset(*this, offset, currentElement, currentOffset);
|
| + return traverseMatchingElementsForwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this));
|
| }
|
| }
|
|
|
| @@ -408,13 +385,14 @@ Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr
|
| ASSERT(currentOffset > offset);
|
| ASSERT(canTraverseBackward());
|
| if (shouldOnlyIncludeDirectChildren()) {
|
| - for (Element* previous = previousMatchingChildElement(*this, currentElement); previous; previous = previousMatchingChildElement(*this, *previous)) {
|
| + IsMatch<HTMLCollection> isMatch(*this);
|
| + for (Element* previous = ElementTraversal::previousSibling(currentElement, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, isMatch)) {
|
| if (--currentOffset == offset)
|
| return previous;
|
| }
|
| return 0;
|
| }
|
| - return traverseMatchingElementsBackwardToOffset(*this, offset, currentElement, currentOffset);
|
| + return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this));
|
| }
|
|
|
| Element* HTMLCollection::namedItem(const AtomicString& name) const
|
|
|