|
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 #ifndef nsNodeUtils_h___ |
|
7 #define nsNodeUtils_h___ |
|
8 |
|
9 #include "nsIContent.h" // for use in inline function (ParentChainChanged) |
|
10 #include "nsIMutationObserver.h" // for use in inline function (ParentChainChanged) |
|
11 #include "js/TypeDecls.h" |
|
12 #include "nsCOMArray.h" |
|
13 |
|
14 struct CharacterDataChangeInfo; |
|
15 class nsIVariant; |
|
16 class nsIDOMNode; |
|
17 class nsIDOMUserDataHandler; |
|
18 template<class E> class nsCOMArray; |
|
19 class nsCycleCollectionTraversalCallback; |
|
20 |
|
21 class nsNodeUtils |
|
22 { |
|
23 public: |
|
24 /** |
|
25 * Send CharacterDataWillChange notifications to nsIMutationObservers. |
|
26 * @param aContent Node whose data changed |
|
27 * @param aInfo Struct with information details about the change |
|
28 * @see nsIMutationObserver::CharacterDataWillChange |
|
29 */ |
|
30 static void CharacterDataWillChange(nsIContent* aContent, |
|
31 CharacterDataChangeInfo* aInfo); |
|
32 |
|
33 /** |
|
34 * Send CharacterDataChanged notifications to nsIMutationObservers. |
|
35 * @param aContent Node whose data changed |
|
36 * @param aInfo Struct with information details about the change |
|
37 * @see nsIMutationObserver::CharacterDataChanged |
|
38 */ |
|
39 static void CharacterDataChanged(nsIContent* aContent, |
|
40 CharacterDataChangeInfo* aInfo); |
|
41 |
|
42 /** |
|
43 * Send AttributeWillChange notifications to nsIMutationObservers. |
|
44 * @param aElement Element whose data will change |
|
45 * @param aNameSpaceID Namespace of changing attribute |
|
46 * @param aAttribute Local-name of changing attribute |
|
47 * @param aModType Type of change (add/change/removal) |
|
48 * @see nsIMutationObserver::AttributeWillChange |
|
49 */ |
|
50 static void AttributeWillChange(mozilla::dom::Element* aElement, |
|
51 int32_t aNameSpaceID, |
|
52 nsIAtom* aAttribute, |
|
53 int32_t aModType); |
|
54 |
|
55 /** |
|
56 * Send AttributeChanged notifications to nsIMutationObservers. |
|
57 * @param aElement Element whose data changed |
|
58 * @param aNameSpaceID Namespace of changed attribute |
|
59 * @param aAttribute Local-name of changed attribute |
|
60 * @param aModType Type of change (add/change/removal) |
|
61 * @see nsIMutationObserver::AttributeChanged |
|
62 */ |
|
63 static void AttributeChanged(mozilla::dom::Element* aElement, |
|
64 int32_t aNameSpaceID, |
|
65 nsIAtom* aAttribute, |
|
66 int32_t aModType); |
|
67 /** |
|
68 * Send AttributeSetToCurrentValue notifications to nsIMutationObservers. |
|
69 * @param aElement Element whose data changed |
|
70 * @param aNameSpaceID Namespace of the attribute |
|
71 * @param aAttribute Local-name of the attribute |
|
72 * @see nsIMutationObserver::AttributeSetToCurrentValue |
|
73 */ |
|
74 static void AttributeSetToCurrentValue(mozilla::dom::Element* aElement, |
|
75 int32_t aNameSpaceID, |
|
76 nsIAtom* aAttribute); |
|
77 |
|
78 /** |
|
79 * Send ContentAppended notifications to nsIMutationObservers |
|
80 * @param aContainer Node into which new child/children were added |
|
81 * @param aFirstNewContent First new child |
|
82 * @param aNewIndexInContainer Index of first new child |
|
83 * @see nsIMutationObserver::ContentAppended |
|
84 */ |
|
85 static void ContentAppended(nsIContent* aContainer, |
|
86 nsIContent* aFirstNewContent, |
|
87 int32_t aNewIndexInContainer); |
|
88 |
|
89 /** |
|
90 * Send ContentInserted notifications to nsIMutationObservers |
|
91 * @param aContainer Node into which new child was inserted |
|
92 * @param aChild Newly inserted child |
|
93 * @param aIndexInContainer Index of new child |
|
94 * @see nsIMutationObserver::ContentInserted |
|
95 */ |
|
96 static void ContentInserted(nsINode* aContainer, |
|
97 nsIContent* aChild, |
|
98 int32_t aIndexInContainer); |
|
99 /** |
|
100 * Send ContentRemoved notifications to nsIMutationObservers |
|
101 * @param aContainer Node from which child was removed |
|
102 * @param aChild Removed child |
|
103 * @param aIndexInContainer Index of removed child |
|
104 * @see nsIMutationObserver::ContentRemoved |
|
105 */ |
|
106 static void ContentRemoved(nsINode* aContainer, |
|
107 nsIContent* aChild, |
|
108 int32_t aIndexInContainer, |
|
109 nsIContent* aPreviousSibling); |
|
110 /** |
|
111 * Send ParentChainChanged notifications to nsIMutationObservers |
|
112 * @param aContent The piece of content that had its parent changed. |
|
113 * @see nsIMutationObserver::ParentChainChanged |
|
114 */ |
|
115 static inline void ParentChainChanged(nsIContent *aContent) |
|
116 { |
|
117 nsINode::nsSlots* slots = aContent->GetExistingSlots(); |
|
118 if (slots && !slots->mMutationObservers.IsEmpty()) { |
|
119 NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(slots->mMutationObservers, |
|
120 nsIMutationObserver, |
|
121 ParentChainChanged, |
|
122 (aContent)); |
|
123 } |
|
124 } |
|
125 |
|
126 /** |
|
127 * To be called when reference count of aNode drops to zero. |
|
128 * @param aNode The node which is going to be deleted. |
|
129 */ |
|
130 static void LastRelease(nsINode* aNode); |
|
131 |
|
132 /** |
|
133 * Clones aNode, its attributes and, if aDeep is true, its descendant nodes |
|
134 * If aNewNodeInfoManager is not null, it is used to create new nodeinfos for |
|
135 * the clones. aNodesWithProperties will be filled with all the nodes that |
|
136 * have properties, and every node in it will be followed by its clone. |
|
137 * |
|
138 * @param aNode Node to clone. |
|
139 * @param aDeep If true the function will be called recursively on |
|
140 * descendants of the node |
|
141 * @param aNewNodeInfoManager The nodeinfo manager to use to create new |
|
142 * nodeinfos for aNode and its attributes and |
|
143 * descendants. May be null if the nodeinfos |
|
144 * shouldn't be changed. |
|
145 * @param aNodesWithProperties All nodes (from amongst aNode and its |
|
146 * descendants) with properties. Every node will |
|
147 * be followed by its clone. |
|
148 * @param aResult *aResult will contain the cloned node. |
|
149 */ |
|
150 static nsresult Clone(nsINode *aNode, bool aDeep, |
|
151 nsNodeInfoManager *aNewNodeInfoManager, |
|
152 nsCOMArray<nsINode> &aNodesWithProperties, |
|
153 nsINode **aResult) |
|
154 { |
|
155 return CloneAndAdopt(aNode, true, aDeep, aNewNodeInfoManager, |
|
156 JS::NullPtr(), aNodesWithProperties, nullptr, aResult); |
|
157 } |
|
158 |
|
159 /** |
|
160 * Clones aNode, its attributes and, if aDeep is true, its descendant nodes |
|
161 */ |
|
162 static nsresult Clone(nsINode *aNode, bool aDeep, nsINode **aResult) |
|
163 { |
|
164 nsCOMArray<nsINode> dummyNodeWithProperties; |
|
165 return CloneAndAdopt(aNode, true, aDeep, nullptr, JS::NullPtr(), |
|
166 dummyNodeWithProperties, aNode->GetParent(), aResult); |
|
167 } |
|
168 |
|
169 /** |
|
170 * Walks aNode, its attributes and descendant nodes. If aNewNodeInfoManager is |
|
171 * not null, it is used to create new nodeinfos for the nodes. Also reparents |
|
172 * the XPConnect wrappers for the nodes into aReparentScope if non-null. |
|
173 * aNodesWithProperties will be filled with all the nodes that have |
|
174 * properties. |
|
175 * |
|
176 * @param aNode Node to adopt. |
|
177 * @param aNewNodeInfoManager The nodeinfo manager to use to create new |
|
178 * nodeinfos for aNode and its attributes and |
|
179 * descendants. May be null if the nodeinfos |
|
180 * shouldn't be changed. |
|
181 * @param aReparentScope New scope for the wrappers, or null if no reparenting |
|
182 * should be done. |
|
183 * @param aNodesWithProperties All nodes (from amongst aNode and its |
|
184 * descendants) with properties. |
|
185 */ |
|
186 static nsresult Adopt(nsINode *aNode, nsNodeInfoManager *aNewNodeInfoManager, |
|
187 JS::Handle<JSObject*> aReparentScope, |
|
188 nsCOMArray<nsINode> &aNodesWithProperties) |
|
189 { |
|
190 nsCOMPtr<nsINode> node; |
|
191 nsresult rv = CloneAndAdopt(aNode, false, true, aNewNodeInfoManager, |
|
192 aReparentScope, aNodesWithProperties, |
|
193 nullptr, getter_AddRefs(node)); |
|
194 |
|
195 nsMutationGuard::DidMutate(); |
|
196 |
|
197 return rv; |
|
198 } |
|
199 |
|
200 /** |
|
201 * Call registered userdata handlers for operation aOperation for the nodes in |
|
202 * aNodesWithProperties. If aCloned is true aNodesWithProperties should |
|
203 * contain both the original and the cloned nodes (and only the userdata |
|
204 * handlers registered for the original nodes will be called). |
|
205 * |
|
206 * @param aNodesWithProperties Contains the nodes that might have properties |
|
207 * registered on them. If aCloned is true every |
|
208 * one of those nodes should be immediately |
|
209 * followed in the array by the cloned node. |
|
210 * @param aOwnerDocument The ownerDocument of the original nodes. |
|
211 * @param aOperation The operation to call a userdata handler for. |
|
212 * @param aCloned If true aNodesWithProperties will contain both original |
|
213 * and cloned nodes. |
|
214 */ |
|
215 static nsresult CallUserDataHandlers(nsCOMArray<nsINode> &aNodesWithProperties, |
|
216 nsIDocument *aOwnerDocument, |
|
217 uint16_t aOperation, bool aCloned); |
|
218 |
|
219 /** |
|
220 * Helper for the cycle collector to traverse the DOM UserData and |
|
221 * UserDataHandlers for aNode. |
|
222 * |
|
223 * @param aNode the node to traverse UserData and UserDataHandlers for |
|
224 * @param aCb the cycle collection callback |
|
225 */ |
|
226 static void TraverseUserData(nsINode* aNode, |
|
227 nsCycleCollectionTraversalCallback &aCb); |
|
228 |
|
229 /** |
|
230 * A basic implementation of the DOM cloneNode method. Calls nsINode::Clone to |
|
231 * do the actual cloning of the node. |
|
232 * |
|
233 * @param aNode the node to clone |
|
234 * @param aDeep if true all descendants will be cloned too |
|
235 * @param aCallUserDataHandlers if true, user data handlers will be called |
|
236 * @param aResult the clone |
|
237 */ |
|
238 static nsresult CloneNodeImpl(nsINode *aNode, bool aDeep, |
|
239 bool aCallUserDataHandlers, |
|
240 nsINode **aResult); |
|
241 |
|
242 /** |
|
243 * Release the UserData and UserDataHandlers for aNode. |
|
244 * |
|
245 * @param aNode the node to release the UserData and UserDataHandlers for |
|
246 */ |
|
247 static void UnlinkUserData(nsINode *aNode); |
|
248 |
|
249 /** |
|
250 * Returns a true if the node is a HTMLTemplate element. |
|
251 * |
|
252 * @param aNode a node to test for HTMLTemplate elementness. |
|
253 */ |
|
254 static bool IsTemplateElement(const nsINode *aNode); |
|
255 |
|
256 /** |
|
257 * Returns the first child of a node or the first child of |
|
258 * a template element's content if the provided node is a |
|
259 * template element. |
|
260 * |
|
261 * @param aNode A node from which to retrieve the first child. |
|
262 */ |
|
263 static nsIContent* GetFirstChildOfTemplateOrNode(nsINode* aNode); |
|
264 |
|
265 private: |
|
266 /** |
|
267 * Walks aNode, its attributes and, if aDeep is true, its descendant nodes. |
|
268 * If aClone is true the nodes will be cloned. If aNewNodeInfoManager is |
|
269 * not null, it is used to create new nodeinfos for the nodes. Also reparents |
|
270 * the XPConnect wrappers for the nodes into aReparentScope if non-null. |
|
271 * aNodesWithProperties will be filled with all the nodes that have |
|
272 * properties. |
|
273 * |
|
274 * @param aNode Node to adopt/clone. |
|
275 * @param aClone If true the node will be cloned and the cloned node will |
|
276 * be in aResult. |
|
277 * @param aDeep If true the function will be called recursively on |
|
278 * descendants of the node |
|
279 * @param aNewNodeInfoManager The nodeinfo manager to use to create new |
|
280 * nodeinfos for aNode and its attributes and |
|
281 * descendants. May be null if the nodeinfos |
|
282 * shouldn't be changed. |
|
283 * @param aReparentScope Scope into which wrappers should be reparented, or |
|
284 * null if no reparenting should be done. |
|
285 * @param aNodesWithProperties All nodes (from amongst aNode and its |
|
286 * descendants) with properties. If aClone is |
|
287 * true every node will be followed by its |
|
288 * clone. |
|
289 * @param aParent If aClone is true the cloned node will be appended to |
|
290 * aParent's children. May be null. If not null then aNode |
|
291 * must be an nsIContent. |
|
292 * @param aResult If aClone is true then *aResult will contain the cloned |
|
293 * node. |
|
294 */ |
|
295 static nsresult CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep, |
|
296 nsNodeInfoManager *aNewNodeInfoManager, |
|
297 JS::Handle<JSObject*> aReparentScope, |
|
298 nsCOMArray<nsINode> &aNodesWithProperties, |
|
299 nsINode *aParent, nsINode **aResult); |
|
300 }; |
|
301 |
|
302 #endif // nsNodeUtils_h___ |