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 |