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

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

Issue 132923003: Make sure the rootNode of a LiveNodeListBase is always a ContainerNode (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Slightly clearer cast Created 6 years, 11 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
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 *
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 case HTMLTagNodeListType: 153 case HTMLTagNodeListType:
154 case RadioNodeListType: 154 case RadioNodeListType:
155 case RadioImgNodeListType: 155 case RadioImgNodeListType:
156 case LabelsNodeListType: 156 case LabelsNodeListType:
157 break; 157 break;
158 } 158 }
159 ASSERT_NOT_REACHED(); 159 ASSERT_NOT_REACHED();
160 return DoNotInvalidateOnAttributeChanges; 160 return DoNotInvalidateOnAttributeChanges;
161 } 161 }
162 162
163 HTMLCollection::HTMLCollection(Node* ownerNode, CollectionType type, ItemAfterOv errideType itemAfterOverrideType) 163 HTMLCollection::HTMLCollection(ContainerNode* ownerNode, CollectionType type, It emAfterOverrideType itemAfterOverrideType)
164 : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidation TypeExcludingIdAndNameAttributes(type), 164 : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidation TypeExcludingIdAndNameAttributes(type),
165 WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideT ype) 165 WebCore::shouldOnlyIncludeDirectChildren(type), type, itemAfterOverrideT ype)
166 , m_isNameCacheValid(false) 166 , m_isNameCacheValid(false)
167 { 167 {
168 ScriptWrappable::init(this); 168 ScriptWrappable::init(this);
169 } 169 }
170 170
171 PassRefPtr<HTMLCollection> HTMLCollection::create(Node* base, CollectionType typ e) 171 PassRefPtr<HTMLCollection> HTMLCollection::create(ContainerNode* base, Collectio nType type)
172 { 172 {
173 return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter)); 173 return adoptRef(new HTMLCollection(base, type, DoesNotOverrideItemAfter));
174 } 174 }
175 175
176 HTMLCollection::~HTMLCollection() 176 HTMLCollection::~HTMLCollection()
177 { 177 {
178 // HTMLNameCollection removes cache by itself. 178 // HTMLNameCollection removes cache by itself.
179 if (type() != WindowNamedItems && type() != DocumentNamedItems) 179 if (type() != WindowNamedItems && type() != DocumentNamedItems)
180 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type()); 180 ownerNode()->nodeLists()->removeCacheWithAtomicName(this, type());
181 } 181 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 template <class NodeListType> 315 template <class NodeListType>
316 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode & root) 316 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode & root)
317 { 317 {
318 Element* element = ElementTraversal::firstWithin(root); 318 Element* element = ElementTraversal::firstWithin(root);
319 while (element && !isMatchingElement(nodeList, element)) 319 while (element && !isMatchingElement(nodeList, element))
320 element = ElementTraversal::next(*element, &root); 320 element = ElementTraversal::next(*element, &root);
321 return element; 321 return element;
322 } 322 }
323 323
324 template <class NodeListType> 324 template <class NodeListType>
325 inline Element* nextMatchingElement(const NodeListType* nodeList, Element& curre nt, ContainerNode* root) 325 inline Element* nextMatchingElement(const NodeListType* nodeList, Element& curre nt, ContainerNode& root)
326 { 326 {
327 Element* next = &current; 327 Element* next = &current;
328 do { 328 do {
329 next = ElementTraversal::next(*next, root); 329 next = ElementTraversal::next(*next, &root);
330 } while (next && !isMatchingElement(nodeList, next)); 330 } while (next && !isMatchingElement(nodeList, next));
331 return next; 331 return next;
332 } 332 }
333 333
334 template <class NodeListType> 334 template <class NodeListType>
335 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* node List, unsigned offset, Element& currentElement, unsigned& currentOffset, Contain erNode* root) 335 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* node List, unsigned offset, Element& currentElement, unsigned& currentOffset, Contain erNode& root)
336 { 336 {
337 ASSERT(currentOffset < offset); 337 ASSERT(currentOffset < offset);
338 Element* next = &currentElement; 338 Element* next = &currentElement;
339 while ((next = nextMatchingElement(nodeList, *next, root))) { 339 while ((next = nextMatchingElement(nodeList, *next, root))) {
340 if (++currentOffset == offset) 340 if (++currentOffset == offset)
341 return next; 341 return next;
342 } 342 }
343 return 0; 343 return 0;
344 } 344 }
345 345
(...skipping 20 matching lines...) Expand all
366 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), r oot); 366 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), r oot);
367 case ClassNodeListType: 367 case ClassNodeListType:
368 return firstMatchingElement(static_cast<const ClassNodeList*>(this), roo t); 368 return firstMatchingElement(static_cast<const ClassNodeList*>(this), roo t);
369 default: 369 default:
370 return firstMatchingElement(static_cast<const LiveNodeList*>(this), root ); 370 return firstMatchingElement(static_cast<const LiveNodeList*>(this), root );
371 } 371 }
372 } 372 }
373 373
374 // FIXME: This should be in LiveNodeList.cpp but it needs to stay here until tra verseMatchingElementsForwardToOffset() 374 // 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. 375 // and others are moved to a separate header.
376 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren tNode, unsigned& currentOffset, ContainerNode* root) const 376 inline Node* LiveNodeList::traverseForwardToOffset(unsigned offset, Node& curren tNode, unsigned& currentOffset, ContainerNode& root) const
377 { 377 {
378 switch (type()) { 378 switch (type()) {
379 case ChildNodeListType: 379 case ChildNodeListType:
380 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse t); 380 return traverseSiblingsForwardToOffset(offset, currentNode, currentOffse t);
381 case HTMLTagNodeListType: 381 case HTMLTagNodeListType:
382 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag NodeList*>(this), offset, toElement(currentNode), currentOffset, root); 382 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag NodeList*>(this), offset, toElement(currentNode), currentOffset, root);
383 case ClassNodeListType: 383 case ClassNodeListType:
384 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo deList*>(this), offset, toElement(currentNode), currentOffset, root); 384 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo deList*>(this), offset, toElement(currentNode), currentOffset, root);
385 default: 385 default:
386 return traverseMatchingElementsForwardToOffset(this, offset, toElement(c urrentNode), currentOffset, root); 386 return traverseMatchingElementsForwardToOffset(this, offset, toElement(c urrentNode), currentOffset, root);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 420
421 // FIXME: It is silly that these functions are in HTMLCollection.cpp. 421 // FIXME: It is silly that these functions are in HTMLCollection.cpp.
422 Node* LiveNodeListBase::item(unsigned offset) const 422 Node* LiveNodeListBase::item(unsigned offset) const
423 { 423 {
424 if (isItemCacheValid() && cachedItemOffset() == offset) 424 if (isItemCacheValid() && cachedItemOffset() == offset)
425 return cachedItem(); 425 return cachedItem();
426 426
427 if (isLengthCacheValid() && cachedLength() <= offset) 427 if (isLengthCacheValid() && cachedLength() <= offset)
428 return 0; 428 return 0;
429 429
430 ContainerNode* root = rootContainerNode(); 430 ContainerNode& root = rootNode();
431 if (!root) {
432 // FIMXE: In someTextNode.childNodes case the root is Text. We shouldn't even make a LiveNodeList for that.
433 setLengthCache(0);
434 return 0;
435 }
436
437 if (isLengthCacheValid() && !overridesItemAfter() && isLastItemCloserThanLas tOrCachedItem(offset)) { 431 if (isLengthCacheValid() && !overridesItemAfter() && isLastItemCloserThanLas tOrCachedItem(offset)) {
438 Node* lastItem = itemBefore(0); 432 Node* lastItem = itemBefore(0);
439 ASSERT(lastItem); 433 ASSERT(lastItem);
440 setItemCache(lastItem, cachedLength() - 1); 434 setItemCache(lastItem, cachedLength() - 1);
441 } else if (!isItemCacheValid() || isFirstItemCloserThanCachedItem(offset) || (overridesItemAfter() && offset < cachedItemOffset())) { 435 } else if (!isItemCacheValid() || isFirstItemCloserThanCachedItem(offset) || (overridesItemAfter() && offset < cachedItemOffset())) {
442 Node* firstItem; 436 Node* firstItem;
443 if (isLiveNodeListType(type())) 437 if (isLiveNodeListType(type()))
444 firstItem = static_cast<const LiveNodeList*>(this)->traverseToFirstE lement(*root); 438 firstItem = static_cast<const LiveNodeList*>(this)->traverseToFirstE lement(root);
445 else 439 else
446 firstItem = static_cast<const HTMLCollection*>(this)->traverseToFirs tElement(*root); 440 firstItem = static_cast<const HTMLCollection*>(this)->traverseToFirs tElement(root);
447 441
448 if (!firstItem) { 442 if (!firstItem) {
449 setLengthCache(0); 443 setLengthCache(0);
450 return 0; 444 return 0;
451 } 445 }
452 setItemCache(firstItem, 0); 446 setItemCache(firstItem, 0);
453 ASSERT(!cachedItemOffset()); 447 ASSERT(!cachedItemOffset());
454 } 448 }
455 449
456 if (cachedItemOffset() == offset) 450 if (cachedItemOffset() == offset)
457 return cachedItem(); 451 return cachedItem();
458 452
459 return itemBeforeOrAfterCachedItem(offset, root); 453 return itemBeforeOrAfterCachedItem(offset, root);
460 } 454 }
461 455
462 inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, Cont ainerNode* root) const 456 inline Node* LiveNodeListBase::itemBeforeOrAfterCachedItem(unsigned offset, Cont ainerNode& root) const
463 { 457 {
464 unsigned currentOffset = cachedItemOffset(); 458 unsigned currentOffset = cachedItemOffset();
465 Node* currentItem = cachedItem(); 459 Node* currentItem = cachedItem();
466 ASSERT(currentItem); 460 ASSERT(currentItem);
467 ASSERT(currentOffset != offset); 461 ASSERT(currentOffset != offset);
468 462
469 if (offset < cachedItemOffset()) { 463 if (offset < cachedItemOffset()) {
470 ASSERT(!overridesItemAfter()); 464 ASSERT(!overridesItemAfter());
471 while ((currentItem = itemBefore(currentItem))) { 465 while ((currentItem = itemBefore(currentItem))) {
472 ASSERT(currentOffset); 466 ASSERT(currentOffset);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 } 523 }
530 524
531 inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, Contai nerNode& root) 525 inline Element* firstMatchingChildElement(const HTMLCollection* nodeList, Contai nerNode& root)
532 { 526 {
533 Element* element = ElementTraversal::firstWithin(root); 527 Element* element = ElementTraversal::firstWithin(root);
534 while (element && !isMatchingElement(nodeList, element)) 528 while (element && !isMatchingElement(nodeList, element))
535 element = ElementTraversal::nextSkippingChildren(*element, &root); 529 element = ElementTraversal::nextSkippingChildren(*element, &root);
536 return element; 530 return element;
537 } 531 }
538 532
539 inline Element* nextMatchingChildElement(const HTMLCollection* nodeList, Element & current, ContainerNode* root) 533 inline Element* nextMatchingChildElement(const HTMLCollection* nodeList, Element & current, ContainerNode& root)
540 { 534 {
541 Element* next = &current; 535 Element* next = &current;
542 do { 536 do {
543 next = ElementTraversal::nextSkippingChildren(*next, root); 537 next = ElementTraversal::nextSkippingChildren(*next, &root);
544 } while (next && !isMatchingElement(nodeList, next)); 538 } while (next && !isMatchingElement(nodeList, next));
545 return next; 539 return next;
546 } 540 }
547 541
548 inline Element* HTMLCollection::traverseToFirstElement(ContainerNode& root) cons t 542 inline Element* HTMLCollection::traverseToFirstElement(ContainerNode& root) cons t
549 { 543 {
550 if (overridesItemAfter()) 544 if (overridesItemAfter())
551 return virtualItemAfter(0); 545 return virtualItemAfter(0);
552 if (shouldOnlyIncludeDirectChildren()) 546 if (shouldOnlyIncludeDirectChildren())
553 return firstMatchingChildElement(static_cast<const HTMLCollection*>(this ), root); 547 return firstMatchingChildElement(static_cast<const HTMLCollection*>(this ), root);
554 return firstMatchingElement(static_cast<const HTMLCollection*>(this), root); 548 return firstMatchingElement(static_cast<const HTMLCollection*>(this), root);
555 } 549 }
556 550
557 inline Element* HTMLCollection::traverseNextElement(Element& previous, Container Node* root) const 551 inline Element* HTMLCollection::traverseNextElement(Element& previous, Container Node& root) const
558 { 552 {
559 if (overridesItemAfter()) 553 if (overridesItemAfter())
560 return virtualItemAfter(&previous); 554 return virtualItemAfter(&previous);
561 if (shouldOnlyIncludeDirectChildren()) 555 if (shouldOnlyIncludeDirectChildren())
562 return nextMatchingChildElement(this, previous, root); 556 return nextMatchingChildElement(this, previous, root);
563 return nextMatchingElement(this, previous, root); 557 return nextMatchingElement(this, previous, root);
564 } 558 }
565 559
566 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element & currentElement, unsigned& currentOffset, ContainerNode* root) const 560 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element & currentElement, unsigned& currentOffset, ContainerNode& root) const
567 { 561 {
568 ASSERT(currentOffset < offset); 562 ASSERT(currentOffset < offset);
569 if (overridesItemAfter()) { 563 if (overridesItemAfter()) {
570 Element* next = &currentElement; 564 Element* next = &currentElement;
571 while ((next = virtualItemAfter(next))) { 565 while ((next = virtualItemAfter(next))) {
572 if (++currentOffset == offset) 566 if (++currentOffset == offset)
573 return next; 567 return next;
574 } 568 }
575 return 0; 569 return 0;
576 } 570 }
577 if (shouldOnlyIncludeDirectChildren()) { 571 if (shouldOnlyIncludeDirectChildren()) {
578 Element* next = &currentElement; 572 Element* next = &currentElement;
579 while ((next = nextMatchingChildElement(this, *next, root))) { 573 while ((next = nextMatchingChildElement(this, *next, root))) {
580 if (++currentOffset == offset) 574 if (++currentOffset == offset)
581 return next; 575 return next;
582 } 576 }
583 return 0; 577 return 0;
584 } 578 }
585 return traverseMatchingElementsForwardToOffset(this, offset, currentElement, currentOffset, root); 579 return traverseMatchingElementsForwardToOffset(this, offset, currentElement, currentOffset, root);
586 } 580 }
587 581
588 Node* HTMLCollection::namedItem(const AtomicString& name) const 582 Node* HTMLCollection::namedItem(const AtomicString& name) const
589 { 583 {
590 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp 584 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit em.asp
591 // This method first searches for an object with a matching id 585 // This method first searches for an object with a matching id
592 // attribute. If a match is not found, the method then searches for an 586 // attribute. If a match is not found, the method then searches for an
593 // object with a matching name attribute, but only on those elements 587 // object with a matching name attribute, but only on those elements
594 // that are allowed a name attribute. 588 // that are allowed a name attribute.
595 589
596 ContainerNode* root = rootContainerNode(); 590 ContainerNode& root = rootNode();
597 if (!root)
598 return 0;
599
600 unsigned i = 0; 591 unsigned i = 0;
601 for (Element* element = traverseToFirstElement(*root); element; element = tr averseNextElement(*element, root)) { 592 for (Element* element = traverseToFirstElement(root); element; element = tra verseNextElement(*element, root)) {
602 if (checkForNameMatch(element, /* checkName */ false, name)) { 593 if (checkForNameMatch(element, /* checkName */ false, name)) {
603 setItemCache(element, i); 594 setItemCache(element, i);
604 return element; 595 return element;
605 } 596 }
606 i++; 597 i++;
607 } 598 }
608 599
609 i = 0; 600 i = 0;
610 for (Element* element = traverseToFirstElement(*root); element; element = tr averseNextElement(*element, root)) { 601 for (Element* element = traverseToFirstElement(root); element; element = tra verseNextElement(*element, root)) {
611 if (checkForNameMatch(element, /* checkName */ true, name)) { 602 if (checkForNameMatch(element, /* checkName */ true, name)) {
612 setItemCache(element, i); 603 setItemCache(element, i);
613 return element; 604 return element;
614 } 605 }
615 i++; 606 i++;
616 } 607 }
617 608
618 return 0; 609 return 0;
619 } 610 }
620 611
621 void HTMLCollection::updateNameCache() const 612 void HTMLCollection::updateNameCache() const
622 { 613 {
623 if (hasNameCache()) 614 if (hasNameCache())
624 return; 615 return;
625 616
626 ContainerNode* root = rootContainerNode(); 617 ContainerNode& root = rootNode();
627 if (!root) 618 for (Element* element = traverseToFirstElement(root); element; element = tra verseNextElement(*element, root)) {
628 return;
629
630 for (Element* element = traverseToFirstElement(*root); element; element = tr averseNextElement(*element, root)) {
631 const AtomicString& idAttrVal = element->getIdAttribute(); 619 const AtomicString& idAttrVal = element->getIdAttribute();
632 if (!idAttrVal.isEmpty()) 620 if (!idAttrVal.isEmpty())
633 appendIdCache(idAttrVal, element); 621 appendIdCache(idAttrVal, element);
634 if (!element->isHTMLElement()) 622 if (!element->isHTMLElement())
635 continue; 623 continue;
636 const AtomicString& nameAttrVal = element->getNameAttribute(); 624 const AtomicString& nameAttrVal = element->getNameAttribute();
637 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc All || nameShouldBeVisibleInDocumentAll(toHTMLElement(element)))) 625 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc All || nameShouldBeVisibleInDocumentAll(toHTMLElement(element))))
638 appendNameCache(nameAttrVal, element); 626 appendNameCache(nameAttrVal, element);
639 } 627 }
640 628
(...skipping 20 matching lines...) Expand all
661 649
662 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element) 650 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element)
663 { 651 {
664 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;
665 if (!vector) 653 if (!vector)
666 vector = adoptPtr(new Vector<Element*>); 654 vector = adoptPtr(new Vector<Element*>);
667 vector->append(element); 655 vector->append(element);
668 } 656 }
669 657
670 } // namespace WebCore 658 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698