|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* |
|
7 * Implementation of the |attributes| property of DOM Core's Element object. |
|
8 */ |
|
9 |
|
10 #ifndef nsDOMAttributeMap_h |
|
11 #define nsDOMAttributeMap_h |
|
12 |
|
13 #include "mozilla/MemoryReporting.h" |
|
14 #include "mozilla/dom/Attr.h" |
|
15 #include "mozilla/ErrorResult.h" |
|
16 #include "nsCycleCollectionParticipant.h" |
|
17 #include "nsIDOMMozNamedAttrMap.h" |
|
18 #include "nsRefPtrHashtable.h" |
|
19 #include "nsString.h" |
|
20 #include "nsWrapperCache.h" |
|
21 |
|
22 class nsIAtom; |
|
23 class nsINodeInfo; |
|
24 class nsIDocument; |
|
25 |
|
26 /** |
|
27 * Structure used as a key for caching Attrs in nsDOMAttributeMap's mAttributeCache. |
|
28 */ |
|
29 class nsAttrKey |
|
30 { |
|
31 public: |
|
32 /** |
|
33 * The namespace of the attribute |
|
34 */ |
|
35 int32_t mNamespaceID; |
|
36 |
|
37 /** |
|
38 * The atom for attribute, weak ref. is fine as we only use it for the |
|
39 * hashcode, we never dereference it. |
|
40 */ |
|
41 nsIAtom* mLocalName; |
|
42 |
|
43 nsAttrKey(int32_t aNs, nsIAtom* aName) |
|
44 : mNamespaceID(aNs), mLocalName(aName) {} |
|
45 |
|
46 nsAttrKey(const nsAttrKey& aAttr) |
|
47 : mNamespaceID(aAttr.mNamespaceID), mLocalName(aAttr.mLocalName) {} |
|
48 }; |
|
49 |
|
50 /** |
|
51 * PLDHashEntryHdr implementation for nsAttrKey. |
|
52 */ |
|
53 class nsAttrHashKey : public PLDHashEntryHdr |
|
54 { |
|
55 public: |
|
56 typedef const nsAttrKey& KeyType; |
|
57 typedef const nsAttrKey* KeyTypePointer; |
|
58 |
|
59 nsAttrHashKey(KeyTypePointer aKey) : mKey(*aKey) {} |
|
60 nsAttrHashKey(const nsAttrHashKey& aCopy) : mKey(aCopy.mKey) {} |
|
61 ~nsAttrHashKey() {} |
|
62 |
|
63 KeyType GetKey() const { return mKey; } |
|
64 bool KeyEquals(KeyTypePointer aKey) const |
|
65 { |
|
66 return mKey.mLocalName == aKey->mLocalName && |
|
67 mKey.mNamespaceID == aKey->mNamespaceID; |
|
68 } |
|
69 |
|
70 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } |
|
71 static PLDHashNumber HashKey(KeyTypePointer aKey) |
|
72 { |
|
73 if (!aKey) |
|
74 return 0; |
|
75 |
|
76 return mozilla::HashGeneric(aKey->mNamespaceID, aKey->mLocalName); |
|
77 } |
|
78 enum { ALLOW_MEMMOVE = true }; |
|
79 |
|
80 private: |
|
81 nsAttrKey mKey; |
|
82 }; |
|
83 |
|
84 // Helper class that implements the nsIDOMMozNamedAttrMap interface. |
|
85 class nsDOMAttributeMap : public nsIDOMMozNamedAttrMap |
|
86 , public nsWrapperCache |
|
87 { |
|
88 public: |
|
89 typedef mozilla::dom::Attr Attr; |
|
90 typedef mozilla::dom::Element Element; |
|
91 typedef mozilla::ErrorResult ErrorResult; |
|
92 |
|
93 nsDOMAttributeMap(Element *aContent); |
|
94 virtual ~nsDOMAttributeMap(); |
|
95 |
|
96 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
97 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsDOMAttributeMap) |
|
98 |
|
99 // nsIDOMMozNamedAttrMap interface |
|
100 NS_DECL_NSIDOMMOZNAMEDATTRMAP |
|
101 |
|
102 void DropReference(); |
|
103 |
|
104 Element* GetContent() |
|
105 { |
|
106 return mContent; |
|
107 } |
|
108 |
|
109 /** |
|
110 * Called when mContent is moved into a new document. |
|
111 * Updates the nodeinfos of all owned nodes. |
|
112 */ |
|
113 nsresult SetOwnerDocument(nsIDocument* aDocument); |
|
114 |
|
115 /** |
|
116 * Drop an attribute from the map's cache (does not remove the attribute |
|
117 * from the node!) |
|
118 */ |
|
119 void DropAttribute(int32_t aNamespaceID, nsIAtom* aLocalName); |
|
120 |
|
121 /** |
|
122 * Returns the number of attribute nodes currently in the map. |
|
123 * Note: this is just the number of cached attribute nodes, not the number of |
|
124 * attributes in mContent. |
|
125 * |
|
126 * @return The number of attribute nodes in the map. |
|
127 */ |
|
128 uint32_t Count() const; |
|
129 |
|
130 typedef nsRefPtrHashtable<nsAttrHashKey, Attr> AttrCache; |
|
131 |
|
132 /** |
|
133 * Enumerates over the attribute nodess in the map and calls aFunc for each |
|
134 * one. If aFunc returns PL_DHASH_STOP we'll stop enumerating at that point. |
|
135 * |
|
136 * @return The number of attribute nodes that aFunc was called for. |
|
137 */ |
|
138 uint32_t Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const; |
|
139 |
|
140 Element* GetParentObject() const |
|
141 { |
|
142 return mContent; |
|
143 } |
|
144 virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
|
145 |
|
146 // WebIDL |
|
147 Attr* GetNamedItem(const nsAString& aAttrName); |
|
148 Attr* NamedGetter(const nsAString& aAttrName, bool& aFound); |
|
149 bool NameIsEnumerable(const nsAString& aName); |
|
150 already_AddRefed<Attr> |
|
151 SetNamedItem(Attr& aAttr, ErrorResult& aError) |
|
152 { |
|
153 return SetNamedItemInternal(aAttr, false, aError); |
|
154 } |
|
155 already_AddRefed<Attr> |
|
156 RemoveNamedItem(const nsAString& aName, ErrorResult& aError); |
|
157 |
|
158 Attr* Item(uint32_t aIndex); |
|
159 Attr* IndexedGetter(uint32_t aIndex, bool& aFound); |
|
160 uint32_t Length() const; |
|
161 |
|
162 Attr* |
|
163 GetNamedItemNS(const nsAString& aNamespaceURI, |
|
164 const nsAString& aLocalName); |
|
165 already_AddRefed<Attr> |
|
166 SetNamedItemNS(Attr& aNode, ErrorResult& aError) |
|
167 { |
|
168 return SetNamedItemInternal(aNode, true, aError); |
|
169 } |
|
170 already_AddRefed<Attr> |
|
171 RemoveNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, |
|
172 ErrorResult& aError); |
|
173 |
|
174 void GetSupportedNames(unsigned, nsTArray<nsString>& aNames) |
|
175 { |
|
176 // No supported names we want to show up in iteration. |
|
177 } |
|
178 |
|
179 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
180 |
|
181 private: |
|
182 nsCOMPtr<Element> mContent; |
|
183 |
|
184 /** |
|
185 * Cache of Attrs. |
|
186 */ |
|
187 AttrCache mAttributeCache; |
|
188 |
|
189 /** |
|
190 * SetNamedItem() (aWithNS = false) and SetNamedItemNS() (aWithNS = |
|
191 * true) implementation. |
|
192 */ |
|
193 already_AddRefed<Attr> |
|
194 SetNamedItemInternal(Attr& aNode, bool aWithNS, ErrorResult& aError); |
|
195 |
|
196 already_AddRefed<nsINodeInfo> |
|
197 GetAttrNodeInfo(const nsAString& aNamespaceURI, |
|
198 const nsAString& aLocalName); |
|
199 |
|
200 Attr* GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware); |
|
201 |
|
202 /** |
|
203 * Remove an attribute, returns the removed node. |
|
204 */ |
|
205 already_AddRefed<Attr> RemoveAttribute(nsINodeInfo* aNodeInfo); |
|
206 }; |
|
207 |
|
208 // XXX khuey yes this is crazy. The bindings code needs to see this include, |
|
209 // but if we pull it in at the top of the file we get a circular include |
|
210 // problem. |
|
211 #include "mozilla/dom/Element.h" |
|
212 |
|
213 #endif /* nsDOMAttributeMap_h */ |