X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fthird_party%2FWebKit%2FSource%2Fcore%2Fhtml%2FHTMLCollection.cpp;h=42f5c65f8be8be9ae8f8a78990043b065f57cb05;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=0b0bce0f17c357f35fab2f810a247c70944d8676;hpb=2f108dbacb161091e42a3479f4e171339b7e7623;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/third_party/WebKit/Source/core/html/HTMLCollection.cpp b/src/third_party/WebKit/Source/core/html/HTMLCollection.cpp index 0b0bce0..42f5c65 100644 --- a/src/third_party/WebKit/Source/core/html/HTMLCollection.cpp +++ b/src/third_party/WebKit/Source/core/html/HTMLCollection.cpp @@ -162,7 +162,6 @@ HTMLCollection::HTMLCollection(ContainerNode& ownerNode, CollectionType type, It : LiveNodeListBase(ownerNode, rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), type) , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter) , m_shouldOnlyIncludeDirectChildren(shouldTypeOnlyIncludeDirectChildren(type)) - , m_hasValidIdNameCache(false) { ScriptWrappable::init(this); } @@ -176,11 +175,9 @@ HTMLCollection::~HTMLCollection() { if (hasValidIdNameCache()) unregisterIdNameCacheFromDocument(document()); - // HTMLNameCollection, ClassCollection and TagCollection remove cache by themselves. - if (type() != WindowNamedItems && type() != DocumentNamedItems && type() != ClassCollectionType - && type() != HTMLTagCollectionType && type() != TagCollectionType) { + // Named HTMLCollection types remove cache by themselves. + if (isUnnamedHTMLCollectionType(type())) ownerNode().nodeLists()->removeCache(this, type()); - } } void HTMLCollection::invalidateCache(Document* oldDocument) const @@ -277,11 +274,6 @@ template <> inline bool isMatchingElement(const HTMLTagCollection& collection, c return collection.elementMatches(element); } -Element* HTMLCollection::itemBefore(const Element* previous) const -{ - return LiveNodeListBase::itemBefore(*this, previous); -} - Element* HTMLCollection::virtualItemAfter(Element*) const { ASSERT_NOT_REACHED(); @@ -307,14 +299,22 @@ static inline bool nameShouldBeVisibleInDocumentAll(const HTMLElement& element) || element.hasLocalName(selectTag); } -inline Element* firstMatchingChildElement(const HTMLCollection& nodeList, const ContainerNode& root) +inline Element* firstMatchingChildElement(const HTMLCollection& nodeList) { - Element* element = ElementTraversal::firstChild(root); + Element* element = ElementTraversal::firstChild(nodeList.rootNode()); while (element && !isMatchingElement(nodeList, *element)) element = ElementTraversal::nextSibling(*element); return element; } +inline Element* lastMatchingChildElement(const HTMLCollection& nodeList) +{ + Element* element = ElementTraversal::lastChild(nodeList.rootNode()); + while (element && !isMatchingElement(nodeList, *element)) + element = ElementTraversal::previousSibling(*element); + return element; +} + inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element& current) { Element* next = ¤t; @@ -324,39 +324,56 @@ inline Element* nextMatchingChildElement(const HTMLCollection& nodeList, Element return next; } -Element* HTMLCollection::traverseToFirstElement(const ContainerNode& root) const +inline Element* previousMatchingChildElement(const HTMLCollection& nodeList, Element& current) +{ + Element* previous = ¤t; + do { + previous = ElementTraversal::previousSibling(*previous); + } while (previous && !isMatchingElement(nodeList, *previous)); + return previous; +} + +Element* HTMLCollection::traverseToFirstElement() const { switch (type()) { case HTMLTagCollectionType: - return firstMatchingElement(static_cast(*this), root); + return firstMatchingElement(static_cast(*this)); case ClassCollectionType: - return firstMatchingElement(static_cast(*this), root); + return firstMatchingElement(static_cast(*this)); default: if (overridesItemAfter()) return virtualItemAfter(0); if (shouldOnlyIncludeDirectChildren()) - return firstMatchingChildElement(*this, root); - return firstMatchingElement(*this, root); + return firstMatchingChildElement(*this); + return firstMatchingElement(*this); } } -inline Element* HTMLCollection::traverseNextElement(Element& previous, const ContainerNode& root) const +Element* HTMLCollection::traverseToLastElement() const +{ + ASSERT(canTraverseBackward()); + if (shouldOnlyIncludeDirectChildren()) + return lastMatchingChildElement(*this); + return lastMatchingElement(*this); +} + +inline Element* HTMLCollection::traverseNextElement(Element& previous) const { if (overridesItemAfter()) return virtualItemAfter(&previous); if (shouldOnlyIncludeDirectChildren()) return nextMatchingChildElement(*this, previous); - return nextMatchingElement(*this, previous, root); + return nextMatchingElement(*this, previous); } -Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset, const ContainerNode& root) const +Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const { ASSERT(currentOffset < offset); switch (type()) { case HTMLTagCollectionType: - return traverseMatchingElementsForwardToOffset(static_cast(*this), offset, currentElement, currentOffset, root); + return traverseMatchingElementsForwardToOffset(static_cast(*this), offset, currentElement, currentOffset); case ClassCollectionType: - return traverseMatchingElementsForwardToOffset(static_cast(*this), offset, currentElement, currentOffset, root); + return traverseMatchingElementsForwardToOffset(static_cast(*this), offset, currentElement, currentOffset); default: if (overridesItemAfter()) { Element* next = ¤tElement; @@ -374,10 +391,25 @@ Element* HTMLCollection::traverseForwardToOffset(unsigned offset, Element& curre } return 0; } - return traverseMatchingElementsForwardToOffset(*this, offset, currentElement, currentOffset, root); + return traverseMatchingElementsForwardToOffset(*this, offset, currentElement, currentOffset); } } +Element* HTMLCollection::traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const +{ + ASSERT(currentOffset > offset); + ASSERT(canTraverseBackward()); + if (shouldOnlyIncludeDirectChildren()) { + Element* previous = ¤tElement; + while ((previous = previousMatchingChildElement(*this, *previous))) { + if (--currentOffset == offset) + return previous; + } + return 0; + } + return traverseMatchingElementsBackwardToOffset(*this, offset, currentElement, currentOffset); +} + Element* HTMLCollection::namedItem(const AtomicString& name) const { // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp @@ -387,11 +419,12 @@ Element* HTMLCollection::namedItem(const AtomicString& name) const // that are allowed a name attribute. updateIdNameCache(); - Vector* idResults = idCache(name); + const NamedItemCache& cache = namedItemCache(); + Vector* idResults = cache.getElementsById(name); if (idResults && !idResults->isEmpty()) return idResults->first(); - Vector* nameResults = nameCache(name); + Vector* nameResults = cache.getElementsByName(name); if (nameResults && !nameResults->isEmpty()) return nameResults->first(); @@ -414,8 +447,7 @@ void HTMLCollection::supportedPropertyNames(Vector& names) // nor is in result, append element's name attribute value to result. // 3. Return result. HashSet existingNames; - ContainerNode& root = rootNode(); - for (Element* element = traverseToFirstElement(root); element; element = traverseNextElement(*element, root)) { + for (Element* element = traverseToFirstElement(); element; element = traverseNextElement(*element)) { const AtomicString& idAttribute = element->getIdAttribute(); if (!idAttribute.isEmpty()) { HashSet::AddResult addResult = existingNames.add(idAttribute); @@ -443,19 +475,19 @@ void HTMLCollection::updateIdNameCache() const if (hasValidIdNameCache()) return; - ContainerNode& root = rootNode(); - for (Element* element = traverseToFirstElement(root); element; element = traverseNextElement(*element, root)) { + OwnPtr cache = NamedItemCache::create(); + for (Element* element = traverseToFirstElement(); element; element = traverseNextElement(*element)) { const AtomicString& idAttrVal = element->getIdAttribute(); if (!idAttrVal.isEmpty()) - appendIdCache(idAttrVal, element); + cache->addElementWithId(idAttrVal, element); if (!element->isHTMLElement()) continue; const AtomicString& nameAttrVal = element->getNameAttribute(); if (!nameAttrVal.isEmpty() && idAttrVal != nameAttrVal && (type() != DocAll || nameShouldBeVisibleInDocumentAll(toHTMLElement(*element)))) - appendNameCache(nameAttrVal, element); + cache->addElementWithName(nameAttrVal, element); } - - setHasValidIdNameCache(); + // Set the named item cache last as traversing the tree may cause cache invalidation. + setNamedItemCache(cache.release()); } void HTMLCollection::namedItems(const AtomicString& name, Vector >& result) const @@ -466,8 +498,9 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector updateIdNameCache(); - Vector* idResults = idCache(name); - Vector* nameResults = nameCache(name); + const NamedItemCache& cache = namedItemCache(); + Vector* idResults = cache.getElementsById(name); + Vector* nameResults = cache.getElementsByName(name); for (unsigned i = 0; idResults && i < idResults->size(); ++i) result.append(idResults->at(i)); @@ -476,12 +509,8 @@ void HTMLCollection::namedItems(const AtomicString& name, Vector result.append(nameResults->at(i)); } -void HTMLCollection::append(NodeCacheMap& map, const AtomicString& key, Element* element) +HTMLCollection::NamedItemCache::NamedItemCache() { - OwnPtr >& vector = map.add(key.impl(), nullptr).storedValue->value; - if (!vector) - vector = adoptPtr(new Vector); - vector->append(element); } } // namespace WebCore