Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(901)

Side by Side Diff: Source/core/html/HTMLCollection.cpp

Issue 143453010: Have getElementsByClassName() / getElementsByTagName*() return an HTMLCollection (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/html/HTMLAllCollection.idl ('k') | Source/core/html/HTMLObjectElement.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r ights reserved. 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All r ights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
11 * This library is distributed in the hope that it will be useful, 11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details. 14 * Library General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU Library General Public License 16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to 17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA. 19 * Boston, MA 02110-1301, USA.
20 * 20 *
21 */ 21 */
22 22
23 #include "config.h" 23 #include "config.h"
24 #include "core/html/HTMLCollection.h" 24 #include "core/html/HTMLCollection.h"
25 25
26 #include "HTMLNames.h" 26 #include "HTMLNames.h"
27 #include "core/dom/ClassNodeList.h" 27 #include "core/dom/ClassCollection.h"
28 #include "core/dom/ElementTraversal.h" 28 #include "core/dom/ElementTraversal.h"
29 #include "core/dom/NodeList.h" 29 #include "core/dom/NodeList.h"
30 #include "core/dom/NodeRareData.h" 30 #include "core/dom/NodeRareData.h"
31 #include "core/dom/NodeTraversal.h" 31 #include "core/dom/NodeTraversal.h"
32 #include "core/html/HTMLElement.h" 32 #include "core/html/HTMLElement.h"
33 #include "core/html/HTMLObjectElement.h" 33 #include "core/html/HTMLObjectElement.h"
34 #include "core/html/HTMLOptionElement.h" 34 #include "core/html/HTMLOptionElement.h"
35 35
36 namespace WebCore { 36 namespace WebCore {
37 37
38 using namespace HTMLNames; 38 using namespace HTMLNames;
39 39
40 static bool shouldOnlyIncludeDirectChildren(CollectionType type) 40 static bool shouldOnlyIncludeDirectChildren(CollectionType type)
41 { 41 {
42 switch (type) { 42 switch (type) {
43 case ClassCollectionType:
44 case TagCollectionType:
45 case HTMLTagCollectionType:
43 case DocAll: 46 case DocAll:
44 case DocAnchors: 47 case DocAnchors:
45 case DocApplets: 48 case DocApplets:
46 case DocEmbeds: 49 case DocEmbeds:
47 case DocForms: 50 case DocForms:
48 case DocImages: 51 case DocImages:
49 case DocLinks: 52 case DocLinks:
50 case DocScripts: 53 case DocScripts:
51 case DocumentNamedItems: 54 case DocumentNamedItems:
52 case MapAreas: 55 case MapAreas:
53 case TableRows: 56 case TableRows:
54 case SelectOptions: 57 case SelectOptions:
55 case SelectedOptions: 58 case SelectedOptions:
56 case DataListOptions: 59 case DataListOptions:
57 case WindowNamedItems: 60 case WindowNamedItems:
58 case FormControls: 61 case FormControls:
59 return false; 62 return false;
60 case NodeChildren: 63 case NodeChildren:
61 case TRCells: 64 case TRCells:
62 case TSectionRows: 65 case TSectionRows:
63 case TableTBodies: 66 case TableTBodies:
64 return true; 67 return true;
65 case ChildNodeListType: 68 case ChildNodeListType:
66 case ClassNodeListType:
67 case NameNodeListType: 69 case NameNodeListType:
68 case TagNodeListType:
69 case HTMLTagNodeListType:
70 case RadioNodeListType: 70 case RadioNodeListType:
71 case RadioImgNodeListType: 71 case RadioImgNodeListType:
72 case LabelsNodeListType: 72 case LabelsNodeListType:
73 break; 73 break;
74 } 74 }
75 ASSERT_NOT_REACHED(); 75 ASSERT_NOT_REACHED();
76 return false; 76 return false;
77 } 77 }
78 78
79 static NodeListRootType rootTypeFromCollectionType(CollectionType type) 79 static NodeListRootType rootTypeFromCollectionType(CollectionType type)
80 { 80 {
81 switch (type) { 81 switch (type) {
82 case DocImages: 82 case DocImages:
83 case DocApplets: 83 case DocApplets:
84 case DocEmbeds: 84 case DocEmbeds:
85 case DocForms: 85 case DocForms:
86 case DocLinks: 86 case DocLinks:
87 case DocAnchors: 87 case DocAnchors:
88 case DocScripts: 88 case DocScripts:
89 case DocAll: 89 case DocAll:
90 case WindowNamedItems: 90 case WindowNamedItems:
91 case DocumentNamedItems: 91 case DocumentNamedItems:
92 case FormControls: 92 case FormControls:
93 return NodeListIsRootedAtDocument; 93 return NodeListIsRootedAtDocument;
94 case ClassCollectionType:
95 case TagCollectionType:
96 case HTMLTagCollectionType:
94 case NodeChildren: 97 case NodeChildren:
95 case TableTBodies: 98 case TableTBodies:
96 case TSectionRows: 99 case TSectionRows:
97 case TableRows: 100 case TableRows:
98 case TRCells: 101 case TRCells:
99 case SelectOptions: 102 case SelectOptions:
100 case SelectedOptions: 103 case SelectedOptions:
101 case DataListOptions: 104 case DataListOptions:
102 case MapAreas: 105 case MapAreas:
103 return NodeListIsRootedAtNode; 106 return NodeListIsRootedAtNode;
104 case ChildNodeListType: 107 case ChildNodeListType:
105 case ClassNodeListType:
106 case NameNodeListType: 108 case NameNodeListType:
107 case TagNodeListType:
108 case HTMLTagNodeListType:
109 case RadioNodeListType: 109 case RadioNodeListType:
110 case RadioImgNodeListType: 110 case RadioImgNodeListType:
111 case LabelsNodeListType: 111 case LabelsNodeListType:
112 break; 112 break;
113 } 113 }
114 ASSERT_NOT_REACHED(); 114 ASSERT_NOT_REACHED();
115 return NodeListIsRootedAtNode; 115 return NodeListIsRootedAtNode;
116 } 116 }
117 117
118 static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col lectionType type) 118 static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(Col lectionType type)
119 { 119 {
120 switch (type) { 120 switch (type) {
121 case TagCollectionType:
122 case HTMLTagCollectionType:
121 case DocImages: 123 case DocImages:
122 case DocEmbeds: 124 case DocEmbeds:
123 case DocForms: 125 case DocForms:
124 case DocScripts: 126 case DocScripts:
125 case DocAll: 127 case DocAll:
126 case NodeChildren: 128 case NodeChildren:
127 case TableTBodies: 129 case TableTBodies:
128 case TSectionRows: 130 case TSectionRows:
129 case TableRows: 131 case TableRows:
130 case TRCells: 132 case TRCells:
131 case SelectOptions: 133 case SelectOptions:
132 case MapAreas: 134 case MapAreas:
133 return DoNotInvalidateOnAttributeChanges; 135 return DoNotInvalidateOnAttributeChanges;
134 case DocApplets: 136 case DocApplets:
135 case SelectedOptions: 137 case SelectedOptions:
136 case DataListOptions: 138 case DataListOptions:
137 // FIXME: We can do better some day. 139 // FIXME: We can do better some day.
138 return InvalidateOnAnyAttrChange; 140 return InvalidateOnAnyAttrChange;
139 case DocAnchors: 141 case DocAnchors:
140 return InvalidateOnNameAttrChange; 142 return InvalidateOnNameAttrChange;
141 case DocLinks: 143 case DocLinks:
142 return InvalidateOnHRefAttrChange; 144 return InvalidateOnHRefAttrChange;
143 case WindowNamedItems: 145 case WindowNamedItems:
144 return InvalidateOnIdNameAttrChange; 146 return InvalidateOnIdNameAttrChange;
145 case DocumentNamedItems: 147 case DocumentNamedItems:
146 return InvalidateOnIdNameAttrChange; 148 return InvalidateOnIdNameAttrChange;
147 case FormControls: 149 case FormControls:
148 return InvalidateForFormControls; 150 return InvalidateForFormControls;
151 case ClassCollectionType:
152 return InvalidateOnClassAttrChange;
149 case ChildNodeListType: 153 case ChildNodeListType:
150 case ClassNodeListType:
151 case NameNodeListType: 154 case NameNodeListType:
152 case TagNodeListType:
153 case HTMLTagNodeListType:
154 case RadioNodeListType: 155 case RadioNodeListType:
155 case RadioImgNodeListType: 156 case RadioImgNodeListType:
156 case LabelsNodeListType: 157 case LabelsNodeListType:
157 break; 158 break;
158 } 159 }
159 ASSERT_NOT_REACHED(); 160 ASSERT_NOT_REACHED();
160 return DoNotInvalidateOnAttributeChanges; 161 return DoNotInvalidateOnAttributeChanges;
161 } 162 }
162 163
163 HTMLCollection::HTMLCollection(ContainerNode* ownerNode, CollectionType type, It emAfterOverrideType itemAfterOverrideType) 164 HTMLCollection::HTMLCollection(ContainerNode* ownerNode, CollectionType type, It emAfterOverrideType itemAfterOverrideType)
164 : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidation TypeExcludingIdAndNameAttributes(type), 165 : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidation TypeExcludingIdAndNameAttributes(type),
165 WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideT ype) 166 WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideT ype)
166 , m_isNameCacheValid(false) 167 , m_isNameCacheValid(false)
167 { 168 {
168 ScriptWrappable::init(this); 169 ScriptWrappable::init(this);
169 } 170 }
170 171
171 PassRefPtr<HTMLCollection> HTMLCollection::create(ContainerNode* base, Collectio nType type) 172 PassRefPtr<HTMLCollection> HTMLCollection::create(ContainerNode* base, Collectio nType type)
172 { 173 {
173 return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter)); 174 return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter));
174 } 175 }
175 176
176 HTMLCollection::~HTMLCollection() 177 HTMLCollection::~HTMLCollection()
177 { 178 {
178 // HTMLNameCollection removes cache by itself. 179 // HTMLNameCollection, ClassCollection and TagCollection remove cache by the mselves.
179 if (type() != WindowNamedItems && type() != DocumentNamedItems) 180 if (type() != WindowNamedItems && type() != DocumentNamedItems && type() != ClassCollectionType
181 && type() != HTMLTagCollectionType && type() != TagCollectionType) {
180 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); 182 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type());
183 }
181 } 184 }
182 185
183 void HTMLCollection::invalidateCache() const 186 void HTMLCollection::invalidateCache() const
184 { 187 {
185 LiveNodeListBase::invalidateCache(); 188 LiveNodeListBase::invalidateCache();
186 invalidateIdNameCacheMaps(); 189 invalidateIdNameCacheMaps();
187 } 190 }
188 191
189 template <class NodeListType> 192 template <class NodeListType>
190 inline bool isMatchingElement(const NodeListType&, const Element&); 193 inline bool isMatchingElement(const NodeListType&, const Element&);
191 194
192 template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) 195 template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element)
193 { 196 {
194 CollectionType type = htmlCollection.type(); 197 CollectionType type = htmlCollection.type();
195 if (!element.isHTMLElement() && !(type == DocAll || type == NodeChildren || type == WindowNamedItems)) 198
199 // These collections apply to any kind of Elements, not just HTMLElements.
200 switch (type) {
201 case DocAll:
202 case NodeChildren:
203 return true;
204 case ClassCollectionType:
205 return static_cast<const ClassCollection&>(htmlCollection).elementMatche s(element);
206 case TagCollectionType:
207 return static_cast<const TagCollection&>(htmlCollection).elementMatches( element);
208 case HTMLTagCollectionType:
209 return static_cast<const HTMLTagCollection&>(htmlCollection).elementMatc hes(element);
210 default:
211 break;
212 }
213
214 // The following only applies to HTMLElements.
215 if (!element.isHTMLElement())
196 return false; 216 return false;
197 217
198 switch (type) { 218 switch (type) {
199 case DocImages: 219 case DocImages:
200 return element.hasLocalName(imgTag); 220 return element.hasLocalName(imgTag);
201 case DocScripts: 221 case DocScripts:
202 return element.hasLocalName(scriptTag); 222 return element.hasLocalName(scriptTag);
203 case DocForms: 223 case DocForms:
204 return element.hasLocalName(formTag); 224 return element.hasLocalName(formTag);
205 case TableTBodies: 225 case TableTBodies:
(...skipping 16 matching lines...) Expand all
222 case MapAreas: 242 case MapAreas:
223 return element.hasLocalName(areaTag); 243 return element.hasLocalName(areaTag);
224 case DocApplets: 244 case DocApplets:
225 return element.hasLocalName(appletTag) || (element.hasLocalName(objectTa g) && toHTMLObjectElement(element).containsJavaApplet()); 245 return element.hasLocalName(appletTag) || (element.hasLocalName(objectTa g) && toHTMLObjectElement(element).containsJavaApplet());
226 case DocEmbeds: 246 case DocEmbeds:
227 return element.hasLocalName(embedTag); 247 return element.hasLocalName(embedTag);
228 case DocLinks: 248 case DocLinks:
229 return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) && element.fastHasAttribute(hrefAttr); 249 return (element.hasLocalName(aTag) || element.hasLocalName(areaTag)) && element.fastHasAttribute(hrefAttr);
230 case DocAnchors: 250 case DocAnchors:
231 return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr); 251 return element.hasLocalName(aTag) && element.fastHasAttribute(nameAttr);
252 case ClassCollectionType:
253 case TagCollectionType:
254 case HTMLTagCollectionType:
232 case DocAll: 255 case DocAll:
233 case NodeChildren: 256 case NodeChildren:
234 return true;
235 case FormControls: 257 case FormControls:
236 case DocumentNamedItems: 258 case DocumentNamedItems:
237 case TableRows: 259 case TableRows:
238 case WindowNamedItems: 260 case WindowNamedItems:
239 case ChildNodeListType: 261 case ChildNodeListType:
240 case ClassNodeListType:
241 case NameNodeListType: 262 case NameNodeListType:
242 case TagNodeListType:
243 case HTMLTagNodeListType:
244 case RadioNodeListType: 263 case RadioNodeListType:
245 case RadioImgNodeListType: 264 case RadioImgNodeListType:
246 case LabelsNodeListType: 265 case LabelsNodeListType:
247 ASSERT_NOT_REACHED(); 266 ASSERT_NOT_REACHED();
248 } 267 }
249 return false; 268 return false;
250 } 269 }
251 270
252 template <> inline bool isMatchingElement(const LiveNodeList& nodeList, const El ement& element) 271 template <> inline bool isMatchingElement(const LiveNodeList& nodeList, const El ement& element)
253 { 272 {
254 return nodeList.nodeMatches(element); 273 return nodeList.nodeMatches(element);
255 } 274 }
256 275
257 template <> inline bool isMatchingElement(const HTMLTagNodeList& nodeList, const Element& element)
258 {
259 return nodeList.nodeMatchesInlined(element);
260 }
261
262 template <> inline bool isMatchingElement(const ClassNodeList& nodeList, const E lement& element)
263 {
264 return nodeList.nodeMatchesInlined(element);
265 }
266
267 static Node* previousNode(const Node& base, const Node& previous, bool onlyInclu deDirectChildren) 276 static Node* previousNode(const Node& base, const Node& previous, bool onlyInclu deDirectChildren)
268 { 277 {
269 return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversa l::previous(previous, &base); 278 return onlyIncludeDirectChildren ? previous.previousSibling() : NodeTraversa l::previous(previous, &base);
270 } 279 }
271 280
272 static inline Node* lastDescendant(const Node& node) 281 static inline Node* lastDescendant(const Node& node)
273 { 282 {
274 Node* descendant = node.lastChild(); 283 Node* descendant = node.lastChild();
275 for (Node* current = descendant; current; current = current->lastChild()) 284 for (Node* current = descendant; current; current = current->lastChild())
276 descendant = current; 285 descendant = current;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 364 }
356 365
357 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until fir stMatchingElement() 366 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until fir stMatchingElement()
358 // and others are moved to a separate header. 367 // and others are moved to a separate header.
359 inline Node* LiveNodeList::traverseToFirstElement(const ContainerNode& root) con st 368 inline Node* LiveNodeList::traverseToFirstElement(const ContainerNode& root) con st
360 { 369 {
361 ASSERT(isLiveNodeListType(type())); 370 ASSERT(isLiveNodeListType(type()));
362 switch (type()) { 371 switch (type()) {
363 case ChildNodeListType: 372 case ChildNodeListType:
364 return root.firstChild(); 373 return root.firstChild();
365 case HTMLTagNodeListType:
366 return firstMatchingElement(static_cast<const HTMLTagNodeList&>(*this), root);
367 case ClassNodeListType:
368 return firstMatchingElement(static_cast<const ClassNodeList&>(*this), ro ot);
369 default: 374 default:
370 return firstMatchingElement(static_cast<const LiveNodeList&>(*this), roo t); 375 return firstMatchingElement(static_cast<const LiveNodeList&>(*this), roo t);
371 } 376 }
372 } 377 }
373 378
374 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until tra verseMatchingElementsForwardToOffset() 379 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until tra verseMatchingElementsForwardToOffset()
375 // and others are moved to a separate header. 380 // and others are moved to a separate header.
376 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren tNode, unsigned& currentOffset, const ContainerNode& root) const 381 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren tNode, unsigned& currentOffset, const ContainerNode& root) const
377 { 382 {
378 switch (type()) { 383 switch (type()) {
379 case ChildNodeListType: 384 case ChildNodeListType:
380 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse t); 385 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse t);
381 case HTMLTagNodeListType:
382 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag NodeList&>(*this), offset, toElement(currentNode), currentOffset, root);
383 case ClassNodeListType:
384 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo deList&>(*this), offset, toElement(currentNode), currentOffset, root);
385 default: 386 default:
386 return traverseMatchingElementsForwardToOffset(*this, offset, toElement( currentNode), currentOffset, root); 387 return traverseMatchingElementsForwardToOffset(*this, offset, toElement( currentNode), currentOffset, root);
387 } 388 }
388 } 389 }
389 390
390 bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsign ed offset) const 391 bool ALWAYS_INLINE LiveNodeListBase::isLastItemCloserThanLastOrCachedItem(unsign ed offset) const
391 { 392 {
392 ASSERT(isLengthCacheValid()); 393 ASSERT(isLengthCacheValid());
393 unsigned distanceFromLastItem = cachedLength() - offset; 394 unsigned distanceFromLastItem = cachedLength() - offset;
394 if (!cachedItem()) 395 if (!cachedItem())
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 649
649 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element) 650 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element)
650 { 651 {
651 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v alue; 652 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v alue;
652 if (!vector) 653 if (!vector)
653 vector = adoptPtr(new Vector<Element*>); 654 vector = adoptPtr(new Vector<Element*>);
654 vector->append(element); 655 vector->append(element);
655 } 656 }
656 657
657 } // namespace WebCore 658 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/html/HTMLAllCollection.idl ('k') | Source/core/html/HTMLObjectElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698