2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@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.
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.
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.
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.
24 #ifndef HTMLCollection_h
25 #define HTMLCollection_h
27 #include "core/CoreExport.h"
28 #include "core/dom/LiveNodeListBase.h"
29 #include "core/html/CollectionItemsCache.h"
30 #include "core/html/CollectionType.h"
31 #include "wtf/Forward.h"
35 class CORE_EXPORT HTMLCollection
: public RefCountedWillBeGarbageCollectedFinalized
<HTMLCollection
>, public ScriptWrappable
, public LiveNodeListBase
{
36 DEFINE_WRAPPERTYPEINFO();
37 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(HTMLCollection
);
39 enum ItemAfterOverrideType
{
41 DoesNotOverrideItemAfter
,
44 static PassRefPtrWillBeRawPtr
<HTMLCollection
> create(ContainerNode
& base
, CollectionType
);
45 virtual ~HTMLCollection();
46 void invalidateCache(Document
* oldDocument
= 0) const override
;
47 void invalidateCacheForAttribute(const QualifiedName
*) const;
50 unsigned length() const;
51 Element
* item(unsigned offset
) const;
52 virtual Element
* namedItem(const AtomicString
& name
) const;
53 bool namedPropertyQuery(const AtomicString
&, ExceptionState
&);
54 void namedPropertyEnumerator(Vector
<String
>& names
, ExceptionState
&);
57 void namedItems(const AtomicString
& name
, WillBeHeapVector
<RefPtrWillBeMember
<Element
>>&) const;
58 bool isEmpty() const { return m_collectionItemsCache
.isEmpty(*this); }
59 bool hasExactlyOneItem() const { return m_collectionItemsCache
.hasExactlyOneNode(*this); }
60 bool elementMatches(const Element
&) const;
62 // CollectionIndexCache API.
63 bool canTraverseBackward() const { return !overridesItemAfter(); }
64 Element
* traverseToFirst() const;
65 Element
* traverseToLast() const;
66 Element
* traverseForwardToOffset(unsigned offset
, Element
& currentElement
, unsigned& currentOffset
) const;
67 Element
* traverseBackwardToOffset(unsigned offset
, Element
& currentElement
, unsigned& currentOffset
) const;
69 DECLARE_VIRTUAL_TRACE();
72 HTMLCollection(ContainerNode
& base
, CollectionType
, ItemAfterOverrideType
);
74 class NamedItemCache final
: public NoBaseWillBeGarbageCollected
<NamedItemCache
> {
76 static PassOwnPtrWillBeRawPtr
<NamedItemCache
> create()
78 return adoptPtrWillBeNoop(new NamedItemCache
);
81 WillBeHeapVector
<RawPtrWillBeMember
<Element
>>* getElementsById(const AtomicString
& id
) const { return m_idCache
.get(id
.impl()); }
82 WillBeHeapVector
<RawPtrWillBeMember
<Element
>>* getElementsByName(const AtomicString
& name
) const { return m_nameCache
.get(name
.impl()); }
83 void addElementWithId(const AtomicString
& id
, Element
* element
) { addElementToMap(m_idCache
, id
, element
); }
84 void addElementWithName(const AtomicString
& name
, Element
* element
) { addElementToMap(m_nameCache
, name
, element
); }
89 visitor
->trace(m_idCache
);
90 visitor
->trace(m_nameCache
);
96 typedef WillBeHeapHashMap
<StringImpl
*, OwnPtrWillBeMember
<WillBeHeapVector
<RawPtrWillBeMember
<Element
>>>> StringToElementsMap
;
97 static void addElementToMap(StringToElementsMap
& map
, const AtomicString
& key
, Element
* element
)
99 OwnPtrWillBeMember
<WillBeHeapVector
<RawPtrWillBeMember
<Element
>>>& vector
= map
.add(key
.impl(), nullptr).storedValue
->value
;
101 vector
= adoptPtrWillBeNoop(new WillBeHeapVector
<RawPtrWillBeMember
<Element
>>);
102 vector
->append(element
);
105 StringToElementsMap m_idCache
;
106 StringToElementsMap m_nameCache
;
109 bool overridesItemAfter() const { return m_overridesItemAfter
; }
110 virtual Element
* virtualItemAfter(Element
*) const;
111 bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDirectChildren
; }
112 virtual void supportedPropertyNames(Vector
<String
>& names
);
114 virtual void updateIdNameCache() const;
115 bool hasValidIdNameCache() const { return m_namedItemCache
; }
117 void setNamedItemCache(PassOwnPtrWillBeRawPtr
<NamedItemCache
> cache
) const
119 ASSERT(!m_namedItemCache
);
120 document().registerNodeListWithIdNameCache(this);
121 m_namedItemCache
= cache
;
124 NamedItemCache
& namedItemCache() const
126 ASSERT(m_namedItemCache
);
127 return *m_namedItemCache
;
131 void invalidateIdNameCacheMaps(Document
* oldDocument
= 0) const
133 if (!hasValidIdNameCache())
136 // Make sure we decrement the NodeListWithIdNameCache count from
137 // the old document instead of the new one in the case the collection
138 // is moved to a new document.
139 unregisterIdNameCacheFromDocument(oldDocument
? *oldDocument
: document());
141 m_namedItemCache
.clear();
144 void unregisterIdNameCacheFromDocument(Document
& document
) const
146 ASSERT(hasValidIdNameCache());
147 document
.unregisterNodeListWithIdNameCache(this);
150 const unsigned m_overridesItemAfter
: 1;
151 const unsigned m_shouldOnlyIncludeDirectChildren
: 1;
152 mutable OwnPtrWillBeMember
<NamedItemCache
> m_namedItemCache
;
153 mutable CollectionItemsCache
<HTMLCollection
, Element
> m_collectionItemsCache
;
156 DEFINE_TYPE_CASTS(HTMLCollection
, LiveNodeListBase
, collection
, isHTMLCollectionType(collection
->type()), isHTMLCollectionType(collection
.type()));
158 inline void HTMLCollection::invalidateCacheForAttribute(const QualifiedName
* attrName
) const
160 if (!attrName
|| shouldInvalidateTypeOnAttributeChange(invalidationType(), *attrName
))
162 else if (*attrName
== HTMLNames::idAttr
|| *attrName
== HTMLNames::nameAttr
)
163 invalidateIdNameCacheMaps();
168 #endif // HTMLCollection_h