Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * Implementation of the |attributes| property of DOM Core's Element object.
9 : */
10 :
11 : #ifndef nsDOMAttributeMap_h
12 : #define nsDOMAttributeMap_h
13 :
14 : #include "mozilla/MemoryReporting.h"
15 : #include "mozilla/dom/Attr.h"
16 : #include "mozilla/ErrorResult.h"
17 : #include "nsCycleCollectionParticipant.h"
18 : #include "nsIDOMMozNamedAttrMap.h"
19 : #include "nsRefPtrHashtable.h"
20 : #include "nsString.h"
21 : #include "nsWrapperCache.h"
22 :
23 : class nsIAtom;
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, stored as void*, to make sure that we only use it
39 : * for the hashcode, and we can never dereference it.
40 : */
41 : void* mLocalName;
42 :
43 0 : nsAttrKey(int32_t aNs, nsIAtom* aName)
44 0 : : mNamespaceID(aNs), mLocalName(aName) {}
45 :
46 0 : nsAttrKey(const nsAttrKey& aAttr)
47 0 : : 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 0 : explicit nsAttrHashKey(KeyTypePointer aKey) : mKey(*aKey) {}
60 : nsAttrHashKey(const nsAttrHashKey& aCopy) : mKey(aCopy.mKey) {}
61 0 : ~nsAttrHashKey() {}
62 :
63 : KeyType GetKey() const { return mKey; }
64 0 : bool KeyEquals(KeyTypePointer aKey) const
65 : {
66 0 : return mKey.mLocalName == aKey->mLocalName &&
67 0 : mKey.mNamespaceID == aKey->mNamespaceID;
68 : }
69 :
70 0 : static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
71 0 : static PLDHashNumber HashKey(KeyTypePointer aKey)
72 : {
73 0 : if (!aKey)
74 0 : return 0;
75 :
76 0 : 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 final : 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 : explicit nsDOMAttributeMap(Element *aContent);
94 :
95 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
96 0 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsDOMAttributeMap)
97 :
98 : // nsIDOMMozNamedAttrMap interface
99 : NS_DECL_NSIDOMMOZNAMEDATTRMAP
100 :
101 : void DropReference();
102 :
103 0 : Element* GetContent()
104 : {
105 0 : return mContent;
106 : }
107 :
108 : /**
109 : * Called when mContent is moved into a new document.
110 : * Updates the nodeinfos of all owned nodes.
111 : */
112 : nsresult SetOwnerDocument(nsIDocument* aDocument);
113 :
114 : /**
115 : * Drop an attribute from the map's cache (does not remove the attribute
116 : * from the node!)
117 : */
118 : void DropAttribute(int32_t aNamespaceID, nsIAtom* aLocalName);
119 :
120 : /**
121 : * Returns the number of attribute nodes currently in the map.
122 : * Note: this is just the number of cached attribute nodes, not the number of
123 : * attributes in mContent.
124 : *
125 : * @return The number of attribute nodes in the map.
126 : */
127 : uint32_t Count() const;
128 :
129 : typedef nsRefPtrHashtable<nsAttrHashKey, Attr> AttrCache;
130 :
131 : static void BlastSubtreeToPieces(nsINode *aNode);
132 :
133 0 : Element* GetParentObject() const
134 : {
135 0 : return mContent;
136 : }
137 : virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
138 :
139 : // WebIDL
140 : Attr* GetNamedItem(const nsAString& aAttrName);
141 : Attr* NamedGetter(const nsAString& aAttrName, bool& aFound);
142 : already_AddRefed<Attr>
143 : RemoveNamedItem(mozilla::dom::NodeInfo* aNodeInfo, ErrorResult& aError);
144 : already_AddRefed<Attr>
145 : RemoveNamedItem(const nsAString& aName, ErrorResult& aError);
146 :
147 : Attr* Item(uint32_t aIndex);
148 : Attr* IndexedGetter(uint32_t aIndex, bool& aFound);
149 : uint32_t Length() const;
150 :
151 : Attr*
152 : GetNamedItemNS(const nsAString& aNamespaceURI,
153 : const nsAString& aLocalName);
154 : already_AddRefed<Attr>
155 : SetNamedItemNS(Attr& aNode, ErrorResult& aError);
156 : already_AddRefed<Attr>
157 : RemoveNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName,
158 : ErrorResult& aError);
159 :
160 : void
161 : GetSupportedNames(nsTArray<nsString>& aNames);
162 :
163 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
164 :
165 : protected:
166 : virtual ~nsDOMAttributeMap();
167 :
168 : private:
169 : nsCOMPtr<Element> mContent;
170 :
171 : /**
172 : * Cache of Attrs.
173 : */
174 : AttrCache mAttributeCache;
175 :
176 : already_AddRefed<mozilla::dom::NodeInfo>
177 : GetAttrNodeInfo(const nsAString& aNamespaceURI,
178 : const nsAString& aLocalName);
179 :
180 : Attr* GetAttribute(mozilla::dom::NodeInfo* aNodeInfo);
181 : };
182 :
183 : // XXX khuey yes this is crazy. The bindings code needs to see this include,
184 : // but if we pull it in at the top of the file we get a circular include
185 : // problem.
186 : #include "mozilla/dom/Element.h"
187 :
188 : #endif /* nsDOMAttributeMap_h */
|