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/. */
7 #ifndef nsIMutationObserver_h
8 #define nsIMutationObserver_h
10 #include "nsISupports.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/DoublyLinkedList.h"
19 struct BatchRemovalState
;
21 namespace mozilla::dom
{
23 } // namespace mozilla::dom
25 #define NS_IMUTATION_OBSERVER_IID \
26 {0x6d674c17, 0x0fbc, 0x4633, {0x8f, 0x46, 0x73, 0x4e, 0x87, 0xeb, 0xf0, 0xc7}}
29 * Information details about a characterdata change. Basically, we
30 * view all changes as replacements of a length of text at some offset
31 * with some other text (of possibly some other length).
33 struct CharacterDataChangeInfo
{
35 * True if this character data change is just an append.
40 * The offset in the text where the change occurred.
42 uint32_t mChangeStart
;
45 * The offset such that mChangeEnd - mChangeStart is equal to the length of
46 * the text we removed. If this was a pure insert, append or a result of
47 * `splitText()` this is equal to mChangeStart.
51 uint32_t LengthOfRemovedText() const {
52 MOZ_ASSERT(mChangeStart
<= mChangeEnd
);
54 return mChangeEnd
- mChangeStart
;
58 * The length of the text that was inserted in place of the removed text. If
59 * this was a pure text removal, this is 0.
61 uint32_t mReplaceLength
;
64 * The net result is that mChangeStart characters at the beginning of the
65 * text remained as they were. The next mChangeEnd - mChangeStart characters
66 * were removed, and mReplaceLength characters were inserted in their place.
67 * The text that used to begin at mChangeEnd now begins at
68 * mChangeStart + mReplaceLength.
71 struct MOZ_STACK_CLASS Details
{
73 eMerge
, // two text nodes are merged as a result of normalize()
74 eSplit
// a text node is split as a result of splitText()
77 * For eMerge it's the text node that will be removed, for eSplit it's the
80 nsIContent
* MOZ_NON_OWNING_REF mNextSibling
;
84 * Used for splitText() and normalize(), otherwise null.
90 * Mutation observer interface
92 * See nsINode::AddMutationObserver, nsINode::RemoveMutationObserver for how to
93 * attach or remove your observers. nsINode stores mutation observers using a
94 * mozilla::SafeDoublyLinkedList, which is a specialization of the
95 * DoublyLinkedList allowing for adding/removing elements while iterating.
96 * If a mutation observer is intended to be added to multiple nsINode instances,
97 * derive from nsMultiMutationObserver.
99 * WARNING: During these notifications, you are not allowed to perform
100 * any mutations to the current or any other document, or start a
101 * network load. If you need to perform such operations do that
102 * during the _last_ nsIDocumentObserver::EndUpdate notification. The
103 * exception for this is ParentChainChanged, where mutations should be
104 * done from an async event, as the notification might not be
105 * surrounded by BeginUpdate/EndUpdate calls.
107 class nsIMutationObserver
108 : public nsISupports
,
109 mozilla::DoublyLinkedListElement
<nsIMutationObserver
> {
110 friend struct mozilla::GetDoublyLinkedListElement
<nsIMutationObserver
>;
113 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID
)
116 * Notification that the node value of a data node (text, cdata, pi, comment)
119 * This notification is not sent when a piece of content is
120 * added/removed from the document (the other notifications are used
123 * @param aContent The piece of content that changed. Is never null.
124 * @param aInfo The structure with information details about the change.
126 * @note Callers of this method might not hold a strong reference to the
127 * observer. The observer is responsible for making sure it stays
128 * alive for the duration of the call as needed. The observer may
129 * assume that this call will happen when there are script blockers on
132 virtual void CharacterDataWillChange(nsIContent
* aContent
,
133 const CharacterDataChangeInfo
&) = 0;
136 * Notification that the node value of a data node (text, cdata, pi, comment)
139 * This notification is not sent when a piece of content is
140 * added/removed from the document (the other notifications are used
143 * @param aContent The piece of content that changed. Is never null.
144 * @param aInfo The structure with information details about the change.
146 * @note Callers of this method might not hold a strong reference to the
147 * observer. The observer is responsible for making sure it stays
148 * alive for the duration of the call as needed. The observer may
149 * assume that this call will happen when there are script blockers on
152 virtual void CharacterDataChanged(nsIContent
* aContent
,
153 const CharacterDataChangeInfo
&) = 0;
156 * Notification that an attribute of an element will change. This
157 * can happen before the BeginUpdate for the change and may not
158 * always be followed by an AttributeChanged (in particular, if the
159 * attribute doesn't actually change there will be no corresponding
162 * @param aContent The element whose attribute will change
163 * @param aNameSpaceID The namespace id of the changing attribute
164 * @param aAttribute The name of the changing attribute
165 * @param aModType Whether or not the attribute will be added, changed, or
166 * removed. The constants are defined in
167 * MutationEvent.webidl.
169 * @note Callers of this method might not hold a strong reference to the
170 * observer. The observer is responsible for making sure it stays
171 * alive for the duration of the call as needed. The observer may
172 * assume that this call will happen when there are script blockers on
175 virtual void AttributeWillChange(mozilla::dom::Element
* aElement
,
176 int32_t aNameSpaceID
, nsAtom
* aAttribute
,
177 int32_t aModType
) = 0;
180 * Notification that an attribute of an element has changed.
182 * @param aElement The element whose attribute changed
183 * @param aNameSpaceID The namespace id of the changed attribute
184 * @param aAttribute The name of the changed attribute
185 * @param aModType Whether or not the attribute was added, changed, or
186 * removed. The constants are defined in
187 * MutationEvent.webidl.
188 * @param aOldValue The old value, if either the old value or the new
189 * value are StoresOwnData() (or absent); null otherwise.
191 * @note Callers of this method might not hold a strong reference to the
192 * observer. The observer is responsible for making sure it stays
193 * alive for the duration of the call as needed. The observer may
194 * assume that this call will happen when there are script blockers on
197 virtual void AttributeChanged(mozilla::dom::Element
* aElement
,
198 int32_t aNameSpaceID
, nsAtom
* aAttribute
,
200 const nsAttrValue
* aOldValue
) = 0;
203 * Notification that an attribute of an element has been
204 * set to the value it already had.
206 * @param aElement The element whose attribute changed
207 * @param aNameSpaceID The namespace id of the changed attribute
208 * @param aAttribute The name of the changed attribute
210 virtual void AttributeSetToCurrentValue(mozilla::dom::Element
* aElement
,
211 int32_t aNameSpaceID
,
212 nsAtom
* aAttribute
) {}
215 * Notification that one or more content nodes have been appended to the
216 * child list of another node in the tree.
218 * @param aFirstNewContent the first node appended.
220 * @note Callers of this method might not hold a strong reference to the
221 * observer. The observer is responsible for making sure it stays
222 * alive for the duration of the call as needed. The observer may
223 * assume that this call will happen when there are script blockers on
226 virtual void ContentAppended(nsIContent
* aFirstNewContent
) = 0;
229 * Notification that a content node has been inserted as child to another
232 * @param aChild The newly inserted child.
234 * @note Callers of this method might not hold a strong reference to the
235 * observer. The observer is responsible for making sure it stays
236 * alive for the duration of the call as needed. The observer may
237 * assume that this call will happen when there are script blockers on
240 virtual void ContentInserted(nsIContent
* aChild
) = 0;
243 * Notification that a content node is about to be removed from the child list
244 * of another node in the tree.
246 * @param aChild The child that will be removed.
247 * @param aState The state of our batch removal of all children, or null.
249 * @note Callers of this method might not hold a strong reference to the
250 * observer. The observer is responsible for making sure it stays
251 * alive for the duration of the call as needed. The observer may
252 * assume that this call will happen when there are script blockers on
255 virtual void ContentWillBeRemoved(nsIContent
* aChild
,
256 const BatchRemovalState
*) = 0;
259 * The node is in the process of being destroyed. Calling QI on the node is
260 * not supported, however it is possible to get children and flags through
261 * nsINode as well as calling IsContent and casting to nsIContent to get
264 * NOTE: This notification is only called on observers registered directly
265 * on the node. This is because when the node is destroyed it can not have
266 * any ancestors. If you want to know when a descendant node is being
267 * removed from the observed node, use the ContentWillBeRemoved notification.
269 * @param aNode The node being destroyed.
271 * @note Callers of this method might not hold a strong reference to
272 * the observer. The observer is responsible for making sure it
273 * stays alive for the duration of the call as needed.
275 virtual void NodeWillBeDestroyed(nsINode
* aNode
) = 0;
278 * Notification that the node's parent chain has changed. This
279 * happens when either the node or one of its ancestors is inserted
280 * or removed as a child of another node.
282 * Note that when a node is inserted this notification is sent to
283 * all descendants of that node, since all such nodes have their
284 * parent chain changed.
286 * @param aContent The piece of content that had its parent changed.
288 * @note Callers of this method might not hold a strong reference to
289 * the observer. The observer is responsible for making sure it
290 * stays alive for the duration of the call as needed.
293 virtual void ParentChainChanged(nsIContent
* aContent
) = 0;
295 virtual void ARIAAttributeDefaultWillChange(mozilla::dom::Element
* aElement
,
297 int32_t aModType
) = 0;
298 virtual void ARIAAttributeDefaultChanged(mozilla::dom::Element
* aElement
,
300 int32_t aModType
) = 0;
304 kCharacterDataWillChange
= 1 << 0,
305 kCharacterDataChanged
= 1 << 1,
306 kAttributeWillChange
= 1 << 2,
307 kAttributeChanged
= 1 << 3,
308 kAttributeSetToCurrentValue
= 1 << 4,
309 kContentAppended
= 1 << 5,
310 kContentInserted
= 1 << 6,
311 kContentWillBeRemoved
= 1 << 7,
312 kNodeWillBeDestroyed
= 1 << 8,
313 kParentChainChanged
= 1 << 9,
314 kARIAAttributeDefaultWillChange
= 1 << 10,
315 kARIAAttributeDefaultChanged
= 1 << 11,
317 kBeginUpdate
= 1 << 12,
318 kEndUpdate
= 1 << 13,
319 kBeginLoad
= 1 << 14,
321 kElementStateChanged
= 1 << 16,
323 kAnimationAdded
= 1 << 17,
324 kAnimationChanged
= 1 << 18,
325 kAnimationRemoved
= 1 << 19,
330 void SetEnabledCallbacks(uint32_t aCallbacks
) {
331 mEnabledCallbacks
= aCallbacks
;
334 bool IsCallbackEnabled(uint32_t aCallback
) const {
335 return mEnabledCallbacks
& aCallback
;
339 uint32_t mEnabledCallbacks
= kAll
;
342 NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver
, NS_IMUTATION_OBSERVER_IID
)
344 #define NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE \
345 virtual void CharacterDataWillChange( \
346 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) override;
348 #define NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED \
349 virtual void CharacterDataChanged( \
350 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) override;
352 #define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE \
353 virtual void AttributeWillChange(mozilla::dom::Element* aElement, \
354 int32_t aNameSpaceID, nsAtom* aAttribute, \
355 int32_t aModType) override;
357 #define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED \
358 virtual void AttributeChanged(mozilla::dom::Element* aElement, \
359 int32_t aNameSpaceID, nsAtom* aAttribute, \
361 const nsAttrValue* aOldValue) override;
363 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED \
364 virtual void ContentAppended(nsIContent* aFirstNewContent) override;
366 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED \
367 virtual void ContentInserted(nsIContent* aChild) override;
369 #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED \
370 virtual void ContentWillBeRemoved(nsIContent* aChild, \
371 const BatchRemovalState*) override;
373 #define NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED \
374 virtual void NodeWillBeDestroyed(nsINode* aNode) override;
376 #define NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED \
377 virtual void ParentChainChanged(nsIContent* aContent) override;
379 #define NS_DECL_NSIMUTATIONOBSERVER_ARIAATTRIBUTEDEFAULTWILLCHANGE \
380 virtual void ARIAAttributeDefaultWillChange( \
381 mozilla::dom::Element* aElement, nsAtom* aAttribute, int32_t aModType) \
384 #define NS_DECL_NSIMUTATIONOBSERVER_ARIAATTRIBUTEDEFAULTCHANGED \
385 virtual void ARIAAttributeDefaultChanged( \
386 mozilla::dom::Element* aElement, nsAtom* aAttribute, int32_t aModType) \
389 #define NS_DECL_NSIMUTATIONOBSERVER \
390 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE \
391 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED \
392 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE \
393 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED \
394 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED \
395 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED \
396 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED \
397 NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED \
398 NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED \
399 NS_DECL_NSIMUTATIONOBSERVER_ARIAATTRIBUTEDEFAULTWILLCHANGE \
400 NS_DECL_NSIMUTATIONOBSERVER_ARIAATTRIBUTEDEFAULTCHANGED
402 #define NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class) \
403 void _class::NodeWillBeDestroyed(nsINode* aNode) {}
405 #define NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class) \
406 void _class::CharacterDataWillChange( \
407 nsIContent* aContent, const CharacterDataChangeInfo& aInfo) {} \
408 void _class::CharacterDataChanged(nsIContent* aContent, \
409 const CharacterDataChangeInfo& aInfo) {} \
410 void _class::AttributeWillChange(mozilla::dom::Element* aElement, \
411 int32_t aNameSpaceID, nsAtom* aAttribute, \
412 int32_t aModType) {} \
413 void _class::AttributeChanged( \
414 mozilla::dom::Element* aElement, int32_t aNameSpaceID, \
415 nsAtom* aAttribute, int32_t aModType, const nsAttrValue* aOldValue) {} \
416 void _class::ContentAppended(nsIContent* aFirstNewContent) {} \
417 void _class::ContentInserted(nsIContent* aChild) {} \
418 void _class::ContentWillBeRemoved(nsIContent* aChild, \
419 const BatchRemovalState*) {} \
420 void _class::ParentChainChanged(nsIContent* aContent) {} \
421 void _class::ARIAAttributeDefaultWillChange( \
422 mozilla::dom::Element* aElement, nsAtom* aAttribute, int32_t aModType) { \
424 void _class::ARIAAttributeDefaultChanged( \
425 mozilla::dom::Element* aElement, nsAtom* aAttribute, int32_t aModType) { \
428 #endif /* nsIMutationObserver_h */