|
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 * Base class for all element classes as well as nsDocumentFragment. This |
|
8 * provides an implementation of nsIDOMNode, implements nsIContent, provides |
|
9 * utility methods for subclasses, and so forth. |
|
10 */ |
|
11 |
|
12 #ifndef FragmentOrElement_h___ |
|
13 #define FragmentOrElement_h___ |
|
14 |
|
15 #include "mozilla/Attributes.h" |
|
16 #include "mozilla/MemoryReporting.h" |
|
17 #include "nsAttrAndChildArray.h" // member |
|
18 #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_* |
|
19 #include "nsIContent.h" // base class |
|
20 #include "nsIDOMXPathNSResolver.h" // base class |
|
21 #include "nsINodeList.h" // base class |
|
22 #include "nsIWeakReference.h" // base class |
|
23 #include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl |
|
24 #include "nsIHTMLCollection.h" |
|
25 |
|
26 class ContentUnbinder; |
|
27 class nsContentList; |
|
28 class nsDOMAttributeMap; |
|
29 class nsDOMTokenList; |
|
30 class nsIControllers; |
|
31 class nsICSSDeclaration; |
|
32 class nsIDocument; |
|
33 class nsDOMStringMap; |
|
34 class nsINodeInfo; |
|
35 class nsIURI; |
|
36 |
|
37 /** |
|
38 * Class that implements the nsIDOMNodeList interface (a list of children of |
|
39 * the content), by holding a reference to the content and delegating GetLength |
|
40 * and Item to its existing child list. |
|
41 * @see nsIDOMNodeList |
|
42 */ |
|
43 class nsChildContentList MOZ_FINAL : public nsINodeList |
|
44 { |
|
45 public: |
|
46 nsChildContentList(nsINode* aNode) |
|
47 : mNode(aNode) |
|
48 { |
|
49 SetIsDOMBinding(); |
|
50 } |
|
51 |
|
52 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
53 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsChildContentList) |
|
54 |
|
55 // nsWrapperCache |
|
56 virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; |
|
57 |
|
58 // nsIDOMNodeList interface |
|
59 NS_DECL_NSIDOMNODELIST |
|
60 |
|
61 // nsINodeList interface |
|
62 virtual int32_t IndexOf(nsIContent* aContent) MOZ_OVERRIDE; |
|
63 virtual nsIContent* Item(uint32_t aIndex) MOZ_OVERRIDE; |
|
64 |
|
65 void DropReference() |
|
66 { |
|
67 mNode = nullptr; |
|
68 } |
|
69 |
|
70 virtual nsINode* GetParentObject() MOZ_OVERRIDE |
|
71 { |
|
72 return mNode; |
|
73 } |
|
74 |
|
75 private: |
|
76 // The node whose children make up the list (weak reference) |
|
77 nsINode* mNode; |
|
78 }; |
|
79 |
|
80 /** |
|
81 * A tearoff class for FragmentOrElement to implement additional interfaces |
|
82 */ |
|
83 class nsNode3Tearoff : public nsIDOMXPathNSResolver |
|
84 { |
|
85 public: |
|
86 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
87 |
|
88 NS_DECL_CYCLE_COLLECTION_CLASS(nsNode3Tearoff) |
|
89 |
|
90 NS_DECL_NSIDOMXPATHNSRESOLVER |
|
91 |
|
92 nsNode3Tearoff(nsINode *aNode) : mNode(aNode) |
|
93 { |
|
94 } |
|
95 |
|
96 protected: |
|
97 virtual ~nsNode3Tearoff() {} |
|
98 |
|
99 private: |
|
100 nsCOMPtr<nsINode> mNode; |
|
101 }; |
|
102 |
|
103 /** |
|
104 * A class that implements nsIWeakReference |
|
105 */ |
|
106 |
|
107 class nsNodeWeakReference MOZ_FINAL : public nsIWeakReference |
|
108 { |
|
109 public: |
|
110 nsNodeWeakReference(nsINode* aNode) |
|
111 : mNode(aNode) |
|
112 { |
|
113 } |
|
114 |
|
115 ~nsNodeWeakReference(); |
|
116 |
|
117 // nsISupports |
|
118 NS_DECL_ISUPPORTS |
|
119 |
|
120 // nsIWeakReference |
|
121 NS_DECL_NSIWEAKREFERENCE |
|
122 |
|
123 void NoticeNodeDestruction() |
|
124 { |
|
125 mNode = nullptr; |
|
126 } |
|
127 |
|
128 private: |
|
129 nsINode* mNode; |
|
130 }; |
|
131 |
|
132 /** |
|
133 * Tearoff to use for nodes to implement nsISupportsWeakReference |
|
134 */ |
|
135 class nsNodeSupportsWeakRefTearoff MOZ_FINAL : public nsISupportsWeakReference |
|
136 { |
|
137 public: |
|
138 nsNodeSupportsWeakRefTearoff(nsINode* aNode) |
|
139 : mNode(aNode) |
|
140 { |
|
141 } |
|
142 |
|
143 // nsISupports |
|
144 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
145 |
|
146 // nsISupportsWeakReference |
|
147 NS_DECL_NSISUPPORTSWEAKREFERENCE |
|
148 |
|
149 NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSupportsWeakRefTearoff) |
|
150 |
|
151 private: |
|
152 nsCOMPtr<nsINode> mNode; |
|
153 }; |
|
154 |
|
155 /** |
|
156 * A generic base class for DOM elements, implementing many nsIContent, |
|
157 * nsIDOMNode and nsIDOMElement methods. |
|
158 */ |
|
159 namespace mozilla { |
|
160 namespace dom { |
|
161 |
|
162 class ShadowRoot; |
|
163 class UndoManager; |
|
164 |
|
165 class FragmentOrElement : public nsIContent |
|
166 { |
|
167 public: |
|
168 FragmentOrElement(already_AddRefed<nsINodeInfo>& aNodeInfo); |
|
169 FragmentOrElement(already_AddRefed<nsINodeInfo>&& aNodeInfo); |
|
170 virtual ~FragmentOrElement(); |
|
171 |
|
172 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
173 |
|
174 NS_DECL_SIZEOF_EXCLUDING_THIS |
|
175 |
|
176 // nsINode interface methods |
|
177 virtual uint32_t GetChildCount() const MOZ_OVERRIDE; |
|
178 virtual nsIContent *GetChildAt(uint32_t aIndex) const MOZ_OVERRIDE; |
|
179 virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const MOZ_OVERRIDE; |
|
180 virtual int32_t IndexOf(const nsINode* aPossibleChild) const MOZ_OVERRIDE; |
|
181 virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, |
|
182 bool aNotify) MOZ_OVERRIDE; |
|
183 virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) MOZ_OVERRIDE; |
|
184 virtual void GetTextContentInternal(nsAString& aTextContent) MOZ_OVERRIDE; |
|
185 virtual void SetTextContentInternal(const nsAString& aTextContent, |
|
186 mozilla::ErrorResult& aError) MOZ_OVERRIDE; |
|
187 |
|
188 // nsIContent interface methods |
|
189 virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) MOZ_OVERRIDE; |
|
190 virtual const nsTextFragment *GetText() MOZ_OVERRIDE; |
|
191 virtual uint32_t TextLength() const MOZ_OVERRIDE; |
|
192 virtual nsresult SetText(const char16_t* aBuffer, uint32_t aLength, |
|
193 bool aNotify) MOZ_OVERRIDE; |
|
194 // Need to implement this here too to avoid hiding. |
|
195 nsresult SetText(const nsAString& aStr, bool aNotify) |
|
196 { |
|
197 return SetText(aStr.BeginReading(), aStr.Length(), aNotify); |
|
198 } |
|
199 virtual nsresult AppendText(const char16_t* aBuffer, uint32_t aLength, |
|
200 bool aNotify) MOZ_OVERRIDE; |
|
201 virtual bool TextIsOnlyWhitespace() MOZ_OVERRIDE; |
|
202 virtual bool HasTextForTranslation() MOZ_OVERRIDE; |
|
203 virtual void AppendTextTo(nsAString& aResult) MOZ_OVERRIDE; |
|
204 virtual bool AppendTextTo(nsAString& aResult, |
|
205 const mozilla::fallible_t&) MOZ_OVERRIDE NS_WARN_UNUSED_RESULT; |
|
206 virtual nsIContent *GetBindingParent() const MOZ_OVERRIDE; |
|
207 virtual nsXBLBinding *GetXBLBinding() const MOZ_OVERRIDE; |
|
208 virtual void SetXBLBinding(nsXBLBinding* aBinding, |
|
209 nsBindingManager* aOldBindingManager = nullptr) MOZ_OVERRIDE; |
|
210 virtual ShadowRoot *GetShadowRoot() const MOZ_OVERRIDE; |
|
211 virtual ShadowRoot *GetContainingShadow() const MOZ_OVERRIDE; |
|
212 virtual void SetShadowRoot(ShadowRoot* aBinding) MOZ_OVERRIDE; |
|
213 virtual nsIContent *GetXBLInsertionParent() const MOZ_OVERRIDE; |
|
214 virtual void SetXBLInsertionParent(nsIContent* aContent) MOZ_OVERRIDE; |
|
215 virtual bool IsLink(nsIURI** aURI) const MOZ_OVERRIDE; |
|
216 |
|
217 virtual CustomElementData *GetCustomElementData() const MOZ_OVERRIDE; |
|
218 virtual void SetCustomElementData(CustomElementData* aData) MOZ_OVERRIDE; |
|
219 |
|
220 virtual void DestroyContent() MOZ_OVERRIDE; |
|
221 virtual void SaveSubtreeState() MOZ_OVERRIDE; |
|
222 |
|
223 virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE; |
|
224 NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE; |
|
225 |
|
226 nsIHTMLCollection* Children(); |
|
227 uint32_t ChildElementCount() |
|
228 { |
|
229 return Children()->Length(); |
|
230 } |
|
231 |
|
232 public: |
|
233 /** |
|
234 * If there are listeners for DOMNodeInserted event, fires the event on all |
|
235 * aNodes |
|
236 */ |
|
237 static void FireNodeInserted(nsIDocument* aDoc, |
|
238 nsINode* aParent, |
|
239 nsTArray<nsCOMPtr<nsIContent> >& aNodes); |
|
240 |
|
241 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(FragmentOrElement) |
|
242 |
|
243 /** |
|
244 * Fire a DOMNodeRemoved mutation event for all children of this node |
|
245 */ |
|
246 void FireNodeRemovedForChildren(); |
|
247 |
|
248 virtual bool OwnedOnlyByTheDOMTree() MOZ_OVERRIDE |
|
249 { |
|
250 uint32_t rc = mRefCnt.get(); |
|
251 if (GetParent()) { |
|
252 --rc; |
|
253 } |
|
254 rc -= mAttrsAndChildren.ChildCount(); |
|
255 return rc == 0; |
|
256 } |
|
257 |
|
258 virtual bool IsPurple() MOZ_OVERRIDE |
|
259 { |
|
260 return mRefCnt.IsPurple(); |
|
261 } |
|
262 |
|
263 virtual void RemovePurple() MOZ_OVERRIDE |
|
264 { |
|
265 mRefCnt.RemovePurple(); |
|
266 } |
|
267 |
|
268 static void ClearContentUnbinder(); |
|
269 static bool CanSkip(nsINode* aNode, bool aRemovingAllowed); |
|
270 static bool CanSkipInCC(nsINode* aNode); |
|
271 static bool CanSkipThis(nsINode* aNode); |
|
272 static void RemoveBlackMarkedNode(nsINode* aNode); |
|
273 static void MarkNodeChildren(nsINode* aNode); |
|
274 static void InitCCCallbacks(); |
|
275 static void MarkUserData(void* aObject, nsIAtom* aKey, void* aChild, |
|
276 void *aData); |
|
277 static void MarkUserDataHandler(void* aObject, nsIAtom* aKey, void* aChild, |
|
278 void* aData); |
|
279 |
|
280 protected: |
|
281 /** |
|
282 * Copy attributes and state to another element |
|
283 * @param aDest the object to copy to |
|
284 */ |
|
285 nsresult CopyInnerTo(FragmentOrElement* aDest); |
|
286 |
|
287 public: |
|
288 // Because of a bug in MS C++ compiler nsDOMSlots must be declared public, |
|
289 // otherwise nsXULElement::nsXULSlots doesn't compile. |
|
290 /** |
|
291 * There are a set of DOM- and scripting-specific instance variables |
|
292 * that may only be instantiated when a content object is accessed |
|
293 * through the DOM. Rather than burn actual slots in the content |
|
294 * objects for each of these instance variables, we put them off |
|
295 * in a side structure that's only allocated when the content is |
|
296 * accessed through the DOM. |
|
297 */ |
|
298 class nsDOMSlots : public nsINode::nsSlots |
|
299 { |
|
300 public: |
|
301 nsDOMSlots(); |
|
302 virtual ~nsDOMSlots(); |
|
303 |
|
304 void Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL); |
|
305 void Unlink(bool aIsXUL); |
|
306 |
|
307 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
308 |
|
309 /** |
|
310 * The .style attribute (an interface that forwards to the actual |
|
311 * style rules) |
|
312 * @see nsGenericHTMLElement::GetStyle |
|
313 */ |
|
314 nsCOMPtr<nsICSSDeclaration> mStyle; |
|
315 |
|
316 /** |
|
317 * The .dataset attribute. |
|
318 * @see nsGenericHTMLElement::GetDataset |
|
319 */ |
|
320 nsDOMStringMap* mDataset; // [Weak] |
|
321 |
|
322 /** |
|
323 * The .undoManager property. |
|
324 * @see nsGenericHTMLElement::GetUndoManager |
|
325 */ |
|
326 nsRefPtr<UndoManager> mUndoManager; |
|
327 |
|
328 /** |
|
329 * SMIL Overridde style rules (for SMIL animation of CSS properties) |
|
330 * @see nsIContent::GetSMILOverrideStyle |
|
331 */ |
|
332 nsCOMPtr<nsICSSDeclaration> mSMILOverrideStyle; |
|
333 |
|
334 /** |
|
335 * Holds any SMIL override style rules for this element. |
|
336 */ |
|
337 nsRefPtr<mozilla::css::StyleRule> mSMILOverrideStyleRule; |
|
338 |
|
339 /** |
|
340 * An object implementing nsIDOMMozNamedAttrMap for this content (attributes) |
|
341 * @see FragmentOrElement::GetAttributes |
|
342 */ |
|
343 nsRefPtr<nsDOMAttributeMap> mAttributeMap; |
|
344 |
|
345 union { |
|
346 /** |
|
347 * The nearest enclosing content node with a binding that created us. |
|
348 * @see FragmentOrElement::GetBindingParent |
|
349 */ |
|
350 nsIContent* mBindingParent; // [Weak] |
|
351 |
|
352 /** |
|
353 * The controllers of the XUL Element. |
|
354 */ |
|
355 nsIControllers* mControllers; // [OWNER] |
|
356 }; |
|
357 |
|
358 /** |
|
359 * An object implementing the .children property for this element. |
|
360 */ |
|
361 nsRefPtr<nsContentList> mChildrenList; |
|
362 |
|
363 /** |
|
364 * An object implementing the .classList property for this element. |
|
365 */ |
|
366 nsRefPtr<nsDOMTokenList> mClassList; |
|
367 |
|
368 /** |
|
369 * ShadowRoot bound to the element. |
|
370 */ |
|
371 nsRefPtr<ShadowRoot> mShadowRoot; |
|
372 |
|
373 /** |
|
374 * The root ShadowRoot of this element if it is in a shadow tree. |
|
375 */ |
|
376 nsRefPtr<ShadowRoot> mContainingShadow; |
|
377 |
|
378 /** |
|
379 * XBL binding installed on the element. |
|
380 */ |
|
381 nsRefPtr<nsXBLBinding> mXBLBinding; |
|
382 |
|
383 /** |
|
384 * XBL binding installed on the lement. |
|
385 */ |
|
386 nsCOMPtr<nsIContent> mXBLInsertionParent; |
|
387 |
|
388 /** |
|
389 * Web components custom element data. |
|
390 */ |
|
391 nsAutoPtr<CustomElementData> mCustomElementData; |
|
392 }; |
|
393 |
|
394 protected: |
|
395 void GetMarkup(bool aIncludeSelf, nsAString& aMarkup); |
|
396 void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError); |
|
397 |
|
398 // Override from nsINode |
|
399 virtual nsINode::nsSlots* CreateSlots() MOZ_OVERRIDE; |
|
400 |
|
401 nsDOMSlots *DOMSlots() |
|
402 { |
|
403 return static_cast<nsDOMSlots*>(Slots()); |
|
404 } |
|
405 |
|
406 nsDOMSlots *GetExistingDOMSlots() const |
|
407 { |
|
408 return static_cast<nsDOMSlots*>(GetExistingSlots()); |
|
409 } |
|
410 |
|
411 friend class ::ContentUnbinder; |
|
412 /** |
|
413 * Array containing all attributes and children for this element |
|
414 */ |
|
415 nsAttrAndChildArray mAttrsAndChildren; |
|
416 }; |
|
417 |
|
418 } // namespace dom |
|
419 } // namespace mozilla |
|
420 |
|
421 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE \ |
|
422 if (NS_SUCCEEDED(rv)) \ |
|
423 return rv; \ |
|
424 \ |
|
425 rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); \ |
|
426 NS_INTERFACE_TABLE_TO_MAP_SEGUE |
|
427 |
|
428 #endif /* FragmentOrElement_h___ */ |