Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
      5  * Copyright (C) 2014 Samsung Electronics. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  *
     22  */
     23 
     24 #ifndef HTMLCollection_h
     25 #define HTMLCollection_h
     26 
     27 #include "core/dom/LiveNodeListBase.h"
     28 #include "core/html/CollectionItemsCache.h"
     29 #include "core/html/CollectionType.h"
     30 #include "wtf/Forward.h"
     31 
     32 namespace blink {
     33 
     34 class HTMLCollection : public RefCountedWillBeGarbageCollectedFinalized<HTMLCollection>, public ScriptWrappable, public LiveNodeListBase {
     35     DEFINE_WRAPPERTYPEINFO();
     36     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLCollection);
     37 public:
     38     enum ItemAfterOverrideType {
     39         OverridesItemAfter,
     40         DoesNotOverrideItemAfter,
     41     };
     42 
     43     static PassRefPtrWillBeRawPtr<HTMLCollection> create(ContainerNode& base, CollectionType);
     44     virtual ~HTMLCollection();
     45     virtual void invalidateCache(Document* oldDocument = 0) const OVERRIDE;
     46     void invalidateCacheForAttribute(const QualifiedName*) const;
     47 
     48     // DOM API
     49     unsigned length() const;
     50     Element* item(unsigned offset) const;
     51     virtual Element* namedItem(const AtomicString& name) const;
     52     bool namedPropertyQuery(const AtomicString&, ExceptionState&);
     53     void namedPropertyEnumerator(Vector<String>& names, ExceptionState&);
     54 
     55     // Non-DOM API
     56     void namedItems(const AtomicString& name, WillBeHeapVector<RefPtrWillBeMember<Element> >&) const;
     57     bool isEmpty() const { return m_collectionItemsCache.isEmpty(*this); }
     58     bool hasExactlyOneItem() const { return m_collectionItemsCache.hasExactlyOneNode(*this); }
     59     bool elementMatches(const Element&) const;
     60 
     61     // CollectionIndexCache API.
     62     bool canTraverseBackward() const { return !overridesItemAfter(); }
     63     Element* traverseToFirst() const;
     64     Element* traverseToLast() const;
     65     Element* traverseForwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
     66     Element* traverseBackwardToOffset(unsigned offset, Element& currentElement, unsigned& currentOffset) const;
     67 
     68     virtual void trace(Visitor*);
     69 
     70 protected:
     71     HTMLCollection(ContainerNode& base, CollectionType, ItemAfterOverrideType);
     72 
     73     class NamedItemCache FINAL : public NoBaseWillBeGarbageCollected<NamedItemCache> {
     74     public:
     75         static PassOwnPtrWillBeRawPtr<NamedItemCache> create()
     76         {
     77             return adoptPtrWillBeNoop(new NamedItemCache);
     78         }
     79 
     80         WillBeHeapVector<RawPtrWillBeMember<Element> >* getElementsById(const AtomicString& id) const { return m_idCache.get(id.impl()); }
     81         WillBeHeapVector<RawPtrWillBeMember<Element> >* getElementsByName(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
     82         void addElementWithId(const AtomicString& id, Element* element) { addElementToMap(m_idCache, id, element); }
     83         void addElementWithName(const AtomicString& name, Element* element) { addElementToMap(m_nameCache, name, element); }
     84 
     85         void trace(Visitor* visitor)
     86         {
     87 #if ENABLE(OILPAN)
     88             visitor->trace(m_idCache);
     89             visitor->trace(m_nameCache);
     90 #endif
     91         }
     92 
     93     private:
     94         NamedItemCache();
     95         typedef WillBeHeapHashMap<StringImpl*, OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element> > > > StringToElementsMap;
     96         static void addElementToMap(StringToElementsMap& map, const AtomicString& key, Element* element)
     97         {
     98             OwnPtrWillBeMember<WillBeHeapVector<RawPtrWillBeMember<Element> > >& vector = map.add(key.impl(), nullptr).storedValue->value;
     99             if (!vector)
    100                 vector = adoptPtrWillBeNoop(new WillBeHeapVector<RawPtrWillBeMember<Element> >);
    101             vector->append(element);
    102         }
    103 
    104         StringToElementsMap m_idCache;
    105         StringToElementsMap m_nameCache;
    106     };
    107 
    108     bool overridesItemAfter() const { return m_overridesItemAfter; }
    109     virtual Element* virtualItemAfter(Element*) const;
    110     bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren; }
    111     virtual void supportedPropertyNames(Vector<String>& names);
    112 
    113     virtual void updateIdNameCache() const;
    114     bool hasValidIdNameCache() const { return m_namedItemCache; }
    115 
    116     void setNamedItemCache(PassOwnPtrWillBeRawPtr<NamedItemCache> cache) const
    117     {
    118         ASSERT(!m_namedItemCache);
    119         document().registerNodeListWithIdNameCache(this);
    120         m_namedItemCache = cache;
    121     }
    122 
    123     NamedItemCache& namedItemCache() const
    124     {
    125         ASSERT(m_namedItemCache);
    126         return *m_namedItemCache;
    127     }
    128 
    129 private:
    130     void invalidateIdNameCacheMaps(Document* oldDocument = 0) const
    131     {
    132         if (!hasValidIdNameCache())
    133             return;
    134 
    135         // Make sure we decrement the NodeListWithIdNameCache count from
    136         // the old document instead of the new one in the case the collection
    137         // is moved to a new document.
    138         unregisterIdNameCacheFromDocument(oldDocument ? *oldDocument : document());
    139 
    140         m_namedItemCache.clear();
    141     }
    142 
    143     void unregisterIdNameCacheFromDocument(Document& document) const
    144     {
    145         ASSERT(hasValidIdNameCache());
    146         document.unregisterNodeListWithIdNameCache(this);
    147     }
    148 
    149     const unsigned m_overridesItemAfter : 1;
    150     const unsigned m_shouldOnlyIncludeDirectChildren : 1;
    151     mutable OwnPtrWillBeMember<NamedItemCache> m_namedItemCache;
    152     mutable CollectionItemsCache<HTMLCollection, Element> m_collectionItemsCache;
    153 };
    154 
    155 DEFINE_TYPE_CASTS(HTMLCollection, LiveNodeListBase, collection, isHTMLCollectionType(collection->type()), isHTMLCollectionType(collection.type()));
    156 
    157 inline void HTMLCollection::invalidateCacheForAttribute(const QualifiedName* attrName) const
    158 {
    159     if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName))
    160         invalidateCache();
    161     else if (*attrName == HTMLNames::idAttr || *attrName == HTMLNames::nameAttr)
    162         invalidateIdNameCacheMaps();
    163 }
    164 
    165 } // namespace blink
    166 
    167 #endif // HTMLCollection_h
    168