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/. */
8 * Base class for all element classes as well as nsDocumentFragment. This
9 * provides an implementation of nsINode, implements nsIContent, provides
10 * utility methods for subclasses, and so forth.
13 #ifndef FragmentOrElement_h___
14 #define FragmentOrElement_h___
16 #include "mozilla/Attributes.h"
17 #include "mozilla/EnumSet.h"
18 #include "mozilla/MemoryReporting.h"
19 #include "mozilla/UniquePtr.h"
20 #include "mozilla/dom/RadioGroupContainer.h"
21 #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
22 #include "nsIContent.h" // base class
23 #include "nsAtomHashKeys.h"
24 #include "nsIHTMLCollection.h"
25 #include "nsIWeakReferenceUtils.h"
27 class ContentUnbinder
;
29 class nsLabelsNodeList
;
30 class nsDOMAttributeMap
;
33 class nsICSSDeclaration
;
34 class nsDOMCSSAttributeDeclaration
;
39 class DeclarationBlock
;
40 enum class ContentRelevancyReason
;
41 using ContentRelevancy
= EnumSet
<ContentRelevancyReason
, uint8_t>;
42 class ElementAnimationData
;
44 struct CustomElementData
;
48 } // namespace mozilla
51 * Tearoff to use for nodes to implement nsISupportsWeakReference
53 class nsNodeSupportsWeakRefTearoff final
: public nsISupportsWeakReference
{
55 explicit nsNodeSupportsWeakRefTearoff(nsINode
* aNode
) : mNode(aNode
) {}
58 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
60 // nsISupportsWeakReference
61 NS_DECL_NSISUPPORTSWEAKREFERENCE
63 NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeSupportsWeakRefTearoff
)
66 ~nsNodeSupportsWeakRefTearoff() = default;
68 nsCOMPtr
<nsINode
> mNode
;
72 * A generic base class for DOM elements and document fragments,
73 * implementing many nsIContent, nsINode and Element methods.
75 namespace mozilla::dom
{
79 class FragmentOrElement
: public nsIContent
{
81 explicit FragmentOrElement(
82 already_AddRefed
<mozilla::dom::NodeInfo
>& aNodeInfo
);
83 explicit FragmentOrElement(
84 already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
);
86 // We want to avoid the overhead of extra function calls for
87 // refcounting when we're not doing refcount logging, so we can't
88 // NS_DECL_ISUPPORTS_INHERITED.
89 NS_IMETHOD
QueryInterface(REFNSIID aIID
, void** aInstancePtr
) override
;
90 NS_INLINE_DECL_REFCOUNTING_INHERITED(FragmentOrElement
, nsIContent
);
92 NS_DECL_ADDSIZEOFEXCLUDINGTHIS
94 // nsINode interface methods
95 virtual void GetTextContentInternal(nsAString
& aTextContent
,
96 mozilla::OOMReporter
& aError
) override
;
97 virtual void SetTextContentInternal(const nsAString
& aTextContent
,
98 nsIPrincipal
* aSubjectPrincipal
,
99 mozilla::ErrorResult
& aError
) override
;
101 // nsIContent interface methods
102 const nsTextFragment
* GetText() override
;
103 uint32_t TextLength() const override
;
104 bool TextIsOnlyWhitespace() override
;
105 bool ThreadSafeTextIsOnlyWhitespace() const override
;
107 void DestroyContent() override
;
108 void SaveSubtreeState() override
;
110 nsIHTMLCollection
* Children();
111 uint32_t ChildElementCount() {
112 if (!HasChildren()) {
115 return Children()->Length();
118 RadioGroupContainer
& OwnedRadioGroupContainer() {
119 auto* slots
= ExtendedDOMSlots();
120 if (!slots
->mRadioGroupContainer
) {
121 slots
->mRadioGroupContainer
= MakeUnique
<RadioGroupContainer
>();
123 return *slots
->mRadioGroupContainer
;
128 * If there are listeners for DOMNodeInserted event, fires the event on all
131 static void FireNodeInserted(Document
* aDoc
, nsINode
* aParent
,
132 const nsTArray
<nsCOMPtr
<nsIContent
>>& aNodes
);
134 NS_DECL_CYCLE_COLLECTION_SKIPPABLE_WRAPPERCACHE_CLASS_INHERITED(
135 FragmentOrElement
, nsIContent
)
137 static void ClearContentUnbinder();
138 static bool CanSkip(nsINode
* aNode
, bool aRemovingAllowed
);
139 static bool CanSkipInCC(nsINode
* aNode
);
140 static bool CanSkipThis(nsINode
* aNode
);
141 static void RemoveBlackMarkedNode(nsINode
* aNode
);
142 static void MarkNodeChildren(nsINode
* aNode
);
143 static void InitCCCallbacks();
146 * Is the HTML local name a void element?
148 static bool IsHTMLVoid(nsAtom
* aLocalName
);
151 virtual ~FragmentOrElement();
154 * Dummy CopyInnerTo so that we can use the same macros for
155 * Elements and DocumentFragments.
157 nsresult
CopyInnerTo(FragmentOrElement
* aDest
) { return NS_OK
; }
161 * There are a set of DOM- and scripting-specific instance variables
162 * that may only be instantiated when a content object is accessed
163 * through the DOM. Rather than burn actual slots in the content
164 * objects for each of these instance variables, we put them off
165 * in a side structure that's only allocated when the content is
166 * accessed through the DOM.
169 class nsExtendedDOMSlots
: public nsIContent::nsExtendedContentSlots
{
171 nsExtendedDOMSlots();
172 ~nsExtendedDOMSlots();
174 void TraverseExtendedSlots(nsCycleCollectionTraversalCallback
&) final
;
175 void UnlinkExtendedSlots(nsIContent
&) final
;
177 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const final
;
180 * SMIL Overridde style rules (for SMIL animation of CSS properties)
181 * @see Element::GetSMILOverrideStyle
183 RefPtr
<nsDOMCSSAttributeDeclaration
> mSMILOverrideStyle
;
186 * Holds any SMIL override style declaration for this element.
188 RefPtr
<DeclarationBlock
> mSMILOverrideStyleDeclaration
;
191 * The controllers of the XUL Element.
193 nsCOMPtr
<nsIControllers
> mControllers
;
196 * An object implementing the .labels property for this element.
198 RefPtr
<nsLabelsNodeList
> mLabelsList
;
201 * ShadowRoot bound to the element.
203 RefPtr
<ShadowRoot
> mShadowRoot
;
206 * Web components custom element data.
208 UniquePtr
<CustomElementData
> mCustomElementData
;
211 * Web animations data.
213 UniquePtr
<ElementAnimationData
> mAnimations
;
216 * PopoverData for the element.
218 UniquePtr
<PopoverData
> mPopoverData
;
221 * CustomStates for the element.
223 nsTArray
<RefPtr
<nsAtom
>> mCustomStates
;
226 * RadioGroupContainer for radio buttons grouped under this disconnected
229 UniquePtr
<RadioGroupContainer
> mRadioGroupContainer
;
232 * Last remembered size (in CSS pixels) for the element.
233 * @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered}
235 Maybe
<float> mLastRememberedBSize
;
236 Maybe
<float> mLastRememberedISize
;
239 * Whether the content of this element is relevant for the purposes
240 * of `content-visibility: auto.
241 * Reflects 'relevant to the user' concept, see
242 * https://drafts.csswg.org/css-contain/#relevant-to-the-user.
244 Maybe
<ContentRelevancy
> mContentRelevancy
;
247 * Whether the content of this element is considered visible for
248 * the purposes of `content-visibility: auto.
249 * Reflects 'proximity to the viewport' concept, see
250 * https://drafts.csswg.org/css-contain/#proximity-to-the-viewport.
252 Maybe
<bool> mVisibleForContentVisibility
;
255 * Whether content-visibility: auto is temporarily visible for
256 * the purposes of the descendant of scrollIntoView.
258 bool mTemporarilyVisibleForScrolledIntoViewDescendant
= false;
261 * Explicitly set attr-elements, see
262 * https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#explicitly-set-attr-element
264 nsTHashMap
<RefPtr
<nsAtom
>, nsWeakPtr
> mExplicitlySetAttrElements
;
267 class nsDOMSlots
: public nsIContent::nsContentSlots
{
272 void Traverse(nsCycleCollectionTraversalCallback
&) final
;
273 void Unlink(nsINode
&) final
;
275 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
) const;
278 * The .style attribute (an interface that forwards to the actual
280 * @see nsGenericHTMLElement::GetStyle
282 nsCOMPtr
<nsICSSDeclaration
> mStyle
;
285 * The .dataset attribute.
286 * @see nsGenericHTMLElement::GetDataset
288 nsDOMStringMap
* mDataset
; // [Weak]
291 * @see Element::Attributes
293 RefPtr
<nsDOMAttributeMap
> mAttributeMap
;
296 * An object implementing the .children property for this element.
298 RefPtr
<nsContentList
> mChildrenList
;
301 * An object implementing the .classList property for this element.
303 RefPtr
<nsDOMTokenList
> mClassList
;
306 * An object implementing the .part property for this element.
308 RefPtr
<nsDOMTokenList
> mPart
;
312 * In case ExtendedDOMSlots is needed before normal DOMSlots, an instance of
313 * FatSlots class, which combines those two slot types, is created.
314 * This way we can avoid extra allocation for ExtendedDOMSlots.
315 * FatSlots is useful for example when creating Custom Elements.
317 class FatSlots final
: public nsDOMSlots
, public nsExtendedDOMSlots
{
319 FatSlots() : nsDOMSlots(), nsExtendedDOMSlots() {
320 MOZ_COUNT_CTOR(FatSlots
);
321 SetExtendedContentSlots(this, false);
324 ~FatSlots() final
{ MOZ_COUNT_DTOR(FatSlots
); }
328 void GetMarkup(bool aIncludeSelf
, nsAString
& aMarkup
);
329 void SetInnerHTMLInternal(const nsAString
& aInnerHTML
, ErrorResult
& aError
);
331 // Override from nsINode
332 nsIContent::nsContentSlots
* CreateSlots() override
{
333 return new nsDOMSlots();
336 nsIContent::nsExtendedContentSlots
* CreateExtendedSlots() final
{
337 return new nsExtendedDOMSlots();
340 nsDOMSlots
* DOMSlots() { return static_cast<nsDOMSlots
*>(Slots()); }
342 nsDOMSlots
* GetExistingDOMSlots() const {
343 return static_cast<nsDOMSlots
*>(GetExistingSlots());
346 nsExtendedDOMSlots
* ExtendedDOMSlots() {
347 nsContentSlots
* slots
= GetExistingContentSlots();
349 FatSlots
* fatSlots
= new FatSlots();
354 if (!slots
->GetExtendedContentSlots()) {
355 slots
->SetExtendedContentSlots(CreateExtendedSlots(), true);
358 return static_cast<nsExtendedDOMSlots
*>(slots
->GetExtendedContentSlots());
361 const nsExtendedDOMSlots
* GetExistingExtendedDOMSlots() const {
362 return static_cast<const nsExtendedDOMSlots
*>(
363 GetExistingExtendedContentSlots());
366 nsExtendedDOMSlots
* GetExistingExtendedDOMSlots() {
367 return static_cast<nsExtendedDOMSlots
*>(GetExistingExtendedContentSlots());
370 friend class ::ContentUnbinder
;
373 } // namespace mozilla::dom
375 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE \
376 if (NS_SUCCEEDED(rv)) return rv; \
378 rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); \
379 NS_INTERFACE_TABLE_TO_MAP_SEGUE
381 #endif /* FragmentOrElement_h___ */