/work/obj-fuzz/dist/include/nsINode.h
Line | Count | Source (jump to first uncovered line) |
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 nsINode_h___ |
8 | | #define nsINode_h___ |
9 | | |
10 | | #include "mozilla/Likely.h" |
11 | | #include "mozilla/UniquePtr.h" |
12 | | #include "nsCOMPtr.h" // for member, local |
13 | | #include "nsGkAtoms.h" // for nsGkAtoms::baseURIProperty |
14 | | #include "mozilla/dom/NodeInfo.h" // member (in nsCOMPtr) |
15 | | #include "nsIVariant.h" // for use in GetUserData() |
16 | | #include "nsIWeakReference.h" |
17 | | #include "nsNodeInfoManager.h" // for use in NodePrincipal() |
18 | | #include "nsPropertyTable.h" // for typedefs |
19 | | #include "nsTObserverArray.h" // for member |
20 | | #include "mozilla/ErrorResult.h" |
21 | | #include "mozilla/LinkedList.h" |
22 | | #include "mozilla/MemoryReporting.h" |
23 | | #include "mozilla/dom/EventTarget.h" // for base class |
24 | | #include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext |
25 | | #include "mozilla/dom/DOMString.h" |
26 | | #include "mozilla/dom/BindingDeclarations.h" |
27 | | #include "mozilla/dom/NodeBinding.h" |
28 | | #include "nsTHashtable.h" |
29 | | #include <iosfwd> |
30 | | |
31 | | // Including 'windows.h' will #define GetClassInfo to something else. |
32 | | #ifdef XP_WIN |
33 | | #ifdef GetClassInfo |
34 | | #undef GetClassInfo |
35 | | #endif |
36 | | #endif |
37 | | |
38 | | class AttrArray; |
39 | | class nsAttrChildContentList; |
40 | | class nsDOMAttributeMap; |
41 | | class nsIAnimationObserver; |
42 | | class nsIContent; |
43 | | class nsIDocument; |
44 | | class nsIFrame; |
45 | | class nsIHTMLCollection; |
46 | | class nsIMutationObserver; |
47 | | class nsINode; |
48 | | class nsINodeList; |
49 | | class nsIPresShell; |
50 | | class nsIPrincipal; |
51 | | class nsIURI; |
52 | | class nsNodeSupportsWeakRefTearoff; |
53 | | class nsDOMMutationObserver; |
54 | | class nsRange; |
55 | | class nsWindowSizes; |
56 | | struct RawServoSelectorList; |
57 | | |
58 | | namespace mozilla { |
59 | | class EventListenerManager; |
60 | | class TextEditor; |
61 | | namespace dom { |
62 | | /** |
63 | | * @return true if aChar is what the WHATWG defines as a 'ascii whitespace'. |
64 | | * https://infra.spec.whatwg.org/#ascii-whitespace |
65 | | */ |
66 | | inline bool IsSpaceCharacter(char16_t aChar) { |
67 | | return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' || |
68 | | aChar == '\f'; |
69 | | } |
70 | | inline bool IsSpaceCharacter(char aChar) { |
71 | | return aChar == ' ' || aChar == '\t' || aChar == '\n' || aChar == '\r' || |
72 | | aChar == '\f'; |
73 | | } |
74 | | class AccessibleNode; |
75 | | struct BoxQuadOptions; |
76 | | struct ConvertCoordinateOptions; |
77 | | class DocGroup; |
78 | | class DocumentFragment; |
79 | | class DocumentOrShadowRoot; |
80 | | class DOMPoint; |
81 | | class DOMQuad; |
82 | | class DOMRectReadOnly; |
83 | | class Element; |
84 | | class EventHandlerNonNull; |
85 | | class L10nCallback; |
86 | | template<typename T> class Optional; |
87 | | class OwningNodeOrString; |
88 | | class Promise; |
89 | | template<typename> class Sequence; |
90 | | class SVGUseElement; |
91 | | class Text; |
92 | | class TextOrElementOrDocument; |
93 | | struct DOMPointInit; |
94 | | struct GetRootNodeOptions; |
95 | | enum class CallerType : uint32_t; |
96 | | } // namespace dom |
97 | | } // namespace mozilla |
98 | | |
99 | | #define NODE_FLAG_BIT(n_) \ |
100 | | (nsWrapperCache::FlagsType(1U) << (WRAPPER_CACHE_FLAGS_BITS_USED + (n_))) |
101 | | |
102 | | enum { |
103 | | // This bit will be set if the node has a listener manager. |
104 | | NODE_HAS_LISTENERMANAGER = NODE_FLAG_BIT(0), |
105 | | |
106 | | // Whether this node has had any properties set on it |
107 | | NODE_HAS_PROPERTIES = NODE_FLAG_BIT(1), |
108 | | |
109 | | // Whether this node is the root of an anonymous subtree. Note that this |
110 | | // need not be a native anonymous subtree. Any anonymous subtree, including |
111 | | // XBL-generated ones, will do. This flag is set-once: once a node has it, |
112 | | // it must not be removed. |
113 | | // NOTE: Should only be used on nsIContent nodes |
114 | | NODE_IS_ANONYMOUS_ROOT = NODE_FLAG_BIT(2), |
115 | | |
116 | | // Whether the node has some ancestor, possibly itself, that is native |
117 | | // anonymous. This includes ancestors crossing XBL scopes, in cases when an |
118 | | // XBL binding is attached to an element which has a native anonymous |
119 | | // ancestor. This flag is set-once: once a node has it, it must not be |
120 | | // removed. |
121 | | // NOTE: Should only be used on nsIContent nodes |
122 | | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE = NODE_FLAG_BIT(3), |
123 | | |
124 | | // Whether this node is the root of a native anonymous (from the perspective |
125 | | // of its parent) subtree. This flag is set-once: once a node has it, it |
126 | | // must not be removed. |
127 | | // NOTE: Should only be used on nsIContent nodes |
128 | | NODE_IS_NATIVE_ANONYMOUS_ROOT = NODE_FLAG_BIT(4), |
129 | | |
130 | | // Whether a binding manager may have a pointer to this |
131 | | NODE_MAY_BE_IN_BINDING_MNGR = NODE_FLAG_BIT(5), |
132 | | |
133 | | NODE_IS_EDITABLE = NODE_FLAG_BIT(6), |
134 | | |
135 | | // Free bit here. |
136 | | |
137 | | // Whether the node participates in a shadow tree. |
138 | | NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(8), |
139 | | |
140 | | // Node has an :empty or :-moz-only-whitespace selector |
141 | | NODE_HAS_EMPTY_SELECTOR = NODE_FLAG_BIT(9), |
142 | | |
143 | | // A child of the node has a selector such that any insertion, |
144 | | // removal, or appending of children requires restyling the parent. |
145 | | NODE_HAS_SLOW_SELECTOR = NODE_FLAG_BIT(10), |
146 | | |
147 | | // A child of the node has a :first-child, :-moz-first-node, |
148 | | // :only-child, :last-child or :-moz-last-node selector. |
149 | | NODE_HAS_EDGE_CHILD_SELECTOR = NODE_FLAG_BIT(11), |
150 | | |
151 | | // A child of the node has a selector such that any insertion or |
152 | | // removal of children requires restyling later siblings of that |
153 | | // element. Additionally (in this manner it is stronger than |
154 | | // NODE_HAS_SLOW_SELECTOR), if a child's style changes due to any |
155 | | // other content tree changes (e.g., the child changes to or from |
156 | | // matching :empty due to a grandchild insertion or removal), the |
157 | | // child's later siblings must also be restyled. |
158 | | NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS = NODE_FLAG_BIT(12), |
159 | | |
160 | | NODE_ALL_SELECTOR_FLAGS = NODE_HAS_EMPTY_SELECTOR | |
161 | | NODE_HAS_SLOW_SELECTOR | |
162 | | NODE_HAS_EDGE_CHILD_SELECTOR | |
163 | | NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS, |
164 | | |
165 | | // This node needs to go through frame construction to get a frame (or |
166 | | // undisplayed entry). |
167 | | NODE_NEEDS_FRAME = NODE_FLAG_BIT(13), |
168 | | |
169 | | // At least one descendant in the flattened tree has NODE_NEEDS_FRAME set. |
170 | | // This should be set on every node on the flattened tree path between the |
171 | | // node(s) with NODE_NEEDS_FRAME and the root content. |
172 | | NODE_DESCENDANTS_NEED_FRAMES = NODE_FLAG_BIT(14), |
173 | | |
174 | | // Set if the node has the accesskey attribute set. |
175 | | NODE_HAS_ACCESSKEY = NODE_FLAG_BIT(15), |
176 | | |
177 | | // Set if the node has right-to-left directionality |
178 | | NODE_HAS_DIRECTION_RTL = NODE_FLAG_BIT(16), |
179 | | |
180 | | // Set if the node has left-to-right directionality |
181 | | NODE_HAS_DIRECTION_LTR = NODE_FLAG_BIT(17), |
182 | | |
183 | | NODE_ALL_DIRECTION_FLAGS = NODE_HAS_DIRECTION_LTR | |
184 | | NODE_HAS_DIRECTION_RTL, |
185 | | |
186 | | NODE_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(18), |
187 | | |
188 | | NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS = NODE_FLAG_BIT(19), |
189 | | |
190 | | // Remaining bits are node type specific. |
191 | | NODE_TYPE_SPECIFIC_BITS_OFFSET = 20 |
192 | | }; |
193 | | |
194 | | // Make sure we have space for our bits |
195 | | #define ASSERT_NODE_FLAGS_SPACE(n) \ |
196 | | static_assert(WRAPPER_CACHE_FLAGS_BITS_USED + (n) <= \ |
197 | | sizeof(nsWrapperCache::FlagsType) * 8, \ |
198 | | "Not enough space for our bits") |
199 | | ASSERT_NODE_FLAGS_SPACE(NODE_TYPE_SPECIFIC_BITS_OFFSET); |
200 | | |
201 | | /** |
202 | | * Class used to detect unexpected mutations. To use the class create an |
203 | | * nsMutationGuard on the stack before unexpected mutations could occur. |
204 | | * You can then at any time call Mutated to check if any unexpected mutations |
205 | | * have occurred. |
206 | | */ |
207 | | class nsMutationGuard { |
208 | | public: |
209 | | nsMutationGuard() |
210 | | { |
211 | | mStartingGeneration = sGeneration; |
212 | | } |
213 | | |
214 | | /** |
215 | | * Returns true if any unexpected mutations have occurred. You can pass in |
216 | | * an 8-bit ignore count to ignore a number of expected mutations. |
217 | | * |
218 | | * We don't need to care about overflow because subtraction of uint64_t's is |
219 | | * finding the difference between two elements of the group Z < 2^64. Once |
220 | | * we know the difference between two elements we only need to check that is |
221 | | * less than the given number of mutations to know less than that many |
222 | | * mutations occured. Assuming constant 1ns mutations it would take 584 |
223 | | * years for sGeneration to fully wrap around so we can ignore a guard living |
224 | | * through a full wrap around. |
225 | | */ |
226 | | bool Mutated(uint8_t aIgnoreCount) |
227 | | { |
228 | | return (sGeneration - mStartingGeneration) > aIgnoreCount; |
229 | | } |
230 | | |
231 | | // This function should be called whenever a mutation that we want to keep |
232 | | // track of happen. For now this is only done when children are added or |
233 | | // removed, but we might do it for attribute changes too in the future. |
234 | | static void DidMutate() |
235 | | { |
236 | | sGeneration++; |
237 | | } |
238 | | |
239 | | private: |
240 | | // This is the value sGeneration had when the guard was constructed. |
241 | | uint64_t mStartingGeneration; |
242 | | |
243 | | // This value is incremented on every mutation, for the life of the process. |
244 | | static uint64_t sGeneration; |
245 | | }; |
246 | | |
247 | | /** |
248 | | * A class that implements nsIWeakReference |
249 | | */ |
250 | | class nsNodeWeakReference final : public nsIWeakReference |
251 | | { |
252 | | public: |
253 | | explicit nsNodeWeakReference(nsINode* aNode); |
254 | | |
255 | | // nsISupports |
256 | | NS_DECL_ISUPPORTS |
257 | | |
258 | | // nsIWeakReference |
259 | | NS_DECL_NSIWEAKREFERENCE |
260 | | size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override; |
261 | | |
262 | | void NoticeNodeDestruction() |
263 | | { |
264 | | mObject = nullptr; |
265 | | } |
266 | | |
267 | | private: |
268 | | ~nsNodeWeakReference(); |
269 | | }; |
270 | | |
271 | | // This should be used for any nsINode sub-class that has fields of its own |
272 | | // that it needs to measure; any sub-class that doesn't use it will inherit |
273 | | // AddSizeOfExcludingThis from its super-class. AddSizeOfIncludingThis() need |
274 | | // not be defined, it is inherited from nsINode. |
275 | | #define NS_DECL_ADDSIZEOFEXCLUDINGTHIS \ |
276 | | virtual void AddSizeOfExcludingThis(nsWindowSizes& aSizes, \ |
277 | | size_t* aNodeSize) const override; |
278 | | |
279 | | // IID for the nsINode interface |
280 | | // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs |
281 | | #define NS_INODE_IID \ |
282 | | { 0x70ba4547, 0x7699, 0x44fc, \ |
283 | | { 0xb3, 0x20, 0x52, 0xdb, 0xe3, 0xd1, 0xf9, 0x0a } } |
284 | | |
285 | | /** |
286 | | * An internal interface that abstracts some DOMNode-related parts that both |
287 | | * nsIContent and nsIDocument share. An instance of this interface has a list |
288 | | * of nsIContent children and provides access to them. |
289 | | */ |
290 | | class nsINode : public mozilla::dom::EventTarget |
291 | | { |
292 | | public: |
293 | | typedef mozilla::dom::BoxQuadOptions BoxQuadOptions; |
294 | | typedef mozilla::dom::ConvertCoordinateOptions ConvertCoordinateOptions; |
295 | | typedef mozilla::dom::DocGroup DocGroup; |
296 | | typedef mozilla::dom::DOMPoint DOMPoint; |
297 | | typedef mozilla::dom::DOMPointInit DOMPointInit; |
298 | | typedef mozilla::dom::DOMQuad DOMQuad; |
299 | | typedef mozilla::dom::DOMRectReadOnly DOMRectReadOnly; |
300 | | typedef mozilla::dom::OwningNodeOrString OwningNodeOrString; |
301 | | typedef mozilla::dom::TextOrElementOrDocument TextOrElementOrDocument; |
302 | | typedef mozilla::dom::CallerType CallerType; |
303 | | typedef mozilla::ErrorResult ErrorResult; |
304 | | |
305 | | // XXXbz Maybe we should codegen a class holding these constants and |
306 | | // inherit from it... |
307 | | static const auto ELEMENT_NODE = mozilla::dom::Node_Binding::ELEMENT_NODE; |
308 | | static const auto ATTRIBUTE_NODE = mozilla::dom::Node_Binding::ATTRIBUTE_NODE; |
309 | | static const auto TEXT_NODE = mozilla::dom::Node_Binding::TEXT_NODE; |
310 | | static const auto CDATA_SECTION_NODE = |
311 | | mozilla::dom::Node_Binding::CDATA_SECTION_NODE; |
312 | | static const auto ENTITY_REFERENCE_NODE = |
313 | | mozilla::dom::Node_Binding::ENTITY_REFERENCE_NODE; |
314 | | static const auto ENTITY_NODE = mozilla::dom::Node_Binding::ENTITY_NODE; |
315 | | static const auto PROCESSING_INSTRUCTION_NODE = |
316 | | mozilla::dom::Node_Binding::PROCESSING_INSTRUCTION_NODE; |
317 | | static const auto COMMENT_NODE = mozilla::dom::Node_Binding::COMMENT_NODE; |
318 | | static const auto DOCUMENT_NODE = mozilla::dom::Node_Binding::DOCUMENT_NODE; |
319 | | static const auto DOCUMENT_TYPE_NODE = |
320 | | mozilla::dom::Node_Binding::DOCUMENT_TYPE_NODE; |
321 | | static const auto DOCUMENT_FRAGMENT_NODE = |
322 | | mozilla::dom::Node_Binding::DOCUMENT_FRAGMENT_NODE; |
323 | | static const auto NOTATION_NODE = mozilla::dom::Node_Binding::NOTATION_NODE; |
324 | | |
325 | | template<class T> |
326 | | using Sequence = mozilla::dom::Sequence<T>; |
327 | | |
328 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID) |
329 | | |
330 | | // The |aNodeSize| outparam on this function is where the actual node size |
331 | | // value is put. It gets added to the appropriate value within |aSizes| by |
332 | | // AddSizeOfNodeTree(). |
333 | | // |
334 | | // Among the sub-classes that inherit (directly or indirectly) from nsINode, |
335 | | // measurement of the following members may be added later if DMD finds it is |
336 | | // worthwhile: |
337 | | // - nsGenericHTMLElement: mForm, mFieldSet |
338 | | // - nsGenericHTMLFrameElement: mFrameLoader (bug 672539) |
339 | | // - HTMLBodyElement: mContentStyleRule |
340 | | // - HTMLDataListElement: mOptions |
341 | | // - HTMLFieldSetElement: mElements, mDependentElements, mFirstLegend |
342 | | // - HTMLFormElement: many! |
343 | | // - HTMLFrameSetElement: mRowSpecs, mColSpecs |
344 | | // - HTMLInputElement: mInputData, mFiles, mFileList, mStaticDocfileList |
345 | | // - nsHTMLMapElement: mAreas |
346 | | // - HTMLMediaElement: many! |
347 | | // - nsHTMLOutputElement: mDefaultValue, mTokenList |
348 | | // - nsHTMLRowElement: mCells |
349 | | // - nsHTMLSelectElement: mOptions, mRestoreState |
350 | | // - nsHTMLTableElement: mTBodies, mRows, mTableInheritedAttributes |
351 | | // - nsHTMLTableSectionElement: mRows |
352 | | // - nsHTMLTextAreaElement: mControllers, mState |
353 | | // |
354 | | // The following members don't need to be measured: |
355 | | // - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere |
356 | | // |
357 | | virtual void AddSizeOfExcludingThis(nsWindowSizes& aSizes, |
358 | | size_t* aNodeSize) const; |
359 | | |
360 | | // SizeOfIncludingThis doesn't need to be overridden by sub-classes because |
361 | | // sub-classes of nsINode are guaranteed to be laid out in memory in such a |
362 | | // way that |this| points to the start of the allocated object, even in |
363 | | // methods of nsINode's sub-classes, so aSizes.mState.mMallocSizeOf(this) is |
364 | | // always safe to call no matter which object it was invoked on. |
365 | | void AddSizeOfIncludingThis(nsWindowSizes& aSizes, size_t* aNodeSize) const; |
366 | | |
367 | | friend class nsNodeUtils; |
368 | | friend class nsNodeWeakReference; |
369 | | friend class nsNodeSupportsWeakRefTearoff; |
370 | | friend class AttrArray; |
371 | | |
372 | | #ifdef MOZILLA_INTERNAL_API |
373 | | explicit nsINode(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); |
374 | | #endif |
375 | | |
376 | | virtual ~nsINode(); |
377 | | |
378 | | /** |
379 | | * Bit-flags to pass (or'ed together) to IsNodeOfType() |
380 | | */ |
381 | | enum { |
382 | | /** form control elements */ |
383 | | eHTML_FORM_CONTROL = 1 << 6, |
384 | | /** animation elements */ |
385 | | eANIMATION = 1 << 10, |
386 | | /** filter elements that implement SVGFilterPrimitiveStandardAttributes */ |
387 | | eFILTER = 1 << 11, |
388 | | /** SVGGeometryElement */ |
389 | | eSHAPE = 1 << 12 |
390 | | }; |
391 | | |
392 | | /** |
393 | | * API for doing a quick check if a content is of a given |
394 | | * type, such as Text, Document, Comment ... Use this when you can instead of |
395 | | * checking the tag. |
396 | | * |
397 | | * @param aFlags what types you want to test for (see above) |
398 | | * @return whether the content matches ALL flags passed in |
399 | | */ |
400 | | virtual bool IsNodeOfType(uint32_t aFlags) const = 0; |
401 | | |
402 | | bool IsContainerNode() const |
403 | | { |
404 | | return IsElement() || IsDocument() || IsDocumentFragment(); |
405 | | } |
406 | | |
407 | | bool IsSlotable() const |
408 | | { |
409 | | return IsElement() || IsText(); |
410 | | } |
411 | | |
412 | | /** |
413 | | * Returns true if this is a document node. |
414 | | */ |
415 | | bool IsDocument() const |
416 | | { |
417 | | // One less pointer-chase than checking NodeType(). |
418 | | return !GetParentNode() && IsInUncomposedDoc(); |
419 | | } |
420 | | |
421 | | /** |
422 | | * Return this node as a document. Asserts IsDocument(). |
423 | | * |
424 | | * This is defined inline in nsIDocument.h. |
425 | | */ |
426 | | inline nsIDocument* AsDocument(); |
427 | | inline const nsIDocument* AsDocument() const; |
428 | | |
429 | | /** |
430 | | * Returns true if this is a document fragment node. |
431 | | */ |
432 | | bool IsDocumentFragment() const |
433 | | { |
434 | | return NodeType() == DOCUMENT_FRAGMENT_NODE; |
435 | | } |
436 | | |
437 | | /** |
438 | | * Return this node as a document fragment. Asserts IsDocumentFragment(). |
439 | | * |
440 | | * This is defined inline in DocumentFragment.h. |
441 | | */ |
442 | | inline mozilla::dom::DocumentFragment* AsDocumentFragment(); |
443 | | inline const mozilla::dom::DocumentFragment* AsDocumentFragment() const; |
444 | | |
445 | | virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; |
446 | | |
447 | | /** |
448 | | * Hook for constructing JS::ubi::Concrete specializations for memory reporting. |
449 | | * Specializations are defined in NodeUbiReporting.h. |
450 | | */ |
451 | | virtual void ConstructUbiNode(void* storage) = 0; |
452 | | |
453 | | /** |
454 | | * returns true if we are in priviliged code or |
455 | | * layout.css.getBoxQuads.enabled == true. |
456 | | */ |
457 | | static bool HasBoxQuadsSupport(JSContext* aCx, JSObject* /* unused */); |
458 | | |
459 | | protected: |
460 | | /** |
461 | | * WrapNode is called from WrapObject to actually wrap this node, WrapObject |
462 | | * does some additional checks and fix-up that's common to all nodes. WrapNode |
463 | | * should just call the DOM binding's Wrap function. |
464 | | * |
465 | | * aGivenProto is the prototype to use (or null if the default one should be |
466 | | * used) and should just be passed directly on to the DOM binding's Wrap |
467 | | * function. |
468 | | */ |
469 | | virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) = 0; |
470 | | |
471 | | public: |
472 | | mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h |
473 | | |
474 | | /** |
475 | | * Return the scope chain parent for this node, for use in things |
476 | | * like event handler compilation. Returning null means to use the |
477 | | * global object as the scope chain parent. |
478 | | */ |
479 | | virtual nsINode* GetScopeChainParent() const; |
480 | | |
481 | | /** |
482 | | * Return whether the node is an Element node |
483 | | */ |
484 | | bool IsElement() const |
485 | | { |
486 | | return GetBoolFlag(NodeIsElement); |
487 | | } |
488 | | |
489 | | /** |
490 | | * Return this node as an Element. Should only be used for nodes |
491 | | * for which IsElement() is true. This is defined inline in Element.h. |
492 | | */ |
493 | | inline mozilla::dom::Element* AsElement(); |
494 | | inline const mozilla::dom::Element* AsElement() const; |
495 | | |
496 | | /** |
497 | | * Return this node as nsIContent. Should only be used for nodes for which |
498 | | * IsContent() is true. This is defined inline in nsIContent.h. |
499 | | */ |
500 | | inline nsIContent* AsContent(); |
501 | | inline const nsIContent* AsContent() const; |
502 | | |
503 | | /* |
504 | | * Return whether the node is a Text node (which might be an actual |
505 | | * textnode, or might be a CDATA section). |
506 | | */ |
507 | | bool IsText() const |
508 | | { |
509 | | uint32_t nodeType = NodeType(); |
510 | | return nodeType == TEXT_NODE || nodeType == CDATA_SECTION_NODE; |
511 | | } |
512 | | |
513 | | /** |
514 | | * Return this node as Text if it is one, otherwise null. This is defined |
515 | | * inline in Text.h. |
516 | | */ |
517 | | inline mozilla::dom::Text* GetAsText(); |
518 | | inline const mozilla::dom::Text* GetAsText() const; |
519 | | |
520 | | /** |
521 | | * Return this node as Text. Asserts IsText(). This is defined inline in |
522 | | * Text.h. |
523 | | */ |
524 | | inline mozilla::dom::Text* AsText(); |
525 | | inline const mozilla::dom::Text* AsText() const; |
526 | | |
527 | | /* |
528 | | * Return whether the node is a ProcessingInstruction node. |
529 | | */ |
530 | | bool IsProcessingInstruction() const |
531 | | { |
532 | | return NodeType() == PROCESSING_INSTRUCTION_NODE; |
533 | | } |
534 | | |
535 | | /* |
536 | | * Return whether the node is a CharacterData node (text, cdata, |
537 | | * comment, processing instruction) |
538 | | */ |
539 | | bool IsCharacterData() const |
540 | | { |
541 | | uint32_t nodeType = NodeType(); |
542 | | return nodeType == TEXT_NODE || |
543 | | nodeType == CDATA_SECTION_NODE || |
544 | | nodeType == PROCESSING_INSTRUCTION_NODE || |
545 | | nodeType == COMMENT_NODE; |
546 | | } |
547 | | |
548 | | /** |
549 | | * Return whether the node is a Comment node. |
550 | | */ |
551 | | bool IsComment() const |
552 | | { |
553 | | return NodeType() == COMMENT_NODE; |
554 | | } |
555 | | |
556 | | /** |
557 | | * Return whether the node is an Attr node. |
558 | | */ |
559 | | bool IsAttr() const |
560 | | { |
561 | | return NodeType() == ATTRIBUTE_NODE; |
562 | | } |
563 | | |
564 | | /** |
565 | | * Return if this node has any children. |
566 | | */ |
567 | | bool HasChildren() const { return !!mFirstChild; } |
568 | | |
569 | | /** |
570 | | * Get the number of children |
571 | | * @return the number of children |
572 | | */ |
573 | | uint32_t GetChildCount() const |
574 | | { |
575 | | return mChildCount; |
576 | | } |
577 | | |
578 | | /** |
579 | | * NOTE: this function is going to be removed soon (hopefully!) Don't use it |
580 | | * in new code. |
581 | | * |
582 | | * Get a child by index |
583 | | * @param aIndex the index of the child to get |
584 | | * @return the child, or null if index out of bounds |
585 | | */ |
586 | | nsIContent* GetChildAt_Deprecated(uint32_t aIndex) const; |
587 | | |
588 | | /** |
589 | | * Get the index of a child within this content |
590 | | * @param aPossibleChild the child to get the index of. |
591 | | * @return the index of the child, or -1 if not a child |
592 | | * |
593 | | * If the return value is not -1, then calling GetChildAt_Deprecated() with |
594 | | * that value will return aPossibleChild. |
595 | | */ |
596 | | virtual int32_t ComputeIndexOf(const nsINode* aPossibleChild) const; |
597 | | |
598 | | /** |
599 | | * Returns the "node document" of this node. |
600 | | * |
601 | | * https://dom.spec.whatwg.org/#concept-node-document |
602 | | * |
603 | | * Note that in the case that this node is a document node this method |
604 | | * will return |this|. That is different to the Node.ownerDocument DOM |
605 | | * attribute (implemented by nsINode::GetOwnerDocument) which is specified to |
606 | | * be null in that case: |
607 | | * |
608 | | * https://dom.spec.whatwg.org/#dom-node-ownerdocument |
609 | | * |
610 | | * For all other cases OwnerDoc and GetOwnerDocument behave identically. |
611 | | */ |
612 | | nsIDocument* OwnerDoc() const |
613 | 0 | { |
614 | 0 | return mNodeInfo->GetDocument(); |
615 | 0 | } |
616 | | |
617 | | /** |
618 | | * Return the "owner document" of this node as an nsINode*. Implemented |
619 | | * in nsIDocument.h. |
620 | | */ |
621 | | inline nsINode* OwnerDocAsNode() const; |
622 | | |
623 | | /** |
624 | | * Returns true if the content has an ancestor that is a document. |
625 | | * |
626 | | * @return whether this content is in a document tree |
627 | | */ |
628 | | bool IsInUncomposedDoc() const |
629 | 0 | { |
630 | 0 | return GetBoolFlag(IsInDocument); |
631 | 0 | } |
632 | | |
633 | | /** |
634 | | * Get the document that this content is currently in, if any. This will be |
635 | | * null if the content has no ancestor that is a document. |
636 | | * |
637 | | * @return the current document |
638 | | */ |
639 | | |
640 | | nsIDocument* GetUncomposedDoc() const |
641 | 0 | { |
642 | 0 | return IsInUncomposedDoc() ? OwnerDoc() : nullptr; |
643 | 0 | } |
644 | | |
645 | | /** |
646 | | * Returns true if we're connected, and thus GetComposedDoc() would return a |
647 | | * non-null value. |
648 | | */ |
649 | | bool IsInComposedDoc() const |
650 | | { |
651 | | return GetBoolFlag(IsConnected); |
652 | | } |
653 | | |
654 | | /** |
655 | | * This method returns the owner document if the node is connected to it |
656 | | * (as defined in the DOM spec), otherwise it returns null. |
657 | | * In other words, returns non-null even in the case the node is in |
658 | | * Shadow DOM, if there is a possibly shadow boundary crossing path from |
659 | | * the node to its owner document. |
660 | | */ |
661 | | nsIDocument* GetComposedDoc() const |
662 | 0 | { |
663 | 0 | return IsInComposedDoc() ? OwnerDoc() : nullptr; |
664 | 0 | } |
665 | | |
666 | | /** |
667 | | * Returns OwnerDoc() if the node is in uncomposed document and ShadowRoot if |
668 | | * the node is in Shadow DOM and is in composed document. |
669 | | */ |
670 | | mozilla::dom::DocumentOrShadowRoot* GetUncomposedDocOrConnectedShadowRoot() const; |
671 | | |
672 | | /** |
673 | | * The values returned by this function are the ones defined for |
674 | | * Node.nodeType |
675 | | */ |
676 | | uint16_t NodeType() const |
677 | | { |
678 | | return mNodeInfo->NodeType(); |
679 | | } |
680 | | const nsString& NodeName() const |
681 | | { |
682 | | return mNodeInfo->NodeName(); |
683 | | } |
684 | | const nsString& LocalName() const |
685 | | { |
686 | | return mNodeInfo->LocalName(); |
687 | | } |
688 | | |
689 | | /** |
690 | | * Get the NodeInfo for this element |
691 | | * @return the nodes node info |
692 | | */ |
693 | | inline mozilla::dom::NodeInfo* NodeInfo() const |
694 | 0 | { |
695 | 0 | return mNodeInfo; |
696 | 0 | } |
697 | | |
698 | | inline bool IsInNamespace(int32_t aNamespace) const |
699 | | { |
700 | | return mNodeInfo->NamespaceID() == aNamespace; |
701 | | } |
702 | | |
703 | | /** |
704 | | * Returns the DocGroup of the "node document" of this node. |
705 | | */ |
706 | | DocGroup* GetDocGroup() const; |
707 | | |
708 | | /** |
709 | | * Print a debugger friendly descriptor of this element. This will describe |
710 | | * the position of this element in the document. |
711 | | */ |
712 | | friend std::ostream& operator<<(std::ostream& aStream, const nsINode& aNode); |
713 | | |
714 | | protected: |
715 | | // These 2 methods are useful for the recursive templates IsHTMLElement, |
716 | | // IsSVGElement, etc. |
717 | | inline bool IsNodeInternal() const |
718 | 0 | { |
719 | 0 | return false; |
720 | 0 | } |
721 | | |
722 | | template<typename First, typename... Args> |
723 | | inline bool IsNodeInternal(First aFirst, Args... aArgs) const |
724 | 0 | { |
725 | 0 | return mNodeInfo->Equals(aFirst) || IsNodeInternal(aArgs...); |
726 | 0 | } Unexecuted instantiation: bool nsINode::IsNodeInternal<nsStaticAtom*, nsStaticAtom*>(nsStaticAtom*, nsStaticAtom*) const Unexecuted instantiation: bool nsINode::IsNodeInternal<nsStaticAtom*>(nsStaticAtom*) const |
727 | | |
728 | | public: |
729 | | inline bool IsHTMLElement() const |
730 | | { |
731 | | return IsElement() && IsInNamespace(kNameSpaceID_XHTML); |
732 | | } |
733 | | |
734 | | inline bool IsHTMLElement(nsAtom* aTag) const |
735 | | { |
736 | | return IsElement() && mNodeInfo->Equals(aTag, kNameSpaceID_XHTML); |
737 | | } |
738 | | |
739 | | template<typename First, typename... Args> |
740 | | inline bool IsAnyOfHTMLElements(First aFirst, Args... aArgs) const |
741 | 0 | { |
742 | 0 | return IsHTMLElement() && IsNodeInternal(aFirst, aArgs...); |
743 | 0 | } |
744 | | |
745 | | inline bool IsSVGElement() const |
746 | | { |
747 | | return IsElement() && IsInNamespace(kNameSpaceID_SVG); |
748 | | } |
749 | | |
750 | | inline bool IsSVGElement(nsAtom* aTag) const |
751 | | { |
752 | | return IsElement() && mNodeInfo->Equals(aTag, kNameSpaceID_SVG); |
753 | | } |
754 | | |
755 | | template<typename First, typename... Args> |
756 | | inline bool IsAnyOfSVGElements(First aFirst, Args... aArgs) const |
757 | | { |
758 | | return IsSVGElement() && IsNodeInternal(aFirst, aArgs...); |
759 | | } |
760 | | |
761 | | inline bool IsXULElement() const |
762 | | { |
763 | | return IsElement() && IsInNamespace(kNameSpaceID_XUL); |
764 | | } |
765 | | |
766 | | inline bool IsXULElement(nsAtom* aTag) const |
767 | 0 | { |
768 | 0 | return IsElement() && mNodeInfo->Equals(aTag, kNameSpaceID_XUL); |
769 | 0 | } |
770 | | |
771 | | template<typename First, typename... Args> |
772 | | inline bool IsAnyOfXULElements(First aFirst, Args... aArgs) const |
773 | | { |
774 | | return IsXULElement() && IsNodeInternal(aFirst, aArgs...); |
775 | | } |
776 | | |
777 | | inline bool IsMathMLElement() const |
778 | 0 | { |
779 | 0 | return IsElement() && IsInNamespace(kNameSpaceID_MathML); |
780 | 0 | } |
781 | | |
782 | | inline bool IsMathMLElement(nsAtom* aTag) const |
783 | 0 | { |
784 | 0 | return IsElement() && mNodeInfo->Equals(aTag, kNameSpaceID_MathML); |
785 | 0 | } |
786 | | |
787 | | template<typename First, typename... Args> |
788 | | inline bool IsAnyOfMathMLElements(First aFirst, Args... aArgs) const |
789 | | { |
790 | | return IsMathMLElement() && IsNodeInternal(aFirst, aArgs...); |
791 | | } |
792 | | |
793 | | bool IsShadowRoot() const |
794 | | { |
795 | | const bool isShadowRoot = IsInShadowTree() && !GetParentNode(); |
796 | | MOZ_ASSERT_IF(isShadowRoot, IsDocumentFragment()); |
797 | | return isShadowRoot; |
798 | | } |
799 | | |
800 | | /** |
801 | | * Insert a content node before another or at the end. |
802 | | * This method handles calling BindToTree on the child appropriately. |
803 | | * |
804 | | * @param aKid the content to insert |
805 | | * @param aBeforeThis an existing node. Use nullptr if you want to |
806 | | * add aKid at the end. |
807 | | * @param aNotify whether to notify the document (current document for |
808 | | * nsIContent, and |this| for nsIDocument) that the insert has |
809 | | * occurred |
810 | | * |
811 | | * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more |
812 | | * than one element node as a child of a document. Doing this will also |
813 | | * assert -- you shouldn't be doing it! Check with |
814 | | * nsIDocument::GetRootElement() first if you're not sure. Apart from this |
815 | | * one constraint, this doesn't do any checking on whether aKid is a valid |
816 | | * child of |this|. |
817 | | * |
818 | | * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree). |
819 | | */ |
820 | | virtual nsresult InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis, |
821 | | bool aNotify); |
822 | | |
823 | | /** |
824 | | * Append a content node to the end of the child list. This method handles |
825 | | * calling BindToTree on the child appropriately. |
826 | | * |
827 | | * @param aKid the content to append |
828 | | * @param aNotify whether to notify the document (current document for |
829 | | * nsIContent, and |this| for nsIDocument) that the append has |
830 | | * occurred |
831 | | * |
832 | | * @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more |
833 | | * than one element node as a child of a document. Doing this will also |
834 | | * assert -- you shouldn't be doing it! Check with |
835 | | * nsIDocument::GetRootElement() first if you're not sure. Apart from this |
836 | | * one constraint, this doesn't do any checking on whether aKid is a valid |
837 | | * child of |this|. |
838 | | * |
839 | | * @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree). |
840 | | */ |
841 | | nsresult AppendChildTo(nsIContent* aKid, bool aNotify) |
842 | | { |
843 | | return InsertChildBefore(aKid, nullptr, aNotify); |
844 | | } |
845 | | |
846 | | /** |
847 | | * Remove a child from this node. This method handles calling UnbindFromTree |
848 | | * on the child appropriately. |
849 | | * |
850 | | * @param aKid the content to remove |
851 | | * @param aNotify whether to notify the document (current document for |
852 | | * nsIContent, and |this| for nsIDocument) that the remove has |
853 | | * occurred |
854 | | */ |
855 | | virtual void RemoveChildNode(nsIContent* aKid, bool aNotify); |
856 | | |
857 | | /** |
858 | | * Get a property associated with this node. |
859 | | * |
860 | | * @param aPropertyName name of property to get. |
861 | | * @param aStatus out parameter for storing resulting status. |
862 | | * Set to NS_PROPTABLE_PROP_NOT_THERE if the property |
863 | | * is not set. |
864 | | * @return the property. Null if the property is not set |
865 | | * (though a null return value does not imply the |
866 | | * property was not set, i.e. it can be set to null). |
867 | | */ |
868 | | void* GetProperty(nsAtom* aPropertyName, nsresult* aStatus = nullptr) const; |
869 | | |
870 | | /** |
871 | | * Set a property to be associated with this node. This will overwrite an |
872 | | * existing value if one exists. The existing value is destroyed using the |
873 | | * destructor function given when that value was set. |
874 | | * |
875 | | * @param aPropertyName name of property to set. |
876 | | * @param aValue new value of property. |
877 | | * @param aDtor destructor function to be used when this property |
878 | | * is destroyed. |
879 | | * @param aTransfer if true the property will not be deleted when the |
880 | | * ownerDocument of the node changes, if false it |
881 | | * will be deleted. |
882 | | * |
883 | | * @return NS_PROPTABLE_PROP_OVERWRITTEN (success value) if the property |
884 | | * was already set |
885 | | * @throws NS_ERROR_OUT_OF_MEMORY if that occurs |
886 | | */ |
887 | | nsresult SetProperty(nsAtom* aPropertyName, |
888 | | void* aValue, |
889 | | NSPropertyDtorFunc aDtor = nullptr, |
890 | | bool aTransfer = false); |
891 | | |
892 | | /** |
893 | | * A generic destructor for property values allocated with new. |
894 | | */ |
895 | | template<class T> |
896 | | static void DeleteProperty(void*, nsAtom*, void* aPropertyValue, void*) |
897 | 0 | { |
898 | 0 | delete static_cast<T *>(aPropertyValue); |
899 | 0 | } Unexecuted instantiation: void nsINode::DeleteProperty<mozilla::gfx::PointTyped<mozilla::CSSPixel, float> >(void*, nsAtom*, void*, void*) Unexecuted instantiation: void nsINode::DeleteProperty<mozilla::TimeStamp>(void*, nsAtom*, void*, void*) |
900 | | |
901 | | /** |
902 | | * Destroys a property associated with this node. The value is destroyed |
903 | | * using the destruction function given when that value was set. |
904 | | * |
905 | | * @param aPropertyName name of property to destroy. |
906 | | */ |
907 | | void DeleteProperty(nsAtom* aPropertyName); |
908 | | |
909 | | /** |
910 | | * Unset a property associated with this node. The value will not be |
911 | | * destroyed but rather returned. It is the caller's responsibility to |
912 | | * destroy the value after that point. |
913 | | * |
914 | | * @param aPropertyName name of property to unset. |
915 | | * @param aStatus out parameter for storing resulting status. |
916 | | * Set to NS_PROPTABLE_PROP_NOT_THERE if the property |
917 | | * is not set. |
918 | | * @return the property. Null if the property is not set |
919 | | * (though a null return value does not imply the |
920 | | * property was not set, i.e. it can be set to null). |
921 | | */ |
922 | | void* UnsetProperty(nsAtom* aPropertyName, nsresult* aStatus = nullptr); |
923 | | |
924 | | bool HasProperties() const |
925 | | { |
926 | | return HasFlag(NODE_HAS_PROPERTIES); |
927 | | } |
928 | | |
929 | | /** |
930 | | * Return the principal of this node. This is guaranteed to never be a null |
931 | | * pointer. |
932 | | */ |
933 | | nsIPrincipal* NodePrincipal() const { |
934 | | return mNodeInfo->NodeInfoManager()->DocumentPrincipal(); |
935 | | } |
936 | | |
937 | | /** |
938 | | * Get the parent nsIContent for this node. |
939 | | * @return the parent, or null if no parent or the parent is not an nsIContent |
940 | | */ |
941 | | nsIContent* GetParent() const { |
942 | | return MOZ_LIKELY(GetBoolFlag(ParentIsContent)) ? |
943 | | reinterpret_cast<nsIContent*>(mParent) : nullptr; |
944 | | } |
945 | | |
946 | | /** |
947 | | * Get the parent nsINode for this node. This can be either an nsIContent, |
948 | | * an nsIDocument or an Attr. |
949 | | * @return the parent node |
950 | | */ |
951 | | nsINode* GetParentNode() const |
952 | | { |
953 | | return mParent; |
954 | | } |
955 | | |
956 | | /** |
957 | | * This is similar to above, but in case 'this' is ShadowRoot, we return its |
958 | | * host element. |
959 | | */ |
960 | | nsINode* GetParentOrHostNode() const; |
961 | | |
962 | | enum FlattenedParentType { eNotForStyle, eForStyle }; |
963 | | |
964 | | /** |
965 | | * Returns the node that is the parent of this node in the flattened |
966 | | * tree. This differs from the normal parent if the node is filtered |
967 | | * into an insertion point, or if the node is a direct child of a |
968 | | * shadow root. |
969 | | * |
970 | | * @return the flattened tree parent |
971 | | */ |
972 | | inline nsINode* GetFlattenedTreeParentNode() const; |
973 | | |
974 | | nsINode* GetFlattenedTreeParentNodeNonInline() const; |
975 | | |
976 | | /** |
977 | | * Like GetFlattenedTreeParentNode, but returns the document for any native |
978 | | * anonymous content that was generated for ancestor frames of the document |
979 | | * element's primary frame, such as scrollbar elements created by the root |
980 | | * scroll frame. |
981 | | */ |
982 | | inline nsINode* GetFlattenedTreeParentNodeForStyle() const; |
983 | | |
984 | | inline mozilla::dom::Element* GetFlattenedTreeParentElement() const; |
985 | | inline mozilla::dom::Element* GetFlattenedTreeParentElementForStyle() const; |
986 | | |
987 | | /** |
988 | | * Get the parent nsINode for this node if it is an Element. |
989 | | * |
990 | | * Defined inline in Element.h |
991 | | * |
992 | | * @return the parent node |
993 | | */ |
994 | | inline mozilla::dom::Element* GetParentElement() const; |
995 | | |
996 | | /** |
997 | | * Get the parent Element of this node, traversing over a ShadowRoot |
998 | | * to its host if necessary. |
999 | | */ |
1000 | | mozilla::dom::Element* GetParentElementCrossingShadowRoot() const; |
1001 | | |
1002 | | /** |
1003 | | * Get the root of the subtree this node belongs to. This never returns |
1004 | | * null. It may return 'this' (e.g. for document nodes, and nodes that |
1005 | | * are the roots of disconnected subtrees). |
1006 | | */ |
1007 | | nsINode* SubtreeRoot() const; |
1008 | | |
1009 | | /* |
1010 | | * Get context object's shadow-including root if options's composed is true, |
1011 | | * and context object's root otherwise. |
1012 | | */ |
1013 | | nsINode* GetRootNode(const mozilla::dom::GetRootNodeOptions& aOptions); |
1014 | | |
1015 | | virtual mozilla::EventListenerManager* |
1016 | | GetExistingListenerManager() const override; |
1017 | | virtual mozilla::EventListenerManager* |
1018 | | GetOrCreateListenerManager() override; |
1019 | | |
1020 | | bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final; |
1021 | | |
1022 | | virtual bool IsApzAware() const override; |
1023 | | |
1024 | | virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override; |
1025 | | virtual nsIGlobalObject* GetOwnerGlobal() const override; |
1026 | | |
1027 | | using mozilla::dom::EventTarget::DispatchEvent; |
1028 | | bool DispatchEvent(mozilla::dom::Event& aEvent, |
1029 | | mozilla::dom::CallerType aCallerType, |
1030 | | mozilla::ErrorResult& aRv) override; |
1031 | | |
1032 | | nsresult PostHandleEvent(mozilla::EventChainPostVisitor& aVisitor) override; |
1033 | | |
1034 | | /** |
1035 | | * Adds a mutation observer to be notified when this node, or any of its |
1036 | | * descendants, are modified. The node will hold a weak reference to the |
1037 | | * observer, which means that it is the responsibility of the observer to |
1038 | | * remove itself in case it dies before the node. If an observer is added |
1039 | | * while observers are being notified, it may also be notified. In general, |
1040 | | * adding observers while inside a notification is not a good idea. An |
1041 | | * observer that is already observing the node must not be added without |
1042 | | * being removed first. |
1043 | | * |
1044 | | * For mutation observers that implement nsIAnimationObserver, use |
1045 | | * AddAnimationObserver instead. |
1046 | | */ |
1047 | | void AddMutationObserver(nsIMutationObserver* aMutationObserver) |
1048 | | { |
1049 | | nsSlots* s = Slots(); |
1050 | | NS_ASSERTION(s->mMutationObservers.IndexOf(aMutationObserver) == |
1051 | | nsTArray<int>::NoIndex, |
1052 | | "Observer already in the list"); |
1053 | | s->mMutationObservers.AppendElement(aMutationObserver); |
1054 | | } |
1055 | | |
1056 | | /** |
1057 | | * Same as above, but only adds the observer if its not observing |
1058 | | * the node already. |
1059 | | * |
1060 | | * For mutation observers that implement nsIAnimationObserver, use |
1061 | | * AddAnimationObserverUnlessExists instead. |
1062 | | */ |
1063 | | void AddMutationObserverUnlessExists(nsIMutationObserver* aMutationObserver) |
1064 | | { |
1065 | | nsSlots* s = Slots(); |
1066 | | s->mMutationObservers.AppendElementUnlessExists(aMutationObserver); |
1067 | | } |
1068 | | |
1069 | | /** |
1070 | | * Same as AddMutationObserver, but for nsIAnimationObservers. This |
1071 | | * additionally records on the document that animation observers have |
1072 | | * been registered, which is used to determine whether notifications |
1073 | | * must be fired when animations are added, removed or changed. |
1074 | | */ |
1075 | | void AddAnimationObserver(nsIAnimationObserver* aAnimationObserver); |
1076 | | |
1077 | | /** |
1078 | | * Same as above, but only adds the observer if its not observing |
1079 | | * the node already. |
1080 | | */ |
1081 | | void AddAnimationObserverUnlessExists(nsIAnimationObserver* aAnimationObserver); |
1082 | | |
1083 | | /** |
1084 | | * Removes a mutation observer. |
1085 | | */ |
1086 | | void RemoveMutationObserver(nsIMutationObserver* aMutationObserver) |
1087 | | { |
1088 | | nsSlots* s = GetExistingSlots(); |
1089 | | if (s) { |
1090 | | s->mMutationObservers.RemoveElement(aMutationObserver); |
1091 | | } |
1092 | | } |
1093 | | |
1094 | | /** |
1095 | | * Clones this node. This needs to be overriden by all node classes. aNodeInfo |
1096 | | * should be identical to this node's nodeInfo, except for the document which |
1097 | | * may be different. When cloning an element, all attributes of the element |
1098 | | * will be cloned. The children of the node will not be cloned. |
1099 | | * |
1100 | | * @param aNodeInfo the nodeinfo to use for the clone |
1101 | | * @param aResult the clone |
1102 | | */ |
1103 | | virtual nsresult Clone(mozilla::dom::NodeInfo*, nsINode** aResult) const = 0; |
1104 | | |
1105 | | // This class can be extended by subclasses that wish to store more |
1106 | | // information in the slots. |
1107 | | class nsSlots |
1108 | | { |
1109 | | public: |
1110 | | nsSlots(); |
1111 | | |
1112 | | // If needed we could remove the vtable pointer this dtor causes by |
1113 | | // putting a DestroySlots function on nsINode |
1114 | | virtual ~nsSlots(); |
1115 | | |
1116 | | virtual void Traverse(nsCycleCollectionTraversalCallback&); |
1117 | | virtual void Unlink(); |
1118 | | |
1119 | | /** |
1120 | | * A list of mutation observers |
1121 | | */ |
1122 | | nsAutoTObserverArray<nsIMutationObserver*, 1> mMutationObservers; |
1123 | | |
1124 | | /** |
1125 | | * An object implementing NodeList for this content (childNodes) |
1126 | | * @see NodeList |
1127 | | * @see nsGenericHTMLElement::GetChildNodes |
1128 | | */ |
1129 | | RefPtr<nsAttrChildContentList> mChildNodes; |
1130 | | |
1131 | | /** |
1132 | | * Weak reference to this node. This is cleared by the destructor of |
1133 | | * nsNodeWeakReference. |
1134 | | */ |
1135 | | nsNodeWeakReference* MOZ_NON_OWNING_REF mWeakReference; |
1136 | | |
1137 | | /** |
1138 | | * A set of ranges which are in the selection and which have this node as |
1139 | | * their endpoints' common ancestor. This is a UniquePtr instead of just a |
1140 | | * LinkedList, because that prevents us from pushing DOMSlots up to the next |
1141 | | * allocation bucket size, at the cost of some complexity. |
1142 | | */ |
1143 | | mozilla::UniquePtr<mozilla::LinkedList<nsRange>> mCommonAncestorRanges; |
1144 | | |
1145 | | /** |
1146 | | * Number of descendant nodes in the uncomposed document that have been |
1147 | | * explicitly set as editable. |
1148 | | */ |
1149 | | uint32_t mEditableDescendantCount; |
1150 | | }; |
1151 | | |
1152 | | /** |
1153 | | * Functions for managing flags and slots |
1154 | | */ |
1155 | | #ifdef DEBUG |
1156 | | nsSlots* DebugGetSlots() |
1157 | | { |
1158 | | return Slots(); |
1159 | | } |
1160 | | #endif |
1161 | | |
1162 | | void SetFlags(FlagsType aFlagsToSet) |
1163 | | { |
1164 | | NS_ASSERTION(!(aFlagsToSet & (NODE_IS_ANONYMOUS_ROOT | |
1165 | | NODE_IS_NATIVE_ANONYMOUS_ROOT | |
1166 | | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | |
1167 | | NODE_DESCENDANTS_NEED_FRAMES | |
1168 | | NODE_NEEDS_FRAME | |
1169 | | NODE_CHROME_ONLY_ACCESS)) || |
1170 | | IsContent(), |
1171 | | "Flag only permitted on nsIContent nodes"); |
1172 | | nsWrapperCache::SetFlags(aFlagsToSet); |
1173 | | } |
1174 | | |
1175 | | void UnsetFlags(FlagsType aFlagsToUnset) |
1176 | | { |
1177 | | NS_ASSERTION(!(aFlagsToUnset & |
1178 | | (NODE_IS_ANONYMOUS_ROOT | |
1179 | | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | |
1180 | | NODE_IS_NATIVE_ANONYMOUS_ROOT)), |
1181 | | "Trying to unset write-only flags"); |
1182 | | nsWrapperCache::UnsetFlags(aFlagsToUnset); |
1183 | | } |
1184 | | |
1185 | | void ChangeEditableDescendantCount(int32_t aDelta); |
1186 | | |
1187 | | /** |
1188 | | * Returns the count of descendant nodes in the uncomposed |
1189 | | * document that are explicitly set as editable. |
1190 | | */ |
1191 | | uint32_t EditableDescendantCount(); |
1192 | | |
1193 | | /** |
1194 | | * Sets the editable descendant count to 0. The editable |
1195 | | * descendant count only counts explicitly editable nodes |
1196 | | * that are in the uncomposed document so this method |
1197 | | * should be called when nodes are are removed from it. |
1198 | | */ |
1199 | | void ResetEditableDescendantCount(); |
1200 | | |
1201 | | void SetEditableFlag(bool aEditable) |
1202 | | { |
1203 | | if (aEditable) { |
1204 | | SetFlags(NODE_IS_EDITABLE); |
1205 | | } |
1206 | | else { |
1207 | | UnsetFlags(NODE_IS_EDITABLE); |
1208 | | } |
1209 | | } |
1210 | | |
1211 | | inline bool IsEditable() const; |
1212 | | |
1213 | | /** |
1214 | | * Returns true if |this| or any of its ancestors is native anonymous. |
1215 | | */ |
1216 | | bool IsInNativeAnonymousSubtree() const |
1217 | 0 | { |
1218 | | #ifdef DEBUG |
1219 | | if (HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE)) { |
1220 | | return true; |
1221 | | } |
1222 | | CheckNotNativeAnonymous(); |
1223 | | return false; |
1224 | | #else |
1225 | | return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE); |
1226 | 0 | #endif |
1227 | 0 | } |
1228 | | |
1229 | | bool IsInAnonymousSubtree() const; |
1230 | | |
1231 | | bool IsInSVGUseShadowTree() const |
1232 | | { |
1233 | | return !!GetContainingSVGUseShadowHost(); |
1234 | | } |
1235 | | |
1236 | | mozilla::dom::SVGUseElement* GetContainingSVGUseShadowHost() const |
1237 | | { |
1238 | | if (!IsInShadowTree()) { |
1239 | | return nullptr; |
1240 | | } |
1241 | | return DoGetContainingSVGUseShadowHost(); |
1242 | | } |
1243 | | |
1244 | | bool IsInUAWidget() const; |
1245 | | |
1246 | | // True for native anonymous content and for XBL content if the binding |
1247 | | // has chromeOnlyContent="true". |
1248 | | bool ChromeOnlyAccess() const |
1249 | | { |
1250 | | return HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE | NODE_CHROME_ONLY_ACCESS); |
1251 | | } |
1252 | | |
1253 | | bool IsInShadowTree() const |
1254 | 0 | { |
1255 | 0 | return HasFlag(NODE_IS_IN_SHADOW_TREE); |
1256 | 0 | } |
1257 | | |
1258 | | /** |
1259 | | * Returns true if |this| node is the common ancestor of the start/end |
1260 | | * nodes of a Range in a Selection or a descendant of such a common ancestor. |
1261 | | * This node is definitely not selected when |false| is returned, but it may |
1262 | | * or may not be selected when |true| is returned. |
1263 | | */ |
1264 | | bool IsSelectionDescendant() const |
1265 | | { |
1266 | | return IsDescendantOfCommonAncestorForRangeInSelection() || |
1267 | | IsCommonAncestorForRangeInSelection(); |
1268 | | } |
1269 | | |
1270 | | /** |
1271 | | * Get the root content of an editor. So, this node must be a descendant of |
1272 | | * an editor. Note that this should be only used for getting input or textarea |
1273 | | * editor's root content. This method doesn't support HTML editors. |
1274 | | */ |
1275 | | nsIContent* GetTextEditorRootContent( |
1276 | | mozilla::TextEditor** aTextEditor = nullptr); |
1277 | | |
1278 | | /** |
1279 | | * Get the nearest selection root, ie. the node that will be selected if the |
1280 | | * user does "Select All" while the focus is in this node. Note that if this |
1281 | | * node is not in an editor, the result comes from the nsFrameSelection that |
1282 | | * is related to aPresShell, so the result might not be the ancestor of this |
1283 | | * node. Be aware that if this node and the computed selection limiter are |
1284 | | * not in same subtree, this returns the root content of the closeset subtree. |
1285 | | */ |
1286 | | nsIContent* GetSelectionRootContent(nsIPresShell* aPresShell); |
1287 | | |
1288 | | nsINodeList* ChildNodes(); |
1289 | | |
1290 | | nsIContent* GetFirstChild() const |
1291 | | { |
1292 | | return mFirstChild; |
1293 | | } |
1294 | | |
1295 | | nsIContent* GetLastChild() const; |
1296 | | |
1297 | | /** |
1298 | | * Implementation is in nsIDocument.h, because it needs to cast from |
1299 | | * nsIDocument* to nsINode*. |
1300 | | */ |
1301 | | nsIDocument* GetOwnerDocument() const; |
1302 | | |
1303 | | void Normalize(); |
1304 | | |
1305 | | /** |
1306 | | * Get the base URI for any relative URIs within this piece of |
1307 | | * content. Generally, this is the document's base URI, but certain |
1308 | | * content carries a local base for backward compatibility, and XML |
1309 | | * supports setting a per-node base URI. |
1310 | | * |
1311 | | * @return the base URI |
1312 | | */ |
1313 | | virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const = 0; |
1314 | | already_AddRefed<nsIURI> GetBaseURIObject() const; |
1315 | | |
1316 | | /** |
1317 | | * Return true if the node may be apz aware. There are two cases. One is that |
1318 | | * the node is apz aware (such as HTMLInputElement with number type). The |
1319 | | * other is that the node has apz aware listeners. This is a non-virtual |
1320 | | * function which calls IsNodeApzAwareInternal only when the MayBeApzAware is |
1321 | | * set. We check the details in IsNodeApzAwareInternal which may be overriden |
1322 | | * by child classes |
1323 | | */ |
1324 | | bool IsNodeApzAware() const |
1325 | | { |
1326 | | return NodeMayBeApzAware() ? IsNodeApzAwareInternal() : false; |
1327 | | } |
1328 | | |
1329 | | /** |
1330 | | * Override this function and set the flag MayBeApzAware in case the node has |
1331 | | * to let APZC be aware of it. It's used when the node may handle the apz |
1332 | | * aware events and may do preventDefault to stop APZC to do default actions. |
1333 | | * |
1334 | | * For example, instead of scrolling page by APZ, we handle mouse wheel event |
1335 | | * in HTMLInputElement with number type as increasing / decreasing its value. |
1336 | | */ |
1337 | | virtual bool IsNodeApzAwareInternal() const; |
1338 | | |
1339 | | void GetTextContent(nsAString& aTextContent, |
1340 | | mozilla::OOMReporter& aError) |
1341 | | { |
1342 | | GetTextContentInternal(aTextContent, aError); |
1343 | | } |
1344 | | void SetTextContent(const nsAString& aTextContent, |
1345 | | nsIPrincipal* aSubjectPrincipal, |
1346 | | mozilla::ErrorResult& aError) |
1347 | 0 | { |
1348 | 0 | SetTextContentInternal(aTextContent, aSubjectPrincipal, aError); |
1349 | 0 | } |
1350 | | void SetTextContent(const nsAString& aTextContent, |
1351 | | mozilla::ErrorResult& aError) |
1352 | | { |
1353 | | SetTextContentInternal(aTextContent, nullptr, aError); |
1354 | | } |
1355 | | |
1356 | | mozilla::dom::Element* QuerySelector(const nsAString& aSelector, |
1357 | | mozilla::ErrorResult& aResult); |
1358 | | already_AddRefed<nsINodeList> QuerySelectorAll(const nsAString& aSelector, |
1359 | | mozilla::ErrorResult& aResult); |
1360 | | |
1361 | | protected: |
1362 | | // nsIDocument overrides this with its own (faster) version. This |
1363 | | // should really only be called for elements and document fragments. |
1364 | | mozilla::dom::Element* GetElementById(const nsAString& aId); |
1365 | | |
1366 | | void AppendChildToChildList(nsIContent* aKid); |
1367 | | void InsertChildToChildList(nsIContent* aKid, nsIContent* aNextSibling); |
1368 | | void DisconnectChild(nsIContent* aKid); |
1369 | | |
1370 | | public: |
1371 | | void LookupPrefix(const nsAString& aNamespace, nsAString& aResult); |
1372 | | bool IsDefaultNamespace(const nsAString& aNamespaceURI) |
1373 | 0 | { |
1374 | 0 | nsAutoString defaultNamespace; |
1375 | 0 | LookupNamespaceURI(EmptyString(), defaultNamespace); |
1376 | 0 | return aNamespaceURI.Equals(defaultNamespace); |
1377 | 0 | } |
1378 | | void LookupNamespaceURI(const nsAString& aNamespacePrefix, |
1379 | | nsAString& aNamespaceURI); |
1380 | | |
1381 | | nsIContent* GetNextSibling() const { return mNextSibling; } |
1382 | | nsIContent* GetPreviousSibling() const; |
1383 | | |
1384 | | /** |
1385 | | * Get the next node in the pre-order tree traversal of the DOM. If |
1386 | | * aRoot is non-null, then it must be an ancestor of |this| |
1387 | | * (possibly equal to |this|) and only nodes that are descendants of |
1388 | | * aRoot, not including aRoot itself, will be returned. Returns |
1389 | | * null if there are no more nodes to traverse. |
1390 | | */ |
1391 | | nsIContent* GetNextNode(const nsINode* aRoot = nullptr) const |
1392 | | { |
1393 | | return GetNextNodeImpl(aRoot, false); |
1394 | | } |
1395 | | |
1396 | | /** |
1397 | | * Get the next node in the pre-order tree traversal of the DOM but ignoring |
1398 | | * the children of this node. If aRoot is non-null, then it must be an |
1399 | | * ancestor of |this| (possibly equal to |this|) and only nodes that are |
1400 | | * descendants of aRoot, not including aRoot itself, will be returned. |
1401 | | * Returns null if there are no more nodes to traverse. |
1402 | | */ |
1403 | | nsIContent* GetNextNonChildNode(const nsINode* aRoot = nullptr) const |
1404 | | { |
1405 | | return GetNextNodeImpl(aRoot, true); |
1406 | | } |
1407 | | |
1408 | | /** |
1409 | | * Returns true if 'this' is either document or element or |
1410 | | * document fragment and aOther is a descendant in the same |
1411 | | * anonymous tree. |
1412 | | */ |
1413 | | bool Contains(const nsINode* aOther) const; |
1414 | | |
1415 | | bool UnoptimizableCCNode() const; |
1416 | | |
1417 | | private: |
1418 | | |
1419 | | mozilla::dom::SVGUseElement* DoGetContainingSVGUseShadowHost() const; |
1420 | | |
1421 | | nsIContent* GetNextNodeImpl(const nsINode* aRoot, |
1422 | | const bool aSkipChildren) const |
1423 | | { |
1424 | | // Can't use nsContentUtils::ContentIsDescendantOf here, since we |
1425 | | // can't include it here. |
1426 | | #ifdef DEBUG |
1427 | | if (aRoot) { |
1428 | | const nsINode* cur = this; |
1429 | | for (; cur; cur = cur->GetParentNode()) |
1430 | | if (cur == aRoot) break; |
1431 | | NS_ASSERTION(cur, "aRoot not an ancestor of |this|?"); |
1432 | | } |
1433 | | #endif |
1434 | | if (!aSkipChildren) { |
1435 | | nsIContent* kid = GetFirstChild(); |
1436 | | if (kid) { |
1437 | | return kid; |
1438 | | } |
1439 | | } |
1440 | | if (this == aRoot) { |
1441 | | return nullptr; |
1442 | | } |
1443 | | const nsINode* cur = this; |
1444 | | while (1) { |
1445 | | nsIContent* next = cur->GetNextSibling(); |
1446 | | if (next) { |
1447 | | return next; |
1448 | | } |
1449 | | nsINode* parent = cur->GetParentNode(); |
1450 | | if (parent == aRoot) { |
1451 | | return nullptr; |
1452 | | } |
1453 | | cur = parent; |
1454 | | } |
1455 | | MOZ_ASSERT_UNREACHABLE("How did we get here?"); |
1456 | | } |
1457 | | |
1458 | | public: |
1459 | | |
1460 | | /** |
1461 | | * Get the previous nsIContent in the pre-order tree traversal of the DOM. If |
1462 | | * aRoot is non-null, then it must be an ancestor of |this| |
1463 | | * (possibly equal to |this|) and only nsIContents that are descendants of |
1464 | | * aRoot, including aRoot itself, will be returned. Returns |
1465 | | * null if there are no more nsIContents to traverse. |
1466 | | */ |
1467 | | nsIContent* GetPreviousContent(const nsINode* aRoot = nullptr) const |
1468 | | { |
1469 | | // Can't use nsContentUtils::ContentIsDescendantOf here, since we |
1470 | | // can't include it here. |
1471 | | #ifdef DEBUG |
1472 | | if (aRoot) { |
1473 | | const nsINode* cur = this; |
1474 | | for (; cur; cur = cur->GetParentNode()) |
1475 | | if (cur == aRoot) break; |
1476 | | NS_ASSERTION(cur, "aRoot not an ancestor of |this|?"); |
1477 | | } |
1478 | | #endif |
1479 | | |
1480 | | if (this == aRoot) { |
1481 | | return nullptr; |
1482 | | } |
1483 | | nsIContent* cur = this->GetParent(); |
1484 | | nsIContent* iter = this->GetPreviousSibling(); |
1485 | | while (iter) { |
1486 | | cur = iter; |
1487 | | iter = reinterpret_cast<nsINode*>(iter)->GetLastChild(); |
1488 | | } |
1489 | | return cur; |
1490 | | } |
1491 | | |
1492 | | /** |
1493 | | * Boolean flags |
1494 | | */ |
1495 | | private: |
1496 | | enum BooleanFlag { |
1497 | | // Set if we're being used from -moz-element |
1498 | | NodeHasRenderingObservers, |
1499 | | // Set if our parent chain (including this node itself) terminates |
1500 | | // in a document |
1501 | | IsInDocument, |
1502 | | // Set if we're part of the composed doc. |
1503 | | // https://dom.spec.whatwg.org/#connected |
1504 | | IsConnected, |
1505 | | // Set if mParent is an nsIContent |
1506 | | ParentIsContent, |
1507 | | // Set if this node is an Element |
1508 | | NodeIsElement, |
1509 | | // Set if the element has a non-empty id attribute. This can in rare |
1510 | | // cases lie for nsXMLElement, such as when the node has been moved between |
1511 | | // documents with different id mappings. |
1512 | | ElementHasID, |
1513 | | // Set if the element might have a class. |
1514 | | ElementMayHaveClass, |
1515 | | // Set if the element might have inline style. |
1516 | | ElementMayHaveStyle, |
1517 | | // Set if the element has a name attribute set. |
1518 | | ElementHasName, |
1519 | | // Set if the element might have a contenteditable attribute set. |
1520 | | ElementMayHaveContentEditableAttr, |
1521 | | // Set if the node is the common ancestor of the start/end nodes of a Range |
1522 | | // that is in a Selection. |
1523 | | NodeIsCommonAncestorForRangeInSelection, |
1524 | | // Set if the node is a descendant of a node with the above bit set. |
1525 | | NodeIsDescendantOfCommonAncestorForRangeInSelection, |
1526 | | // Set if CanSkipInCC check has been done for this subtree root. |
1527 | | NodeIsCCMarkedRoot, |
1528 | | // Maybe set if this node is in black subtree. |
1529 | | NodeIsCCBlackTree, |
1530 | | // Maybe set if the node is a root of a subtree |
1531 | | // which needs to be kept in the purple buffer. |
1532 | | NodeIsPurpleRoot, |
1533 | | // Set if the element has some style states locked |
1534 | | ElementHasLockedStyleStates, |
1535 | | // Set if element has pointer locked |
1536 | | ElementHasPointerLock, |
1537 | | // Set if the node may have DOMMutationObserver attached to it. |
1538 | | NodeMayHaveDOMMutationObserver, |
1539 | | // Set if node is Content |
1540 | | NodeIsContent, |
1541 | | // Set if the node has animations or transitions |
1542 | | ElementHasAnimations, |
1543 | | // Set if node has a dir attribute with a valid value (ltr, rtl, or auto). |
1544 | | // Note that we cannot compute this from the dir attribute event state |
1545 | | // flags, because we can't use those to distinguish |
1546 | | // <bdi dir="some-invalid-value"> and <bdi dir="auto">. |
1547 | | NodeHasValidDirAttribute, |
1548 | | // Set if the node has dir=auto and has a property pointing to the text |
1549 | | // node that determines its direction |
1550 | | NodeHasDirAutoSet, |
1551 | | // Set if the node is a text node descendant of a node with dir=auto |
1552 | | // and has a TextNodeDirectionalityMap property listing the elements whose |
1553 | | // direction it determines. |
1554 | | NodeHasTextNodeDirectionalityMap, |
1555 | | // Set if a node in the node's parent chain has dir=auto. |
1556 | | NodeAncestorHasDirAuto, |
1557 | | // Set if the node is handling a click. |
1558 | | NodeHandlingClick, |
1559 | | // Set if the element has a parser insertion mode other than "in body", |
1560 | | // per the HTML5 "Parse state" section. |
1561 | | ElementHasWeirdParserInsertionMode, |
1562 | | // Parser sets this flag if it has notified about the node. |
1563 | | ParserHasNotified, |
1564 | | // Sets if the node is apz aware or we have apz aware listeners. |
1565 | | MayBeApzAware, |
1566 | | // Set if the element might have any kind of anonymous content children, |
1567 | | // which would not be found through the element's children list. |
1568 | | ElementMayHaveAnonymousChildren, |
1569 | | // Set if element has CustomElementData. |
1570 | | ElementHasCustomElementData, |
1571 | | // Guard value |
1572 | | BooleanFlagCount |
1573 | | }; |
1574 | | |
1575 | | void SetBoolFlag(BooleanFlag name, bool value) { |
1576 | | static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags), |
1577 | | "Too many boolean flags"); |
1578 | | mBoolFlags = (mBoolFlags & ~(1 << name)) | (value << name); |
1579 | | } |
1580 | | |
1581 | | void SetBoolFlag(BooleanFlag name) { |
1582 | | static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags), |
1583 | | "Too many boolean flags"); |
1584 | | mBoolFlags |= (1 << name); |
1585 | | } |
1586 | | |
1587 | | void ClearBoolFlag(BooleanFlag name) { |
1588 | | static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags), |
1589 | | "Too many boolean flags"); |
1590 | | mBoolFlags &= ~(1 << name); |
1591 | | } |
1592 | | |
1593 | | bool GetBoolFlag(BooleanFlag name) const { |
1594 | | static_assert(BooleanFlagCount <= 8*sizeof(mBoolFlags), |
1595 | | "Too many boolean flags"); |
1596 | | return mBoolFlags & (1 << name); |
1597 | | } |
1598 | | |
1599 | | public: |
1600 | | bool HasRenderingObservers() const |
1601 | | { return GetBoolFlag(NodeHasRenderingObservers); } |
1602 | | void SetHasRenderingObservers(bool aValue) |
1603 | | { SetBoolFlag(NodeHasRenderingObservers, aValue); } |
1604 | | bool IsContent() const { return GetBoolFlag(NodeIsContent); } |
1605 | | bool HasID() const { return GetBoolFlag(ElementHasID); } |
1606 | | bool MayHaveClass() const { return GetBoolFlag(ElementMayHaveClass); } |
1607 | | void SetMayHaveClass() { SetBoolFlag(ElementMayHaveClass); } |
1608 | | bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); } |
1609 | | bool HasName() const { return GetBoolFlag(ElementHasName); } |
1610 | | bool MayHaveContentEditableAttr() const |
1611 | 0 | { return GetBoolFlag(ElementMayHaveContentEditableAttr); } |
1612 | | bool IsCommonAncestorForRangeInSelection() const |
1613 | | { return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); } |
1614 | | void SetCommonAncestorForRangeInSelection() |
1615 | | { SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); } |
1616 | | void ClearCommonAncestorForRangeInSelection() |
1617 | | { ClearBoolFlag(NodeIsCommonAncestorForRangeInSelection); } |
1618 | | bool IsDescendantOfCommonAncestorForRangeInSelection() const |
1619 | | { return GetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); } |
1620 | | void SetDescendantOfCommonAncestorForRangeInSelection() |
1621 | | { SetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); } |
1622 | | void ClearDescendantOfCommonAncestorForRangeInSelection() |
1623 | | { ClearBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); } |
1624 | | |
1625 | | void SetCCMarkedRoot(bool aValue) |
1626 | | { SetBoolFlag(NodeIsCCMarkedRoot, aValue); } |
1627 | | bool CCMarkedRoot() const { return GetBoolFlag(NodeIsCCMarkedRoot); } |
1628 | | void SetInCCBlackTree(bool aValue) |
1629 | | { SetBoolFlag(NodeIsCCBlackTree, aValue); } |
1630 | | bool InCCBlackTree() const { return GetBoolFlag(NodeIsCCBlackTree); } |
1631 | | void SetIsPurpleRoot(bool aValue) |
1632 | | { SetBoolFlag(NodeIsPurpleRoot, aValue); } |
1633 | | bool IsPurpleRoot() const { return GetBoolFlag(NodeIsPurpleRoot); } |
1634 | | bool MayHaveDOMMutationObserver() |
1635 | | { return GetBoolFlag(NodeMayHaveDOMMutationObserver); } |
1636 | | void SetMayHaveDOMMutationObserver() |
1637 | | { SetBoolFlag(NodeMayHaveDOMMutationObserver, true); } |
1638 | | bool HasListenerManager() { return HasFlag(NODE_HAS_LISTENERMANAGER); } |
1639 | | bool HasPointerLock() const { return GetBoolFlag(ElementHasPointerLock); } |
1640 | | void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); } |
1641 | | void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); } |
1642 | | bool MayHaveAnimations() const { return GetBoolFlag(ElementHasAnimations); } |
1643 | | void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); } |
1644 | | void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); } |
1645 | | void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); } |
1646 | | bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); } |
1647 | | void SetHasDirAutoSet() { |
1648 | | MOZ_ASSERT(NodeType() != TEXT_NODE, |
1649 | | "SetHasDirAutoSet on text node"); |
1650 | | SetBoolFlag(NodeHasDirAutoSet); |
1651 | | } |
1652 | | void ClearHasDirAutoSet() { |
1653 | | MOZ_ASSERT(NodeType() != TEXT_NODE, |
1654 | | "ClearHasDirAutoSet on text node"); |
1655 | | ClearBoolFlag(NodeHasDirAutoSet); |
1656 | | } |
1657 | | bool HasDirAutoSet() const |
1658 | | { return GetBoolFlag(NodeHasDirAutoSet); } |
1659 | | void SetHasTextNodeDirectionalityMap() { |
1660 | | MOZ_ASSERT(NodeType() == TEXT_NODE, |
1661 | | "SetHasTextNodeDirectionalityMap on non-text node"); |
1662 | | SetBoolFlag(NodeHasTextNodeDirectionalityMap); |
1663 | | } |
1664 | | void ClearHasTextNodeDirectionalityMap() { |
1665 | | MOZ_ASSERT(NodeType() == TEXT_NODE, |
1666 | | "ClearHasTextNodeDirectionalityMap on non-text node"); |
1667 | | ClearBoolFlag(NodeHasTextNodeDirectionalityMap); |
1668 | | } |
1669 | | bool HasTextNodeDirectionalityMap() const { |
1670 | | MOZ_ASSERT(NodeType() == TEXT_NODE, |
1671 | | "HasTextNodeDirectionalityMap on non-text node"); |
1672 | | return GetBoolFlag(NodeHasTextNodeDirectionalityMap); |
1673 | | } |
1674 | | |
1675 | | void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); } |
1676 | | void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); } |
1677 | | bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); } |
1678 | | |
1679 | | // Implemented in nsIContentInlines.h. |
1680 | | inline bool NodeOrAncestorHasDirAuto() const; |
1681 | | |
1682 | | void SetParserHasNotified() { SetBoolFlag(ParserHasNotified); }; |
1683 | | bool HasParserNotified() { return GetBoolFlag(ParserHasNotified); } |
1684 | | |
1685 | | void SetMayBeApzAware() { SetBoolFlag(MayBeApzAware); } |
1686 | | bool NodeMayBeApzAware() const |
1687 | | { |
1688 | | return GetBoolFlag(MayBeApzAware); |
1689 | | } |
1690 | | |
1691 | | void SetMayHaveAnonymousChildren() { SetBoolFlag(ElementMayHaveAnonymousChildren); } |
1692 | | bool MayHaveAnonymousChildren() const { return GetBoolFlag(ElementMayHaveAnonymousChildren); } |
1693 | | |
1694 | | void SetHasCustomElementData() { SetBoolFlag(ElementHasCustomElementData); } |
1695 | | bool HasCustomElementData() const { return GetBoolFlag(ElementHasCustomElementData); } |
1696 | | |
1697 | | protected: |
1698 | | void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); } |
1699 | | void SetIsInDocument() { SetBoolFlag(IsInDocument); } |
1700 | | void ClearInDocument() { ClearBoolFlag(IsInDocument); } |
1701 | | void SetIsConnected(bool aConnected) { SetBoolFlag(IsConnected, aConnected); } |
1702 | | void SetNodeIsContent() { SetBoolFlag(NodeIsContent); } |
1703 | | void SetIsElement() { SetBoolFlag(NodeIsElement); } |
1704 | | void SetHasID() { SetBoolFlag(ElementHasID); } |
1705 | | void ClearHasID() { ClearBoolFlag(ElementHasID); } |
1706 | | void SetMayHaveStyle() { SetBoolFlag(ElementMayHaveStyle); } |
1707 | | void SetHasName() { SetBoolFlag(ElementHasName); } |
1708 | | void ClearHasName() { ClearBoolFlag(ElementHasName); } |
1709 | | void SetMayHaveContentEditableAttr() |
1710 | | { SetBoolFlag(ElementMayHaveContentEditableAttr); } |
1711 | | void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); } |
1712 | | void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); } |
1713 | | bool HasLockedStyleStates() const |
1714 | | { return GetBoolFlag(ElementHasLockedStyleStates); } |
1715 | | void SetHasWeirdParserInsertionMode() { SetBoolFlag(ElementHasWeirdParserInsertionMode); } |
1716 | | bool HasWeirdParserInsertionMode() const |
1717 | | { return GetBoolFlag(ElementHasWeirdParserInsertionMode); } |
1718 | | bool HandlingClick() const { return GetBoolFlag(NodeHandlingClick); } |
1719 | | void SetHandlingClick() { SetBoolFlag(NodeHandlingClick); } |
1720 | | void ClearHandlingClick() { ClearBoolFlag(NodeHandlingClick); } |
1721 | | |
1722 | | void SetSubtreeRootPointer(nsINode* aSubtreeRoot) |
1723 | | { |
1724 | | NS_ASSERTION(aSubtreeRoot, "aSubtreeRoot can never be null!"); |
1725 | | NS_ASSERTION(!(IsContent() && IsInUncomposedDoc()) && |
1726 | | !IsInShadowTree(), "Shouldn't be here!"); |
1727 | | mSubtreeRoot = aSubtreeRoot; |
1728 | | } |
1729 | | |
1730 | | void ClearSubtreeRootPointer() |
1731 | | { |
1732 | | mSubtreeRoot = nullptr; |
1733 | | } |
1734 | | |
1735 | | public: |
1736 | | // Makes nsINode object to keep aObject alive. |
1737 | | void BindObject(nsISupports* aObject); |
1738 | | // After calling UnbindObject nsINode object doesn't keep |
1739 | | // aObject alive anymore. |
1740 | | void UnbindObject(nsISupports* aObject); |
1741 | | |
1742 | | void GenerateXPath(nsAString& aResult); |
1743 | | |
1744 | | already_AddRefed<mozilla::dom::Promise> |
1745 | | Localize(JSContext* aCx, mozilla::dom::L10nCallback& aCallback, mozilla::ErrorResult& aRv); |
1746 | | |
1747 | | already_AddRefed<mozilla::dom::AccessibleNode> GetAccessibleNode(); |
1748 | | |
1749 | | /** |
1750 | | * Returns the length of this node, as specified at |
1751 | | * <http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-node-length> |
1752 | | */ |
1753 | | uint32_t Length() const; |
1754 | | |
1755 | | void GetNodeName(mozilla::dom::DOMString& aNodeName) |
1756 | 0 | { |
1757 | 0 | const nsString& nodeName = NodeName(); |
1758 | 0 | aNodeName.SetKnownLiveString(nodeName); |
1759 | 0 | } |
1760 | | MOZ_MUST_USE nsresult GetBaseURI(nsAString& aBaseURI) const; |
1761 | | // Return the base URI for the document. |
1762 | | // The returned value may differ if the document is loaded via XHR, and |
1763 | | // when accessed from chrome privileged script and |
1764 | | // from content privileged script for compatibility. |
1765 | | void GetBaseURIFromJS(nsAString& aBaseURI, |
1766 | | CallerType aCallerType, |
1767 | | ErrorResult& aRv) const; |
1768 | | bool HasChildNodes() const |
1769 | | { |
1770 | | return HasChildren(); |
1771 | | } |
1772 | | |
1773 | | // See nsContentUtils::PositionIsBefore for aThisIndex and aOtherIndex usage. |
1774 | | uint16_t CompareDocumentPosition(nsINode& aOther, |
1775 | | int32_t* aThisIndex = nullptr, |
1776 | | int32_t* aOtherIndex = nullptr) const; |
1777 | | void GetNodeValue(nsAString& aNodeValue) |
1778 | | { |
1779 | | GetNodeValueInternal(aNodeValue); |
1780 | | } |
1781 | | void SetNodeValue(const nsAString& aNodeValue, |
1782 | | mozilla::ErrorResult& aError) |
1783 | | { |
1784 | | SetNodeValueInternal(aNodeValue, aError); |
1785 | | } |
1786 | | virtual void GetNodeValueInternal(nsAString& aNodeValue); |
1787 | | virtual void SetNodeValueInternal(const nsAString& aNodeValue, |
1788 | | mozilla::ErrorResult& aError) |
1789 | | { |
1790 | | // The DOM spec says that when nodeValue is defined to be null "setting it |
1791 | | // has no effect", so we don't throw an exception. |
1792 | | } |
1793 | | void EnsurePreInsertionValidity(nsINode& aNewChild, nsINode* aRefChild, |
1794 | | mozilla::ErrorResult& aError); |
1795 | | nsINode* InsertBefore(nsINode& aNode, nsINode* aChild, |
1796 | | mozilla::ErrorResult& aError) |
1797 | | { |
1798 | | return ReplaceOrInsertBefore(false, &aNode, aChild, aError); |
1799 | | } |
1800 | | nsINode* AppendChild(nsINode& aNode, mozilla::ErrorResult& aError) |
1801 | | { |
1802 | | return InsertBefore(aNode, nullptr, aError); |
1803 | | } |
1804 | | nsINode* ReplaceChild(nsINode& aNode, nsINode& aChild, |
1805 | | mozilla::ErrorResult& aError) |
1806 | | { |
1807 | | return ReplaceOrInsertBefore(true, &aNode, &aChild, aError); |
1808 | | } |
1809 | | nsINode* RemoveChild(nsINode& aChild, mozilla::ErrorResult& aError); |
1810 | | already_AddRefed<nsINode> CloneNode(bool aDeep, mozilla::ErrorResult& aError); |
1811 | | bool IsSameNode(nsINode* aNode); |
1812 | | bool IsEqualNode(nsINode* aNode); |
1813 | | void GetNamespaceURI(nsAString& aNamespaceURI) const |
1814 | | { |
1815 | | mNodeInfo->GetNamespaceURI(aNamespaceURI); |
1816 | | } |
1817 | | #ifdef MOZILLA_INTERNAL_API |
1818 | | void GetPrefix(nsAString& aPrefix) |
1819 | 0 | { |
1820 | 0 | mNodeInfo->GetPrefix(aPrefix); |
1821 | 0 | } |
1822 | | #endif |
1823 | | void GetLocalName(mozilla::dom::DOMString& aLocalName) const |
1824 | 0 | { |
1825 | 0 | const nsString& localName = LocalName(); |
1826 | 0 | aLocalName.SetKnownLiveString(localName); |
1827 | 0 | } |
1828 | | |
1829 | | nsDOMAttributeMap* GetAttributes(); |
1830 | | |
1831 | | // Helper method to remove this node from its parent. This is not exposed |
1832 | | // through WebIDL. |
1833 | | // Only call this if the node has a parent node. |
1834 | | nsresult RemoveFromParent() |
1835 | | { |
1836 | | nsINode* parent = GetParentNode(); |
1837 | | mozilla::ErrorResult rv; |
1838 | | parent->RemoveChild(*this, rv); |
1839 | | return rv.StealNSResult(); |
1840 | | } |
1841 | | |
1842 | | // ChildNode methods |
1843 | | inline mozilla::dom::Element* GetPreviousElementSibling() const; |
1844 | | inline mozilla::dom::Element* GetNextElementSibling() const; |
1845 | | |
1846 | | MOZ_CAN_RUN_SCRIPT void Before(const Sequence<OwningNodeOrString>& aNodes, |
1847 | | ErrorResult& aRv); |
1848 | | MOZ_CAN_RUN_SCRIPT void After(const Sequence<OwningNodeOrString>& aNodes, |
1849 | | ErrorResult& aRv); |
1850 | | MOZ_CAN_RUN_SCRIPT void ReplaceWith(const Sequence<OwningNodeOrString>& aNodes, |
1851 | | ErrorResult& aRv); |
1852 | | /** |
1853 | | * Remove this node from its parent, if any. |
1854 | | */ |
1855 | | void Remove(); |
1856 | | |
1857 | | // ParentNode methods |
1858 | | mozilla::dom::Element* GetFirstElementChild() const; |
1859 | | mozilla::dom::Element* GetLastElementChild() const; |
1860 | | |
1861 | | already_AddRefed<nsIHTMLCollection> |
1862 | | GetElementsByAttribute(const nsAString& aAttribute, |
1863 | | const nsAString& aValue); |
1864 | | already_AddRefed<nsIHTMLCollection> |
1865 | | GetElementsByAttributeNS(const nsAString& aNamespaceURI, |
1866 | | const nsAString& aAttribute, |
1867 | | const nsAString& aValue, |
1868 | | ErrorResult& aRv); |
1869 | | |
1870 | | |
1871 | | MOZ_CAN_RUN_SCRIPT void Prepend(const Sequence<OwningNodeOrString>& aNodes, |
1872 | | ErrorResult& aRv); |
1873 | | MOZ_CAN_RUN_SCRIPT void Append(const Sequence<OwningNodeOrString>& aNodes, |
1874 | | ErrorResult& aRv); |
1875 | | |
1876 | | void GetBoxQuads(const BoxQuadOptions& aOptions, |
1877 | | nsTArray<RefPtr<DOMQuad> >& aResult, |
1878 | | CallerType aCallerType, |
1879 | | ErrorResult& aRv); |
1880 | | |
1881 | | already_AddRefed<DOMQuad> ConvertQuadFromNode(DOMQuad& aQuad, |
1882 | | const TextOrElementOrDocument& aFrom, |
1883 | | const ConvertCoordinateOptions& aOptions, |
1884 | | CallerType aCallerType, |
1885 | | ErrorResult& aRv); |
1886 | | already_AddRefed<DOMQuad> ConvertRectFromNode(DOMRectReadOnly& aRect, |
1887 | | const TextOrElementOrDocument& aFrom, |
1888 | | const ConvertCoordinateOptions& aOptions, |
1889 | | CallerType aCallerType, |
1890 | | ErrorResult& aRv); |
1891 | | already_AddRefed<DOMPoint> ConvertPointFromNode(const DOMPointInit& aPoint, |
1892 | | const TextOrElementOrDocument& aFrom, |
1893 | | const ConvertCoordinateOptions& aOptions, |
1894 | | CallerType aCallerType, |
1895 | | ErrorResult& aRv); |
1896 | | |
1897 | | const mozilla::LinkedList<nsRange>* GetExistingCommonAncestorRanges() const |
1898 | 0 | { |
1899 | 0 | if (!HasSlots()) { |
1900 | 0 | return nullptr; |
1901 | 0 | } |
1902 | 0 | return GetExistingSlots()->mCommonAncestorRanges.get(); |
1903 | 0 | } |
1904 | | |
1905 | | mozilla::LinkedList<nsRange>* GetExistingCommonAncestorRanges() |
1906 | | { |
1907 | | if (!HasSlots()) { |
1908 | | return nullptr; |
1909 | | } |
1910 | | return GetExistingSlots()->mCommonAncestorRanges.get(); |
1911 | | } |
1912 | | |
1913 | | mozilla::UniquePtr<mozilla::LinkedList<nsRange>>& GetCommonAncestorRangesPtr() |
1914 | | { |
1915 | | return Slots()->mCommonAncestorRanges; |
1916 | | } |
1917 | | |
1918 | | nsIWeakReference* GetExistingWeakReference() |
1919 | | { |
1920 | | return HasSlots() ? GetExistingSlots()->mWeakReference : nullptr; |
1921 | | } |
1922 | | |
1923 | | protected: |
1924 | | |
1925 | | // Override this function to create a custom slots class. |
1926 | | // Must not return null. |
1927 | | virtual nsINode::nsSlots* CreateSlots(); |
1928 | | |
1929 | | bool HasSlots() const |
1930 | | { |
1931 | | return mSlots != nullptr; |
1932 | | } |
1933 | | |
1934 | | nsSlots* GetExistingSlots() const |
1935 | | { |
1936 | | return mSlots; |
1937 | | } |
1938 | | |
1939 | | nsSlots* Slots() |
1940 | | { |
1941 | | if (!HasSlots()) { |
1942 | | mSlots = CreateSlots(); |
1943 | | MOZ_ASSERT(mSlots); |
1944 | | } |
1945 | | return GetExistingSlots(); |
1946 | | } |
1947 | | |
1948 | | nsAutoTObserverArray<nsIMutationObserver*, 1> *GetMutationObservers() |
1949 | | { |
1950 | | return HasSlots() ? &GetExistingSlots()->mMutationObservers : nullptr; |
1951 | | } |
1952 | | |
1953 | | /** |
1954 | | * Invalidate cached child array inside mChildNodes |
1955 | | * of type nsParentNodeChildContentList. |
1956 | | */ |
1957 | | void InvalidateChildNodes(); |
1958 | | |
1959 | | virtual void GetTextContentInternal(nsAString& aTextContent, |
1960 | | mozilla::OOMReporter& aError); |
1961 | | virtual void SetTextContentInternal(const nsAString& aTextContent, |
1962 | | nsIPrincipal* aSubjectPrincipal, |
1963 | | mozilla::ErrorResult& aError) |
1964 | | { |
1965 | | } |
1966 | | |
1967 | | #ifdef DEBUG |
1968 | | // Note: virtual so that IsInNativeAnonymousSubtree can be called accross |
1969 | | // module boundaries. |
1970 | | virtual void CheckNotNativeAnonymous() const; |
1971 | | #endif |
1972 | | |
1973 | | void EnsurePreInsertionValidity1(nsINode& aNewChild, nsINode* aRefChild, |
1974 | | mozilla::ErrorResult& aError); |
1975 | | void EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild, |
1976 | | nsINode* aRefChild, |
1977 | | mozilla::ErrorResult& aError); |
1978 | | nsINode* ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild, |
1979 | | nsINode* aRefChild, |
1980 | | mozilla::ErrorResult& aError); |
1981 | | |
1982 | | /** |
1983 | | * Returns the Element that should be used for resolving namespaces |
1984 | | * on this node (ie the ownerElement for attributes, the documentElement for |
1985 | | * documents, the node itself for elements and for other nodes the parentNode |
1986 | | * if it is an element). |
1987 | | */ |
1988 | | virtual mozilla::dom::Element* GetNameSpaceElement() = 0; |
1989 | | |
1990 | | /** |
1991 | | * Parse the given selector string into a servo SelectorList. |
1992 | | * |
1993 | | * Never returns null if aRv is not failing. |
1994 | | * |
1995 | | * Note that the selector list returned here is owned by the owner doc's |
1996 | | * selector cache. |
1997 | | */ |
1998 | | const RawServoSelectorList* ParseSelectorList(const nsAString& aSelectorString, |
1999 | | mozilla::ErrorResult&); |
2000 | | |
2001 | | public: |
2002 | | /* Event stuff that documents and elements share. This needs to be |
2003 | | NS_IMETHOD because some subclasses implement DOM methods with |
2004 | | this exact name and signature and then the calling convention |
2005 | | needs to match. |
2006 | | |
2007 | | Note that we include DOCUMENT_ONLY_EVENT events here so that we |
2008 | | can forward all the document stuff to this implementation. |
2009 | | */ |
2010 | | #define EVENT(name_, id_, type_, struct_) \ |
2011 | | mozilla::dom::EventHandlerNonNull* GetOn##name_(); \ |
2012 | | void SetOn##name_(mozilla::dom::EventHandlerNonNull* listener); |
2013 | | #define TOUCH_EVENT EVENT |
2014 | | #define DOCUMENT_ONLY_EVENT EVENT |
2015 | | #include "mozilla/EventNameList.h" |
2016 | | #undef DOCUMENT_ONLY_EVENT |
2017 | | #undef TOUCH_EVENT |
2018 | | #undef EVENT |
2019 | | |
2020 | | protected: |
2021 | | static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb); |
2022 | | static void Unlink(nsINode *tmp); |
2023 | | |
2024 | | RefPtr<mozilla::dom::NodeInfo> mNodeInfo; |
2025 | | |
2026 | | // mParent is an owning ref most of the time, except for the case of document |
2027 | | // nodes, so it cannot be represented by nsCOMPtr, so mark is as |
2028 | | // MOZ_OWNING_REF. |
2029 | | nsINode* MOZ_OWNING_REF mParent; |
2030 | | |
2031 | | private: |
2032 | | #ifndef BOOL_FLAGS_ON_WRAPPER_CACHE |
2033 | | // Boolean flags. |
2034 | | uint32_t mBoolFlags; |
2035 | | #endif |
2036 | | |
2037 | | //NOTE, there are 32 bits left here, at least in 64 bit builds. |
2038 | | |
2039 | | uint32_t mChildCount; |
2040 | | |
2041 | | protected: |
2042 | | // mNextSibling and mFirstChild are strong references while |
2043 | | // mPreviousOrLastSibling is a weak ref. |mFirstChild->mPreviousOrLastSibling| |
2044 | | // points to the last child node. |
2045 | | nsCOMPtr<nsIContent> mFirstChild; |
2046 | | nsCOMPtr<nsIContent> mNextSibling; |
2047 | | nsIContent* MOZ_NON_OWNING_REF mPreviousOrLastSibling; |
2048 | | |
2049 | | union { |
2050 | | // Pointer to our primary frame. Might be null. |
2051 | | nsIFrame* mPrimaryFrame; |
2052 | | |
2053 | | // Pointer to the root of our subtree. Might be null. |
2054 | | // This reference is non-owning and safe, since it either points to the |
2055 | | // object itself, or is reset by ClearSubtreeRootPointer. |
2056 | | nsINode* MOZ_NON_OWNING_REF mSubtreeRoot; |
2057 | | }; |
2058 | | |
2059 | | // Storage for more members that are usually not needed; allocated lazily. |
2060 | | nsSlots* mSlots; |
2061 | | }; |
2062 | | |
2063 | | // Useful inline function for getting a node given an nsIContent and an |
2064 | | // nsIDocument. Returns the first argument cast to nsINode if it is non-null, |
2065 | | // otherwise returns the second (which may be null). We use type variables |
2066 | | // instead of nsIContent* and nsIDocument* because the actual types must be |
2067 | | // known for the cast to work. |
2068 | | template<class C, class D> |
2069 | | inline nsINode* NODE_FROM(C& aContent, D& aDocument) |
2070 | | { |
2071 | | if (aContent) |
2072 | | return static_cast<nsINode*>(aContent); |
2073 | | return static_cast<nsINode*>(aDocument); |
2074 | | } |
2075 | | |
2076 | | NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID) |
2077 | | |
2078 | | inline nsISupports* |
2079 | | ToSupports(nsINode* aPointer) |
2080 | 0 | { |
2081 | 0 | return aPointer; |
2082 | 0 | } |
2083 | | |
2084 | | // Some checks are faster to do on nsIContent or Element than on |
2085 | | // nsINode, so spit out FromNode versions taking those types too. |
2086 | | #define NS_IMPL_FROMNODE_GENERIC(_class, _check, _const) \ |
2087 | | template<typename T> \ |
2088 | | static auto FromNode(_const T& aNode) \ |
2089 | | -> decltype(static_cast<_const _class*>(&aNode)) \ |
2090 | | { \ |
2091 | | return aNode._check ? static_cast<_const _class*>(&aNode) : nullptr; \ |
2092 | | } \ |
2093 | | template<typename T> \ |
2094 | | static _const _class* FromNode(_const T* aNode) \ |
2095 | | { \ |
2096 | | return FromNode(*aNode); \ |
2097 | | } \ |
2098 | | template<typename T> \ |
2099 | | static _const _class* FromNodeOrNull(_const T* aNode) \ |
2100 | | { \ |
2101 | | return aNode ? FromNode(*aNode) : nullptr; \ |
2102 | | } |
2103 | | |
2104 | | #define NS_IMPL_FROMNODE_HELPER(_class, _check) \ |
2105 | | NS_IMPL_FROMNODE_GENERIC(_class, _check, ) \ |
2106 | | NS_IMPL_FROMNODE_GENERIC(_class, _check, const) \ |
2107 | | \ |
2108 | | template<typename T> \ |
2109 | | static _class* FromNode(T&& aNode) \ |
2110 | 0 | { \ |
2111 | 0 | /* We need the double-cast in case aNode is a smartptr. Those */ \ |
2112 | 0 | /* can cast to superclasses of the type they're templated on, */ \ |
2113 | 0 | /* but not directly to subclasses. */ \ |
2114 | 0 | return aNode->_check \ |
2115 | 0 | ? static_cast<_class*>(static_cast<nsINode*>(aNode)) \ |
2116 | 0 | : nullptr; \ |
2117 | 0 | } \ Unexecuted instantiation: mozilla::dom::HTMLLinkElement* mozilla::dom::HTMLLinkElement::FromNode<nsCOMPtr<nsINode>&>(nsCOMPtr<nsINode>&) Unexecuted instantiation: mozilla::dom::Attr* mozilla::dom::Attr::FromNode<nsCOMPtr<nsINode>&>(nsCOMPtr<nsINode>&) Unexecuted instantiation: mozilla::dom::HTMLLabelElement* mozilla::dom::HTMLLabelElement::FromNode<nsCOMPtr<nsIContent> const&>(nsCOMPtr<nsIContent> const&) Unexecuted instantiation: mozilla::dom::HTMLSummaryElement* mozilla::dom::HTMLSummaryElement::FromNode<nsCOMPtr<nsIContent>&>(nsCOMPtr<nsIContent>&) Unexecuted instantiation: mozilla::dom::HTMLSummaryElement* mozilla::dom::HTMLSummaryElement::FromNode<nsCOMPtr<nsIContent> const&>(nsCOMPtr<nsIContent> const&) Unexecuted instantiation: mozilla::dom::HTMLTextAreaElement* mozilla::dom::HTMLTextAreaElement::FromNode<nsCOMPtr<nsIContent> const&>(nsCOMPtr<nsIContent> const&) Unexecuted instantiation: mozilla::dom::HTMLOptionElement* mozilla::dom::HTMLOptionElement::FromNode<nsCOMPtr<nsIContent> const&>(nsCOMPtr<nsIContent> const&) Unexecuted instantiation: mozilla::dom::HTMLTableElement* mozilla::dom::HTMLTableElement::FromNode<nsCOMPtr<nsIContent>&>(nsCOMPtr<nsIContent>&) Unexecuted instantiation: mozilla::dom::HTMLInputElement* mozilla::dom::HTMLInputElement::FromNode<nsCOMPtr<nsINode>&>(nsCOMPtr<nsINode>&) Unexecuted instantiation: mozilla::dom::HTMLTextAreaElement* mozilla::dom::HTMLTextAreaElement::FromNode<nsCOMPtr<nsINode>&>(nsCOMPtr<nsINode>&) |
2118 | | template<typename T> \ |
2119 | | static _class* FromNodeOrNull(T&& aNode) \ |
2120 | 0 | { \ |
2121 | 0 | return aNode ? FromNode(aNode) : nullptr; \ |
2122 | 0 | } |
2123 | | |
2124 | | #define NS_IMPL_FROMNODE(_class, _nsid) \ |
2125 | | NS_IMPL_FROMNODE_HELPER(_class, IsInNamespace(_nsid)) |
2126 | | |
2127 | | #define NS_IMPL_FROMNODE_WITH_TAG(_class, _nsid, _tag) \ |
2128 | | NS_IMPL_FROMNODE_HELPER(_class, NodeInfo()->Equals(nsGkAtoms::_tag, _nsid)) |
2129 | | |
2130 | | #define NS_IMPL_FROMNODE_HTML_WITH_TAG(_class, _tag) \ |
2131 | | NS_IMPL_FROMNODE_WITH_TAG(_class, kNameSpaceID_XHTML, _tag) |
2132 | | |
2133 | | #endif /* nsINode_h___ */ |