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