Index: Source/core/html/HTMLCollection.cpp |
diff --git a/Source/core/html/HTMLCollection.cpp b/Source/core/html/HTMLCollection.cpp |
index 74a2ccf0becf9cf5c154c9dea46a34c189ff9430..cb25f06e0965dfcdf2fc2fa4e7c93ef8b1b661cc 100644 |
--- a/Source/core/html/HTMLCollection.cpp |
+++ b/Source/core/html/HTMLCollection.cpp |
@@ -24,7 +24,7 @@ |
#include "core/html/HTMLCollection.h" |
#include "HTMLNames.h" |
-#include "core/dom/ClassNodeList.h" |
+#include "core/dom/ClassCollection.h" |
#include "core/dom/ElementTraversal.h" |
#include "core/dom/NodeList.h" |
#include "core/dom/NodeRareData.h" |
@@ -40,6 +40,9 @@ using namespace HTMLNames; |
static bool shouldOnlyIncludeDirectChildren(CollectionType type) |
{ |
switch (type) { |
+ case ClassCollectionType: |
+ case TagCollectionType: |
+ case HTMLTagCollectionType: |
case DocAll: |
case DocAnchors: |
case DocApplets: |
@@ -63,10 +66,7 @@ static bool shouldOnlyIncludeDirectChildren(CollectionType type) |
case TableTBodies: |
return true; |
case ChildNodeListType: |
- case ClassNodeListType: |
case NameNodeListType: |
- case TagNodeListType: |
- case HTMLTagNodeListType: |
case RadioNodeListType: |
case RadioImgNodeListType: |
case LabelsNodeListType: |
@@ -91,6 +91,9 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) |
case DocumentNamedItems: |
case FormControls: |
return NodeListIsRootedAtDocument; |
+ case ClassCollectionType: |
+ case TagCollectionType: |
+ case HTMLTagCollectionType: |
case NodeChildren: |
case TableTBodies: |
case TSectionRows: |
@@ -102,10 +105,7 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) |
case MapAreas: |
return NodeListIsRootedAtNode; |
case ChildNodeListType: |
- case ClassNodeListType: |
case NameNodeListType: |
- case TagNodeListType: |
- case HTMLTagNodeListType: |
case RadioNodeListType: |
case RadioImgNodeListType: |
case LabelsNodeListType: |
@@ -118,6 +118,8 @@ static NodeListRootType rootTypeFromCollectionType(CollectionType type) |
static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(CollectionType type) |
{ |
switch (type) { |
+ case TagCollectionType: |
+ case HTMLTagCollectionType: |
case DocImages: |
case DocEmbeds: |
case DocForms: |
@@ -146,11 +148,10 @@ static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col |
return InvalidateOnIdNameAttrChange; |
case FormControls: |
return InvalidateForFormControls; |
+ case ClassCollectionType: |
+ return InvalidateOnClassAttrChange; |
case ChildNodeListType: |
- case ClassNodeListType: |
case NameNodeListType: |
- case TagNodeListType: |
- case HTMLTagNodeListType: |
case RadioNodeListType: |
case RadioImgNodeListType: |
case LabelsNodeListType: |
@@ -175,9 +176,11 @@ PassRefPtr<HTMLCollection> HTMLCollection::create(ContainerNode* base, Collectio |
HTMLCollection::~HTMLCollection() |
{ |
- // HTMLNameCollection removes cache by itself. |
- if (type() != WindowNamedItems && type() != DocumentNamedItems) |
+ // HTMLNameCollection, ClassCollection and TagCollection remove cache by themselves. |
+ if (type() != WindowNamedItems && type() != DocumentNamedItems && type() != ClassCollectionType |
+ && type() != HTMLTagCollectionType && type() != TagCollectionType) { |
ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); |
+ } |
} |
void HTMLCollection::invalidateCache() const |
@@ -192,7 +195,24 @@ inline bool isMatchingElement(const NodeListType&, const Element&); |
template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) |
{ |
CollectionType type = htmlCollection.type(); |
- if (!element.isHTMLElement() && !(type == DocAll || type == NodeChildren || type == WindowNamedItems)) |
+ |
+ // These collections apply to any kind of Elements, not just HTMLElements. |
+ switch (type) { |
+ case DocAll: |
+ case NodeChildren: |
+ return true; |
+ case ClassCollectionType: |
+ return static_cast<const ClassCollection&>(htmlCollection).elementMatches(element); |
+ case TagCollectionType: |
+ return static_cast<const TagCollection&>(htmlCollection).elementMatches(element); |
+ case HTMLTagCollectionType: |
+ return static_cast<const HTMLTagCollection&>(htmlCollection).elementMatches(element); |
+ default: |
+ break; |
+ } |
+ |
+ // The following only applies to HTMLElements. |
+ if (!element.isHTMLElement()) |
return false; |
switch (type) { |
@@ -229,18 +249,17 @@ template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, |
return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) && element.fastHasAttribute(hrefAttr); |
case DocAnchors: |
return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr); |
+ case ClassCollectionType: |
+ case TagCollectionType: |
+ case HTMLTagCollectionType: |
case DocAll: |
case NodeChildren: |
- return true; |
case FormControls: |
case DocumentNamedItems: |
case TableRows: |
case WindowNamedItems: |
case ChildNodeListType: |
- case ClassNodeListType: |
case NameNodeListType: |
- case TagNodeListType: |
- case HTMLTagNodeListType: |
case RadioNodeListType: |
case RadioImgNodeListType: |
case LabelsNodeListType: |
@@ -254,16 +273,6 @@ template <> inline bool isMatchingElement(const LiveNodeList& nodeList, const El |
return nodeList.nodeMatches(element); |
} |
-template <> inline bool isMatchingElement(const HTMLTagNodeList& nodeList, const Element& element) |
-{ |
- return nodeList.nodeMatchesInlined(element); |
-} |
- |
-template <> inline bool isMatchingElement(const ClassNodeList& nodeList, const Element& element) |
-{ |
- return nodeList.nodeMatchesInlined(element); |
-} |
- |
static Node* previousNode(const Node& base, const Node& previous, bool onlyIncludeDirectChildren) |
{ |
return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversal::previous(previous, &base); |
@@ -362,10 +371,6 @@ inline Node* LiveNodeList::traverseToFirstElement(const ContainerNode& root) con |
switch (type()) { |
case ChildNodeListType: |
return root.firstChild(); |
- case HTMLTagNodeListType: |
- return firstMatchingElement(static_cast<const HTMLTagNodeList&>(*this), root); |
- case ClassNodeListType: |
- return firstMatchingElement(static_cast<const ClassNodeList&>(*this), root); |
default: |
return firstMatchingElement(static_cast<const LiveNodeList&>(*this), root); |
} |
@@ -378,10 +383,6 @@ inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren |
switch (type()) { |
case ChildNodeListType: |
return traverseSiblingsForwardToOffset(offset, currentNode, currentOffset); |
- case HTMLTagNodeListType: |
- return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTagNodeList&>(*this), offset, toElement(currentNode), currentOffset, root); |
- case ClassNodeListType: |
- return traverseMatchingElementsForwardToOffset(static_cast<const ClassNodeList&>(*this), offset, toElement(currentNode), currentOffset, root); |
default: |
return traverseMatchingElementsForwardToOffset(*this, offset, toElement(currentNode), currentOffset, root); |
} |