| 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, 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 if (type() == ChildNodeListType) | 299 if (type() == ChildNodeListType) |
| 300 return current; | 300 return current; |
| 301 return iterateForPreviousNode(current); | 301 return iterateForPreviousNode(current); |
| 302 } | 302 } |
| 303 | 303 |
| 304 template <class NodeListType> | 304 template <class NodeListType> |
| 305 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode
* root) | 305 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode
* root) |
| 306 { | 306 { |
| 307 Element* element = ElementTraversal::firstWithin(root); | 307 Element* element = ElementTraversal::firstWithin(root); |
| 308 while (element && !isMatchingElement(nodeList, element)) | 308 while (element && !isMatchingElement(nodeList, element)) |
| 309 element = ElementTraversal::next(element, root); | 309 element = ElementTraversal::next(*element, root); |
| 310 return element; | 310 return element; |
| 311 } | 311 } |
| 312 | 312 |
| 313 template <class NodeListType> | 313 template <class NodeListType> |
| 314 inline Element* nextMatchingElement(const NodeListType* nodeList, Element* curre
nt, ContainerNode* root) | 314 inline Element* nextMatchingElement(const NodeListType* nodeList, Element& curre
nt, ContainerNode* root) |
| 315 { | 315 { |
| 316 Element* next = ¤t; |
| 316 do { | 317 do { |
| 317 current = ElementTraversal::next(current, root); | 318 next = ElementTraversal::next(*next, root); |
| 318 } while (current && !isMatchingElement(nodeList, current)); | 319 } while (next && !isMatchingElement(nodeList, next)); |
| 319 return current; | 320 return next; |
| 320 } | 321 } |
| 321 | 322 |
| 322 template <class NodeListType> | 323 template <class NodeListType> |
| 323 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* node
List, unsigned offset, Element* currentElement, unsigned& currentOffset, Contain
erNode* root) | 324 inline Element* traverseMatchingElementsForwardToOffset(const NodeListType* node
List, unsigned offset, Element& currentElement, unsigned& currentOffset, Contain
erNode* root) |
| 324 { | 325 { |
| 325 ASSERT(currentOffset < offset); | 326 ASSERT(currentOffset < offset); |
| 326 while ((currentElement = nextMatchingElement(nodeList, currentElement, root)
)) { | 327 Element* next = ¤tElement; |
| 328 while ((next = nextMatchingElement(nodeList, *next, root))) { |
| 327 if (++currentOffset == offset) | 329 if (++currentOffset == offset) |
| 328 return currentElement; | 330 return next; |
| 329 } | 331 } |
| 330 return 0; | 332 return 0; |
| 331 } | 333 } |
| 332 | 334 |
| 333 // FIXME: This should be in ChildNodeList | 335 // FIXME: This should be in ChildNodeList |
| 334 inline Node* LiveNodeListBase::traverseChildNodeListForwardToOffset(unsigned off
set, Node* currentNode, unsigned& currentOffset) const | 336 inline Node* LiveNodeListBase::traverseChildNodeListForwardToOffset(unsigned off
set, Node* currentNode, unsigned& currentOffset) const |
| 335 { | 337 { |
| 336 ASSERT(type() == ChildNodeListType); | 338 ASSERT(type() == ChildNodeListType); |
| 337 ASSERT(currentOffset < offset); | 339 ASSERT(currentOffset < offset); |
| 338 while ((currentNode = currentNode->nextSibling())) { | 340 while ((currentNode = currentNode->nextSibling())) { |
| 339 if (++currentOffset == offset) | 341 if (++currentOffset == offset) |
| 340 return currentNode; | 342 return currentNode; |
| 341 } | 343 } |
| 342 return 0; | 344 return 0; |
| 343 } | 345 } |
| 344 | 346 |
| 345 // FIXME: This should be in LiveNodeList | 347 // FIXME: This should be in LiveNodeList |
| 346 inline Element* LiveNodeListBase::traverseLiveNodeListFirstElement(ContainerNode
* root) const | 348 inline Element* LiveNodeListBase::traverseLiveNodeListFirstElement(ContainerNode
* root) const |
| 347 { | 349 { |
| 348 ASSERT(isNodeList(type())); | 350 ASSERT(isNodeList(type())); |
| 349 ASSERT(type() != ChildNodeListType); | 351 ASSERT(type() != ChildNodeListType); |
| 350 if (type() == HTMLTagNodeListType) | 352 if (type() == HTMLTagNodeListType) |
| 351 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), r
oot); | 353 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), r
oot); |
| 352 if (type() == ClassNodeListType) | 354 if (type() == ClassNodeListType) |
| 353 return firstMatchingElement(static_cast<const ClassNodeList*>(this), roo
t); | 355 return firstMatchingElement(static_cast<const ClassNodeList*>(this), roo
t); |
| 354 return firstMatchingElement(static_cast<const LiveNodeList*>(this), root); | 356 return firstMatchingElement(static_cast<const LiveNodeList*>(this), root); |
| 355 } | 357 } |
| 356 | 358 |
| 357 // FIXME: This should be in LiveNodeList | 359 // FIXME: This should be in LiveNodeList |
| 358 inline Element* LiveNodeListBase::traverseLiveNodeListForwardToOffset(unsigned o
ffset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) co
nst | 360 inline Element* LiveNodeListBase::traverseLiveNodeListForwardToOffset(unsigned o
ffset, Element& currentElement, unsigned& currentOffset, ContainerNode* root) co
nst |
| 359 { | 361 { |
| 360 ASSERT(isNodeList(type())); | 362 ASSERT(isNodeList(type())); |
| 361 ASSERT(type() != ChildNodeListType); | 363 ASSERT(type() != ChildNodeListType); |
| 362 if (type() == HTMLTagNodeListType) | 364 if (type() == HTMLTagNodeListType) |
| 363 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
NodeList*>(this), offset, currentElement, currentOffset, root); | 365 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTag
NodeList*>(this), offset, currentElement, currentOffset, root); |
| 364 if (type() == ClassNodeListType) | 366 if (type() == ClassNodeListType) |
| 365 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo
deList*>(this), offset, currentElement, currentOffset, root); | 367 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNo
deList*>(this), offset, currentElement, currentOffset, root); |
| 366 return traverseMatchingElementsForwardToOffset(static_cast<const LiveNodeLis
t*>(this), offset, currentElement, currentOffset, root); | 368 return traverseMatchingElementsForwardToOffset(static_cast<const LiveNodeLis
t*>(this), offset, currentElement, currentOffset, root); |
| 367 } | 369 } |
| 368 | 370 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 } | 471 } |
| 470 } | 472 } |
| 471 ASSERT_NOT_REACHED(); | 473 ASSERT_NOT_REACHED(); |
| 472 return 0; | 474 return 0; |
| 473 } | 475 } |
| 474 | 476 |
| 475 unsigned offsetInArray = 0; | 477 unsigned offsetInArray = 0; |
| 476 if (type() == ChildNodeListType) | 478 if (type() == ChildNodeListType) |
| 477 currentItem = traverseChildNodeListForwardToOffset(offset, currentItem,
currentOffset); | 479 currentItem = traverseChildNodeListForwardToOffset(offset, currentItem,
currentOffset); |
| 478 else if (isNodeList(type())) | 480 else if (isNodeList(type())) |
| 479 currentItem = traverseLiveNodeListForwardToOffset(offset, toElement(curr
entItem), currentOffset, root); | 481 currentItem = traverseLiveNodeListForwardToOffset(offset, toElement(*cur
rentItem), currentOffset, root); |
| 480 else | 482 else |
| 481 currentItem = static_cast<const HTMLCollection*>(this)->traverseForwardT
oOffset(offset, toElement(currentItem), currentOffset, offsetInArray, root); | 483 currentItem = static_cast<const HTMLCollection*>(this)->traverseForwardT
oOffset(offset, toElement(*currentItem), currentOffset, offsetInArray, root); |
| 482 | 484 |
| 483 if (!currentItem) { | 485 if (!currentItem) { |
| 484 // Did not find the item. On plus side, we now know the length. | 486 // Did not find the item. On plus side, we now know the length. |
| 485 setLengthCache(currentOffset + 1); | 487 setLengthCache(currentOffset + 1); |
| 486 return 0; | 488 return 0; |
| 487 } | 489 } |
| 488 setItemCache(currentItem, currentOffset, offsetInArray); | 490 setItemCache(currentItem, currentOffset, offsetInArray); |
| 489 return currentItem; | 491 return currentItem; |
| 490 } | 492 } |
| 491 | 493 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 inline Element* HTMLCollection::traverseFirstElement(unsigned& offsetInArray, Co
ntainerNode* root) const | 544 inline Element* HTMLCollection::traverseFirstElement(unsigned& offsetInArray, Co
ntainerNode* root) const |
| 543 { | 545 { |
| 544 if (overridesItemAfter()) | 546 if (overridesItemAfter()) |
| 545 return virtualItemAfter(offsetInArray, 0); | 547 return virtualItemAfter(offsetInArray, 0); |
| 546 ASSERT(!offsetInArray); | 548 ASSERT(!offsetInArray); |
| 547 if (shouldOnlyIncludeDirectChildren()) | 549 if (shouldOnlyIncludeDirectChildren()) |
| 548 return firstMatchingChildElement(static_cast<const HTMLCollection*>(this
), root); | 550 return firstMatchingChildElement(static_cast<const HTMLCollection*>(this
), root); |
| 549 return firstMatchingElement(static_cast<const HTMLCollection*>(this), root); | 551 return firstMatchingElement(static_cast<const HTMLCollection*>(this), root); |
| 550 } | 552 } |
| 551 | 553 |
| 552 inline Element* HTMLCollection::traverseNextElement(unsigned& offsetInArray, Ele
ment* previous, ContainerNode* root) const | 554 inline Element* HTMLCollection::traverseNextElement(unsigned& offsetInArray, Ele
ment& previous, ContainerNode* root) const |
| 553 { | 555 { |
| 554 if (overridesItemAfter()) | 556 if (overridesItemAfter()) |
| 555 return virtualItemAfter(offsetInArray, previous); | 557 return virtualItemAfter(offsetInArray, &previous); |
| 556 ASSERT(!offsetInArray); | 558 ASSERT(!offsetInArray); |
| 557 if (shouldOnlyIncludeDirectChildren()) | 559 if (shouldOnlyIncludeDirectChildren()) |
| 558 return nextMatchingChildElement(this, previous, root); | 560 return nextMatchingChildElement(this, &previous, root); |
| 559 return nextMatchingElement(this, previous, root); | 561 return nextMatchingElement(this, previous, root); |
| 560 } | 562 } |
| 561 | 563 |
| 562 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element
* currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNod
e* root) const | 564 inline Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element
& currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNod
e* root) const |
| 563 { | 565 { |
| 564 ASSERT(currentOffset < offset); | 566 ASSERT(currentOffset < offset); |
| 565 if (overridesItemAfter()) { | 567 if (overridesItemAfter()) { |
| 566 offsetInArray = m_cachedElementsArrayOffset; | 568 offsetInArray = m_cachedElementsArrayOffset; |
| 567 while ((currentElement = virtualItemAfter(offsetInArray, currentElement)
)) { | 569 Element* next = ¤tElement; |
| 570 while ((next = virtualItemAfter(offsetInArray, next))) { |
| 568 if (++currentOffset == offset) | 571 if (++currentOffset == offset) |
| 569 return currentElement; | 572 return next; |
| 570 } | 573 } |
| 571 return 0; | 574 return 0; |
| 572 } | 575 } |
| 573 if (shouldOnlyIncludeDirectChildren()) { | 576 if (shouldOnlyIncludeDirectChildren()) { |
| 574 while ((currentElement = nextMatchingChildElement(this, currentElement,
root))) { | 577 Element* next = ¤tElement; |
| 578 while ((next = nextMatchingChildElement(this, next, root))) { |
| 575 if (++currentOffset == offset) | 579 if (++currentOffset == offset) |
| 576 return currentElement; | 580 return next; |
| 577 } | 581 } |
| 578 return 0; | 582 return 0; |
| 579 } | 583 } |
| 580 return traverseMatchingElementsForwardToOffset(this, offset, currentElement,
currentOffset, root); | 584 return traverseMatchingElementsForwardToOffset(this, offset, currentElement,
currentOffset, root); |
| 581 } | 585 } |
| 582 | 586 |
| 583 Node* HTMLCollection::namedItem(const AtomicString& name) const | 587 Node* HTMLCollection::namedItem(const AtomicString& name) const |
| 584 { | 588 { |
| 585 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp | 589 // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/namedit
em.asp |
| 586 // This method first searches for an object with a matching id | 590 // This method first searches for an object with a matching id |
| 587 // attribute. If a match is not found, the method then searches for an | 591 // attribute. If a match is not found, the method then searches for an |
| 588 // object with a matching name attribute, but only on those elements | 592 // object with a matching name attribute, but only on those elements |
| 589 // that are allowed a name attribute. | 593 // that are allowed a name attribute. |
| 590 | 594 |
| 591 ContainerNode* root = rootContainerNode(); | 595 ContainerNode* root = rootContainerNode(); |
| 592 if (!root) | 596 if (!root) |
| 593 return 0; | 597 return 0; |
| 594 | 598 |
| 595 unsigned arrayOffset = 0; | 599 unsigned arrayOffset = 0; |
| 596 unsigned i = 0; | 600 unsigned i = 0; |
| 597 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, element, root)) { | 601 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, *element, root)) { |
| 598 if (checkForNameMatch(element, /* checkName */ false, name)) { | 602 if (checkForNameMatch(element, /* checkName */ false, name)) { |
| 599 setItemCache(element, i, arrayOffset); | 603 setItemCache(element, i, arrayOffset); |
| 600 return element; | 604 return element; |
| 601 } | 605 } |
| 602 i++; | 606 i++; |
| 603 } | 607 } |
| 604 | 608 |
| 605 i = 0; | 609 i = 0; |
| 606 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, element, root)) { | 610 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, *element, root)) { |
| 607 if (checkForNameMatch(element, /* checkName */ true, name)) { | 611 if (checkForNameMatch(element, /* checkName */ true, name)) { |
| 608 setItemCache(element, i, arrayOffset); | 612 setItemCache(element, i, arrayOffset); |
| 609 return element; | 613 return element; |
| 610 } | 614 } |
| 611 i++; | 615 i++; |
| 612 } | 616 } |
| 613 | 617 |
| 614 return 0; | 618 return 0; |
| 615 } | 619 } |
| 616 | 620 |
| 617 void HTMLCollection::updateNameCache() const | 621 void HTMLCollection::updateNameCache() const |
| 618 { | 622 { |
| 619 if (hasNameCache()) | 623 if (hasNameCache()) |
| 620 return; | 624 return; |
| 621 | 625 |
| 622 ContainerNode* root = rootContainerNode(); | 626 ContainerNode* root = rootContainerNode(); |
| 623 if (!root) | 627 if (!root) |
| 624 return; | 628 return; |
| 625 | 629 |
| 626 unsigned arrayOffset = 0; | 630 unsigned arrayOffset = 0; |
| 627 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, element, root)) { | 631 for (Element* element = traverseFirstElement(arrayOffset, root); element; el
ement = traverseNextElement(arrayOffset, *element, root)) { |
| 628 const AtomicString& idAttrVal = element->getIdAttribute(); | 632 const AtomicString& idAttrVal = element->getIdAttribute(); |
| 629 if (!idAttrVal.isEmpty()) | 633 if (!idAttrVal.isEmpty()) |
| 630 appendIdCache(idAttrVal, element); | 634 appendIdCache(idAttrVal, element); |
| 631 if (!element->isHTMLElement()) | 635 if (!element->isHTMLElement()) |
| 632 continue; | 636 continue; |
| 633 const AtomicString& nameAttrVal = element->getNameAttribute(); | 637 const AtomicString& nameAttrVal = element->getNameAttribute(); |
| 634 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(element)))) | 638 if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != Doc
All || nameShouldBeVisibleInDocumentAll(toHTMLElement(element)))) |
| 635 appendNameCache(nameAttrVal, element); | 639 appendNameCache(nameAttrVal, element); |
| 636 } | 640 } |
| 637 | 641 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 | 682 |
| 679 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element*
element) | 683 void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element*
element) |
| 680 { | 684 { |
| 681 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v
alue; | 685 OwnPtr<Vector<Element*> >& vector = map.add(key.impl(), nullptr).iterator->v
alue; |
| 682 if (!vector) | 686 if (!vector) |
| 683 vector = adoptPtr(new Vector<Element*>); | 687 vector = adoptPtr(new Vector<Element*>); |
| 684 vector->append(element); | 688 vector->append(element); |
| 685 } | 689 } |
| 686 | 690 |
| 687 } // namespace WebCore | 691 } // namespace WebCore |
| OLD | NEW |