Chromium Code Reviews| OLD | NEW |
|---|---|
| 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-2008, 2011, 2012, 2014 Apple Inc. All rights reserved. | 4 * Copyright (C) 2003-2008, 2011, 2012, 2014 Apple Inc. All rights reserved. |
| 5 * Copyright (C) 2014 Samsung Electronics. All rights reserved. | 5 * Copyright (C) 2014 Samsung Electronics. All rights reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 case WindowNamedItems: | 248 case WindowNamedItems: |
| 249 case NameNodeListType: | 249 case NameNodeListType: |
| 250 case RadioNodeListType: | 250 case RadioNodeListType: |
| 251 case RadioImgNodeListType: | 251 case RadioImgNodeListType: |
| 252 case LabelsNodeListType: | 252 case LabelsNodeListType: |
| 253 ASSERT_NOT_REACHED(); | 253 ASSERT_NOT_REACHED(); |
| 254 } | 254 } |
| 255 return false; | 255 return false; |
| 256 } | 256 } |
| 257 | 257 |
| 258 template <class NodeListType> | 258 inline bool HTMLCollection::elementMatches(const Element& element) const |
| 259 inline bool isMatchingElement(const NodeListType&, const Element&); | |
| 260 | |
| 261 template <> inline bool isMatchingElement(const HTMLCollection& htmlCollection, const Element& element) | |
| 262 { | 259 { |
| 263 // These collections apply to any kind of Elements, not just HTMLElements. | 260 // These collections apply to any kind of Elements, not just HTMLElements. |
| 264 switch (htmlCollection.type()) { | 261 switch (type()) { |
| 265 case DocAll: | 262 case DocAll: |
| 266 case NodeChildren: | 263 case NodeChildren: |
| 267 return true; | 264 return true; |
| 268 case ClassCollectionType: | 265 case ClassCollectionType: |
| 269 return toClassCollection(htmlCollection).elementMatches(element); | 266 return toClassCollection(*this).elementMatches(element); |
| 270 case TagCollectionType: | 267 case TagCollectionType: |
| 271 return toTagCollection(htmlCollection).elementMatches(element); | 268 return toTagCollection(*this).elementMatches(element); |
| 272 case HTMLTagCollectionType: | 269 case HTMLTagCollectionType: |
| 273 return toHTMLTagCollection(htmlCollection).elementMatches(element); | 270 return toHTMLTagCollection(*this).elementMatches(element); |
| 274 case DocumentNamedItems: | 271 case DocumentNamedItems: |
| 275 return toDocumentNameCollection(htmlCollection).elementMatches(element); | 272 return toDocumentNameCollection(*this).elementMatches(element); |
| 276 case WindowNamedItems: | 273 case WindowNamedItems: |
| 277 return toWindowNameCollection(htmlCollection).elementMatches(element); | 274 return toWindowNameCollection(*this).elementMatches(element); |
| 278 default: | 275 default: |
| 279 break; | 276 break; |
| 280 } | 277 } |
| 281 | 278 |
| 282 // The following only applies to HTMLElements. | 279 // The following only applies to HTMLElements. |
| 283 return element.isHTMLElement() && isMatchingHTMLElement(htmlCollection, toHT MLElement(element)); | 280 return element.isHTMLElement() && isMatchingHTMLElement(*this, toHTMLElement (element)); |
| 284 } | 281 } |
| 285 | 282 |
| 286 template <> inline bool isMatchingElement(const ClassCollection& collection, con st Element& element) | 283 template <class HTMLCollectionType> |
| 287 { | 284 class IsMatch { |
|
adamk
2014/08/13 20:53:55
Same with this, anonymous namespace please.
Inactive
2014/08/13 21:17:19
Done.
| |
| 288 return collection.elementMatches(element); | 285 public: |
| 289 } | 286 IsMatch(const HTMLCollectionType& list) |
| 287 : m_list(list) | |
| 288 { } | |
| 290 | 289 |
| 291 template <> inline bool isMatchingElement(const HTMLTagCollection& collection, c onst Element& element) | 290 bool operator() (const Element& element) const |
| 292 { | 291 { |
| 293 return collection.elementMatches(element); | 292 return m_list.elementMatches(element); |
| 294 } | 293 } |
| 294 | |
| 295 private: | |
| 296 const HTMLCollectionType& m_list; | |
| 297 }; | |
| 298 | |
| 299 template <class HTMLCollectionType> | |
| 300 static inline IsMatch<HTMLCollectionType> makeIsMatch(const HTMLCollectionType& list) { return IsMatch<HTMLCollectionType>(list); } | |
| 295 | 301 |
| 296 Element* HTMLCollection::virtualItemAfter(Element*) const | 302 Element* HTMLCollection::virtualItemAfter(Element*) const |
| 297 { | 303 { |
| 298 ASSERT_NOT_REACHED(); | 304 ASSERT_NOT_REACHED(); |
| 299 return 0; | 305 return 0; |
| 300 } | 306 } |
| 301 | 307 |
| 302 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) | 308 static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) |
| 303 { | 309 { |
| 304 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: | 310 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-in terfaces.html#dom-htmlallcollection-nameditem: |
| 305 // The document.all collection returns only certain types of elements by nam e, | 311 // The document.all collection returns only certain types of elements by nam e, |
| 306 // although it returns any type of element by id. | 312 // although it returns any type of element by id. |
| 307 return element.hasTagName(aTag) | 313 return element.hasTagName(aTag) |
| 308 || element.hasTagName(appletTag) | 314 || element.hasTagName(appletTag) |
| 309 || element.hasTagName(areaTag) | 315 || element.hasTagName(areaTag) |
| 310 || element.hasTagName(embedTag) | 316 || element.hasTagName(embedTag) |
| 311 || element.hasTagName(formTag) | 317 || element.hasTagName(formTag) |
| 312 || element.hasTagName(frameTag) | 318 || element.hasTagName(frameTag) |
| 313 || element.hasTagName(framesetTag) | 319 || element.hasTagName(framesetTag) |
| 314 || element.hasTagName(iframeTag) | 320 || element.hasTagName(iframeTag) |
| 315 || element.hasTagName(imgTag) | 321 || element.hasTagName(imgTag) |
| 316 || element.hasTagName(inputTag) | 322 || element.hasTagName(inputTag) |
| 317 || element.hasTagName(objectTag) | 323 || element.hasTagName(objectTag) |
| 318 || element.hasTagName(selectTag); | 324 || element.hasTagName(selectTag); |
| 319 } | 325 } |
| 320 | 326 |
| 321 inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) | |
| 322 { | |
| 323 Element* element = ElementTraversal::firstChild(nodeList.rootNode()); | |
| 324 while (element && !isMatchingElement(nodeList, *element)) | |
| 325 element = ElementTraversal::nextSibling(*element); | |
| 326 return element; | |
| 327 } | |
| 328 | |
| 329 inline Element* lastMatchingChildElement(const HTMLCollection& nodeList) | |
| 330 { | |
| 331 Element* element = ElementTraversal::lastChild(nodeList.rootNode()); | |
| 332 while (element && !isMatchingElement(nodeList, *element)) | |
| 333 element = ElementTraversal::previousSibling(*element); | |
| 334 return element; | |
| 335 } | |
| 336 | |
| 337 inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element & current) | |
| 338 { | |
| 339 Element* next = ¤t; | |
| 340 do { | |
| 341 next = ElementTraversal::nextSibling(*next); | |
| 342 } while (next && !isMatchingElement(nodeList, *next)); | |
| 343 return next; | |
| 344 } | |
| 345 | |
| 346 inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Ele ment& current) | |
| 347 { | |
| 348 Element* previous = ¤t; | |
| 349 do { | |
| 350 previous = ElementTraversal::previousSibling(*previous); | |
| 351 } while (previous && !isMatchingElement(nodeList, *previous)); | |
| 352 return previous; | |
| 353 } | |
| 354 | |
| 355 Element* HTMLCollection::traverseToFirstElement() const | 327 Element* HTMLCollection::traverseToFirstElement() const |
| 356 { | 328 { |
| 357 switch (type()) { | 329 switch (type()) { |
| 358 case HTMLTagCollectionType: | 330 case HTMLTagCollectionType: |
| 359 return firstMatchingElement(toHTMLTagCollection(*this)); | 331 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toHTMLTagCo llection(*this))); |
| 360 case ClassCollectionType: | 332 case ClassCollectionType: |
| 361 return firstMatchingElement(toClassCollection(*this)); | 333 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(toClassColl ection(*this))); |
| 362 default: | 334 default: |
| 363 if (overridesItemAfter()) | 335 if (overridesItemAfter()) |
| 364 return virtualItemAfter(0); | 336 return virtualItemAfter(0); |
| 365 if (shouldOnlyIncludeDirectChildren()) | 337 if (shouldOnlyIncludeDirectChildren()) |
| 366 return firstMatchingChildElement(*this); | 338 return ElementTraversal::firstChild(rootNode(), makeIsMatch(*this)); |
| 367 return firstMatchingElement(*this); | 339 return ElementTraversal::firstWithin(rootNode(), makeIsMatch(*this)); |
| 368 } | 340 } |
| 369 } | 341 } |
| 370 | 342 |
| 371 Element* HTMLCollection::traverseToLastElement() const | 343 Element* HTMLCollection::traverseToLastElement() const |
| 372 { | 344 { |
| 373 ASSERT(canTraverseBackward()); | 345 ASSERT(canTraverseBackward()); |
| 374 if (shouldOnlyIncludeDirectChildren()) | 346 if (shouldOnlyIncludeDirectChildren()) |
| 375 return lastMatchingChildElement(*this); | 347 return ElementTraversal::lastChild(rootNode(), makeIsMatch(*this)); |
| 376 return lastMatchingElement(*this); | 348 return ElementTraversal::lastWithin(rootNode(), makeIsMatch(*this)); |
| 377 } | 349 } |
| 378 | 350 |
| 379 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const | 351 Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre ntElement, unsigned& currentOffset) const |
| 380 { | 352 { |
| 381 ASSERT(currentOffset < offset); | 353 ASSERT(currentOffset < offset); |
| 382 switch (type()) { | 354 switch (type()) { |
| 383 case HTMLTagCollectionType: | 355 case HTMLTagCollectionType: |
| 384 return traverseMatchingElementsForwardToOffset(toHTMLTagCollection(*this ), offset, currentElement, currentOffset); | 356 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toHTMLTagCollection(*this))); |
| 385 case ClassCollectionType: | 357 case ClassCollectionType: |
| 386 return traverseMatchingElementsForwardToOffset(toClassCollection(*this), offset, currentElement, currentOffset); | 358 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(toClassCollection(*this))); |
| 387 default: | 359 default: |
| 388 if (overridesItemAfter()) { | 360 if (overridesItemAfter()) { |
| 389 for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) { | 361 for (Element* next = virtualItemAfter(¤tElement); next; next = virtualItemAfter(next)) { |
| 390 if (++currentOffset == offset) | 362 if (++currentOffset == offset) |
| 391 return next; | 363 return next; |
| 392 } | 364 } |
| 393 return 0; | 365 return 0; |
| 394 } | 366 } |
| 395 if (shouldOnlyIncludeDirectChildren()) { | 367 if (shouldOnlyIncludeDirectChildren()) { |
| 396 for (Element* next = nextMatchingChildElement(*this, currentElement) ; next; next = nextMatchingChildElement(*this, *next)) { | 368 IsMatch<HTMLCollection> isMatch(*this); |
| 369 for (Element* next = ElementTraversal::nextSibling(currentElement, i sMatch); next; next = ElementTraversal::nextSibling(*next, isMatch)) { | |
| 397 if (++currentOffset == offset) | 370 if (++currentOffset == offset) |
| 398 return next; | 371 return next; |
| 399 } | 372 } |
| 400 return 0; | 373 return 0; |
| 401 } | 374 } |
| 402 return traverseMatchingElementsForwardToOffset(*this, offset, currentEle ment, currentOffset); | 375 return traverseMatchingElementsForwardToOffset(currentElement, &rootNode (), offset, currentOffset, makeIsMatch(*this)); |
| 403 } | 376 } |
| 404 } | 377 } |
| 405 | 378 |
| 406 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const | 379 Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& curr entElement, unsigned& currentOffset) const |
| 407 { | 380 { |
| 408 ASSERT(currentOffset > offset); | 381 ASSERT(currentOffset > offset); |
| 409 ASSERT(canTraverseBackward()); | 382 ASSERT(canTraverseBackward()); |
| 410 if (shouldOnlyIncludeDirectChildren()) { | 383 if (shouldOnlyIncludeDirectChildren()) { |
| 411 for (Element* previous = previousMatchingChildElement(*this, currentElem ent); previous; previous = previousMatchingChildElement(*this, *previous)) { | 384 IsMatch<HTMLCollection> isMatch(*this); |
| 385 for (Element* previous = ElementTraversal::previousSibling(currentElemen t, isMatch); previous; previous = ElementTraversal::previousSibling(*previous, i sMatch)) { | |
| 412 if (--currentOffset == offset) | 386 if (--currentOffset == offset) |
| 413 return previous; | 387 return previous; |
| 414 } | 388 } |
| 415 return 0; | 389 return 0; |
| 416 } | 390 } |
| 417 return traverseMatchingElementsBackwardToOffset(*this, offset, currentElemen t, currentOffset); | 391 return traverseMatchingElementsBackwardToOffset(currentElement, &rootNode(), offset, currentOffset, makeIsMatch(*this)); |
| 418 } | 392 } |
| 419 | 393 |
| 420 Element* HTMLCollection::namedItem(const AtomicString& name) const | 394 Element* HTMLCollection::namedItem(const AtomicString& name) const |
| 421 { | 395 { |
| 422 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp | 396 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp |
| 423 // This method first searches for an object with a matching id | 397 // This method first searches for an object with a matching id |
| 424 // attribute. If a match is not found, the method then searches for an | 398 // attribute. If a match is not found, the method then searches for an |
| 425 // object with a matching name attribute, but only on those elements | 399 // object with a matching name attribute, but only on those elements |
| 426 // that are allowed a name attribute. | 400 // that are allowed a name attribute. |
| 427 updateIdNameCache(); | 401 updateIdNameCache(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 } | 499 } |
| 526 | 500 |
| 527 void HTMLCollection::trace(Visitor* visitor) | 501 void HTMLCollection::trace(Visitor* visitor) |
| 528 { | 502 { |
| 529 visitor->trace(m_namedItemCache); | 503 visitor->trace(m_namedItemCache); |
| 530 visitor->trace(m_collectionIndexCache); | 504 visitor->trace(m_collectionIndexCache); |
| 531 LiveNodeListBase::trace(visitor); | 505 LiveNodeListBase::trace(visitor); |
| 532 } | 506 } |
| 533 | 507 |
| 534 } // namespace blink | 508 } // namespace blink |
| OLD | NEW |