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