Line data Source code
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 : /*
8 : * Base class for all element classes; this provides an implementation
9 : * of DOM Core's nsIDOMElement, implements nsIContent, provides
10 : * utility methods for subclasses, and so forth.
11 : */
12 :
13 : #ifndef mozilla_dom_Element_h__
14 : #define mozilla_dom_Element_h__
15 :
16 : #include "mozilla/dom/FragmentOrElement.h" // for base class
17 : #include "nsChangeHint.h" // for enum
18 : #include "mozilla/EventStates.h" // for member
19 : #include "mozilla/ServoTypes.h"
20 : #include "mozilla/dom/DirectionalityUtils.h"
21 : #include "nsIDOMElement.h"
22 : #include "nsILinkHandler.h"
23 : #include "nsINodeList.h"
24 : #include "nsNodeUtils.h"
25 : #include "nsAttrAndChildArray.h"
26 : #include "mozilla/FlushType.h"
27 : #include "nsDOMAttributeMap.h"
28 : #include "nsPresContext.h"
29 : #include "mozilla/CORSMode.h"
30 : #include "mozilla/Attributes.h"
31 : #include "nsIScrollableFrame.h"
32 : #include "mozilla/dom/Attr.h"
33 : #include "nsISMILAttr.h"
34 : #include "mozilla/dom/DOMRect.h"
35 : #include "nsAttrValue.h"
36 : #include "mozilla/EventForwards.h"
37 : #include "mozilla/dom/BindingDeclarations.h"
38 : #include "mozilla/dom/DOMTokenListSupportedTokens.h"
39 : #include "mozilla/dom/WindowBinding.h"
40 : #include "mozilla/dom/ElementBinding.h"
41 : #include "mozilla/dom/Nullable.h"
42 : #include "mozilla/UniquePtr.h"
43 : #include "Units.h"
44 : #include "DOMIntersectionObserver.h"
45 :
46 : class mozAutoDocUpdate;
47 : class nsIFrame;
48 : class nsIDOMMozNamedAttrMap;
49 : class nsIMozBrowserFrame;
50 : class nsIURI;
51 : class nsIScrollableFrame;
52 : class nsAttrValueOrString;
53 : class nsContentList;
54 : class nsDOMTokenList;
55 : struct nsRect;
56 : class nsFocusManager;
57 : class nsGlobalWindow;
58 : class nsICSSDeclaration;
59 : class nsISMILAttr;
60 : class nsDocument;
61 : class nsDOMStringMap;
62 :
63 : namespace mozilla {
64 : class DeclarationBlock;
65 : class TextEditor;
66 : namespace dom {
67 : struct AnimationFilter;
68 : struct ScrollIntoViewOptions;
69 : struct ScrollToOptions;
70 : class DOMIntersectionObserver;
71 : class DOMMatrixReadOnly;
72 : class ElementOrCSSPseudoElement;
73 : class UnrestrictedDoubleOrKeyframeAnimationOptions;
74 : enum class CallerType : uint32_t;
75 : } // namespace dom
76 : } // namespace mozilla
77 :
78 :
79 : already_AddRefed<nsContentList>
80 : NS_GetContentList(nsINode* aRootNode,
81 : int32_t aMatchNameSpaceId,
82 : const nsAString& aTagname);
83 :
84 : #define ELEMENT_FLAG_BIT(n_) NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
85 :
86 : // Element-specific flags
87 : enum {
88 : // These two bits are shared by Gecko's and Servo's restyle systems for
89 : // different purposes. They should not be accessed directly, and access to
90 : // them should be properly guarded by asserts.
91 : ELEMENT_SHARED_RESTYLE_BIT_1 = ELEMENT_FLAG_BIT(0),
92 : ELEMENT_SHARED_RESTYLE_BIT_2 = ELEMENT_FLAG_BIT(1),
93 : ELEMENT_SHARED_RESTYLE_BIT_3 = ELEMENT_FLAG_BIT(2),
94 : ELEMENT_SHARED_RESTYLE_BIT_4 = ELEMENT_FLAG_BIT(3),
95 :
96 : // Whether this node has dirty descendants for Servo's style system.
97 : ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO = ELEMENT_SHARED_RESTYLE_BIT_1,
98 :
99 : // Whether this node has dirty descendants for animation-only restyle for
100 : // Servo's style system.
101 : ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO =
102 : ELEMENT_SHARED_RESTYLE_BIT_2,
103 :
104 : // Whether the element has been snapshotted due to attribute or state changes
105 : // by the Servo restyle manager.
106 : ELEMENT_HAS_SNAPSHOT = ELEMENT_SHARED_RESTYLE_BIT_3,
107 :
108 : // Whether the element has already handled its relevant snapshot.
109 : //
110 : // Used by the servo restyle process in order to accurately track whether the
111 : // style of an element is up-to-date, even during the same restyle process.
112 : ELEMENT_HANDLED_SNAPSHOT = ELEMENT_SHARED_RESTYLE_BIT_4,
113 :
114 : // Set if the element has a pending style change.
115 : ELEMENT_HAS_PENDING_RESTYLE = ELEMENT_SHARED_RESTYLE_BIT_1,
116 :
117 : // Set if the element is a potential restyle root (that is, has a style
118 : // change pending _and_ that style change will attempt to restyle
119 : // descendants).
120 : ELEMENT_IS_POTENTIAL_RESTYLE_ROOT = ELEMENT_SHARED_RESTYLE_BIT_2,
121 :
122 : // Set if the element has a pending animation-only style change as
123 : // part of an animation-only style update (where we update styles from
124 : // animation to the current refresh tick, but leave everything else as
125 : // it was).
126 : ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE = ELEMENT_SHARED_RESTYLE_BIT_3,
127 :
128 : // Set if the element is a potential animation-only restyle root (that
129 : // is, has an animation-only style change pending _and_ that style
130 : // change will attempt to restyle descendants).
131 : ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT = ELEMENT_SHARED_RESTYLE_BIT_4,
132 :
133 : // Set if this element has a pending restyle with an eRestyle_SomeDescendants
134 : // restyle hint.
135 : ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR = ELEMENT_FLAG_BIT(4),
136 :
137 : // Just the HAS_PENDING bits, for convenience
138 : ELEMENT_PENDING_RESTYLE_FLAGS =
139 : ELEMENT_HAS_PENDING_RESTYLE |
140 : ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE,
141 :
142 : // Just the IS_POTENTIAL bits, for convenience
143 : ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS =
144 : ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
145 : ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT,
146 :
147 : // All of the restyle bits together, for convenience.
148 : ELEMENT_ALL_RESTYLE_FLAGS = ELEMENT_PENDING_RESTYLE_FLAGS |
149 : ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS |
150 : ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR,
151 :
152 : // ELEMENT_FLAG_BIT(5) is currently unused
153 :
154 : // Remaining bits are for subclasses
155 : ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 6
156 : };
157 :
158 : #undef ELEMENT_FLAG_BIT
159 :
160 : // Make sure we have space for our bits
161 : ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
162 :
163 : namespace mozilla {
164 : enum class CSSPseudoElementType : uint8_t;
165 : class EventChainPostVisitor;
166 : class EventChainPreVisitor;
167 : class EventChainVisitor;
168 : class EventListenerManager;
169 : class EventStateManager;
170 :
171 : namespace dom {
172 :
173 : class Animation;
174 : class CustomElementRegistry;
175 : class Link;
176 : class DOMRect;
177 : class DOMRectList;
178 : class DestinationInsertionPointList;
179 : class Grid;
180 :
181 : // IID for the dom::Element interface
182 : #define NS_ELEMENT_IID \
183 : { 0xc67ed254, 0xfd3b, 0x4b10, \
184 : { 0x96, 0xa2, 0xc5, 0x8b, 0x7b, 0x64, 0x97, 0xd1 } }
185 :
186 : class Element : public FragmentOrElement
187 : {
188 : public:
189 : #ifdef MOZILLA_INTERNAL_API
190 3168 : explicit Element(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) :
191 : FragmentOrElement(aNodeInfo),
192 3168 : mState(NS_EVENT_STATE_MOZ_READONLY)
193 : {
194 3168 : MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
195 : "Bad NodeType in aNodeInfo");
196 3168 : SetIsElement();
197 3168 : }
198 :
199 32 : ~Element()
200 64 : {
201 32 : NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier");
202 32 : }
203 :
204 : #endif // MOZILLA_INTERNAL_API
205 :
206 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
207 :
208 : NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
209 :
210 : /**
211 : * Method to get the full state of this element. See mozilla/EventStates.h
212 : * for the possible bits that could be set here.
213 : */
214 488 : EventStates State() const
215 : {
216 : // mState is maintained by having whoever might have changed it
217 : // call UpdateState() or one of the other mState mutators.
218 488 : return mState;
219 : }
220 :
221 : /**
222 : * Ask this element to update its state. If aNotify is false, then
223 : * state change notifications will not be dispatched; in that
224 : * situation it is the caller's responsibility to dispatch them.
225 : *
226 : * In general, aNotify should only be false if we're guaranteed that
227 : * the element can't have a frame no matter what its style is
228 : * (e.g. if we're in the middle of adding it to the document or
229 : * removing it from the document).
230 : */
231 : void UpdateState(bool aNotify);
232 :
233 : /**
234 : * Method to update mState with link state information. This does not notify.
235 : */
236 : void UpdateLinkState(EventStates aState);
237 :
238 0 : virtual int32_t TabIndexDefault()
239 : {
240 0 : return -1;
241 : }
242 :
243 : /**
244 : * Get tabIndex of this element. If not found, return TabIndexDefault.
245 : */
246 : int32_t TabIndex();
247 :
248 : /**
249 : * Set tabIndex value to this element.
250 : */
251 : void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
252 :
253 : /**
254 : * Make focus on this element.
255 : */
256 : virtual void Focus(mozilla::ErrorResult& aError);
257 :
258 : /**
259 : * Show blur and clear focus.
260 : */
261 : virtual void Blur(mozilla::ErrorResult& aError);
262 :
263 : /**
264 : * The style state of this element. This is the real state of the element
265 : * with any style locks applied for pseudo-class inspecting.
266 : */
267 55360 : EventStates StyleState() const
268 : {
269 55360 : if (!HasLockedStyleStates()) {
270 55360 : return mState;
271 : }
272 0 : return StyleStateFromLocks();
273 : }
274 :
275 : /**
276 : * StyleStateLocks is used to specify which event states should be locked,
277 : * and whether they should be locked to on or off.
278 : */
279 0 : struct StyleStateLocks {
280 : // mLocks tracks which event states should be locked.
281 : EventStates mLocks;
282 : // mValues tracks if the locked state should be on or off.
283 : EventStates mValues;
284 : };
285 :
286 : /**
287 : * The style state locks applied to this element.
288 : */
289 : StyleStateLocks LockedStyleStates() const;
290 :
291 : /**
292 : * Add a style state lock on this element.
293 : * aEnabled is the value to lock the given state bits to.
294 : */
295 : void LockStyleStates(EventStates aStates, bool aEnabled);
296 :
297 : /**
298 : * Remove a style state lock on this element.
299 : */
300 : void UnlockStyleStates(EventStates aStates);
301 :
302 : /**
303 : * Clear all style state locks on this element.
304 : */
305 : void ClearStyleStateLocks();
306 :
307 : /**
308 : * Accessors for the state of our dir attribute.
309 : */
310 456 : bool HasDirAuto() const
311 : {
312 456 : return State().HasState(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO);
313 : }
314 :
315 : /**
316 : * Elements with dir="rtl" or dir="ltr".
317 : */
318 0 : bool HasFixedDir() const
319 : {
320 0 : return State().HasAtLeastOneOfStates(NS_EVENT_STATE_DIR_ATTR_LTR |
321 156453 : NS_EVENT_STATE_DIR_ATTR_RTL);
322 : }
323 :
324 : /**
325 : * Get the inline style declaration, if any, for this element.
326 : */
327 : DeclarationBlock* GetInlineStyleDeclaration() const;
328 :
329 : /**
330 : * Get the mapped attributes, if any, for this element.
331 : */
332 : const nsMappedAttributes* GetMappedAttributes() const;
333 :
334 0 : void ClearMappedServoStyle() {
335 0 : mAttrsAndChildren.ClearMappedServoStyle();
336 0 : }
337 :
338 : /**
339 : * Set the inline style declaration for this element. This will send
340 : * an appropriate AttributeChanged notification if aNotify is true.
341 : */
342 : virtual nsresult SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
343 : const nsAString* aSerialized,
344 : bool aNotify);
345 :
346 : /**
347 : * Get the SMIL override style declaration for this element. If the
348 : * rule hasn't been created, this method simply returns null.
349 : */
350 : DeclarationBlock* GetSMILOverrideStyleDeclaration();
351 :
352 : /**
353 : * Set the SMIL override style declaration for this element. If
354 : * aNotify is true, this method will notify the document's pres
355 : * context, so that the style changes will be noticed.
356 : */
357 : nsresult SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
358 : bool aNotify);
359 :
360 : /**
361 : * Returns a new nsISMILAttr that allows the caller to animate the given
362 : * attribute on this element.
363 : */
364 0 : virtual UniquePtr<nsISMILAttr> GetAnimatedAttr(int32_t aNamespaceID,
365 : nsIAtom* aName)
366 : {
367 0 : return nullptr;
368 : }
369 :
370 : /**
371 : * Get the SMIL override style for this element. This is a style declaration
372 : * that is applied *after* the inline style, and it can be used e.g. to store
373 : * animated style values.
374 : *
375 : * Note: This method is analogous to the 'GetStyle' method in
376 : * nsGenericHTMLElement and nsStyledElement.
377 : */
378 : nsICSSDeclaration* GetSMILOverrideStyle();
379 :
380 : /**
381 : * Returns if the element is labelable as per HTML specification.
382 : */
383 : virtual bool IsLabelable() const;
384 :
385 : /**
386 : * Returns if the element is interactive content as per HTML specification.
387 : */
388 : virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const;
389 :
390 : /**
391 : * Returns |this| as an nsIMozBrowserFrame* if the element is a frame or
392 : * iframe element.
393 : *
394 : * We have this method, rather than using QI, so that we can use it during
395 : * the servo traversal, where we can't QI DOM nodes because of non-thread-safe
396 : * refcounts.
397 : */
398 0 : virtual nsIMozBrowserFrame* GetAsMozBrowserFrame() { return nullptr; }
399 :
400 : /**
401 : * Is the attribute named stored in the mapped attributes?
402 : *
403 : * // XXXbz we use this method in HasAttributeDependentStyle, so svg
404 : * returns true here even though it stores nothing in the mapped
405 : * attributes.
406 : */
407 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
408 :
409 : /**
410 : * Get a hint that tells the style system what to do when
411 : * an attribute on this node changes, if something needs to happen
412 : * in response to the change *other* than the result of what is
413 : * mapped into style data via any type of style rule.
414 : */
415 : virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
416 : int32_t aModType) const;
417 :
418 502 : inline Directionality GetDirectionality() const {
419 502 : if (HasFlag(NODE_HAS_DIRECTION_RTL)) {
420 0 : return eDir_RTL;
421 : }
422 :
423 502 : if (HasFlag(NODE_HAS_DIRECTION_LTR)) {
424 416 : return eDir_LTR;
425 : }
426 :
427 86 : return eDir_NotSet;
428 : }
429 :
430 140 : inline void SetDirectionality(Directionality aDir, bool aNotify) {
431 140 : UnsetFlags(NODE_ALL_DIRECTION_FLAGS);
432 140 : if (!aNotify) {
433 140 : RemoveStatesSilently(DIRECTION_STATES);
434 : }
435 :
436 140 : switch (aDir) {
437 : case (eDir_RTL):
438 0 : SetFlags(NODE_HAS_DIRECTION_RTL);
439 0 : if (!aNotify) {
440 0 : AddStatesSilently(NS_EVENT_STATE_RTL);
441 : }
442 0 : break;
443 :
444 : case(eDir_LTR):
445 140 : SetFlags(NODE_HAS_DIRECTION_LTR);
446 140 : if (!aNotify) {
447 140 : AddStatesSilently(NS_EVENT_STATE_LTR);
448 : }
449 140 : break;
450 :
451 : default:
452 0 : break;
453 : }
454 :
455 : /*
456 : * Only call UpdateState if we need to notify, because we call
457 : * SetDirectionality for every element, and UpdateState is very very slow
458 : * for some elements.
459 : */
460 140 : if (aNotify) {
461 0 : UpdateState(true);
462 : }
463 140 : }
464 :
465 : bool GetBindingURL(nsIDocument* aDocument, css::URLValue **aResult);
466 :
467 : Directionality GetComputedDirectionality() const;
468 :
469 : inline Element* GetFlattenedTreeParentElement() const;
470 : inline Element* GetFlattenedTreeParentElementForStyle() const;
471 :
472 0 : bool HasDirtyDescendantsForServo() const
473 : {
474 0 : MOZ_ASSERT(IsStyledByServo());
475 0 : return HasFlag(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
476 : }
477 :
478 0 : void SetHasDirtyDescendantsForServo() {
479 0 : MOZ_ASSERT(IsStyledByServo());
480 0 : SetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
481 0 : }
482 :
483 0 : void UnsetHasDirtyDescendantsForServo() {
484 0 : MOZ_ASSERT(IsStyledByServo());
485 0 : UnsetFlags(ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
486 0 : }
487 :
488 : inline void NoteDirtyDescendantsForServo();
489 :
490 0 : bool HasAnimationOnlyDirtyDescendantsForServo() const {
491 0 : MOZ_ASSERT(IsStyledByServo());
492 0 : return HasFlag(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
493 : }
494 :
495 0 : void UnsetHasAnimationOnlyDirtyDescendantsForServo() {
496 0 : MOZ_ASSERT(IsStyledByServo());
497 0 : UnsetFlags(ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO);
498 0 : }
499 :
500 : #ifdef DEBUG
501 : inline bool DirtyDescendantsBitIsPropagatedForServo();
502 : #endif
503 :
504 956 : bool HasServoData() const {
505 956 : return !!mServoData.Get();
506 : }
507 :
508 : void ClearServoData();
509 :
510 : /**
511 : * Gets the custom element data used by web components custom element.
512 : * Custom element data is created at the first attempt to enqueue a callback.
513 : *
514 : * @return The custom element data or null if none.
515 : */
516 5551 : inline CustomElementData* GetCustomElementData() const
517 : {
518 5551 : nsDOMSlots *slots = GetExistingDOMSlots();
519 5551 : if (slots) {
520 1038 : return slots->mCustomElementData;
521 : }
522 4513 : return nullptr;
523 : }
524 :
525 : /**
526 : * Sets the custom element data, ownership of the
527 : * callback data is taken by this element.
528 : *
529 : * @param aData The custom element data.
530 : */
531 : void SetCustomElementData(CustomElementData* aData);
532 :
533 : protected:
534 : /**
535 : * Method to get the _intrinsic_ content state of this element. This is the
536 : * state that is independent of the element's presentation. To get the full
537 : * content state, use State(). See mozilla/EventStates.h for
538 : * the possible bits that could be set here.
539 : */
540 : virtual EventStates IntrinsicState() const;
541 :
542 : /**
543 : * Method to add state bits. This should be called from subclass
544 : * constructors to set up our event state correctly at construction
545 : * time and other places where we don't want to notify a state
546 : * change.
547 : */
548 1348 : void AddStatesSilently(EventStates aStates)
549 : {
550 1348 : mState |= aStates;
551 1348 : }
552 :
553 : /**
554 : * Method to remove state bits. This should be called from subclass
555 : * constructors to set up our event state correctly at construction
556 : * time and other places where we don't want to notify a state
557 : * change.
558 : */
559 1225 : void RemoveStatesSilently(EventStates aStates)
560 : {
561 1225 : mState &= ~aStates;
562 1225 : }
563 :
564 : private:
565 : // Need to allow the ESM, nsGlobalWindow, and the focus manager to
566 : // set our state
567 : friend class mozilla::EventStateManager;
568 : friend class ::nsGlobalWindow;
569 : friend class ::nsFocusManager;
570 :
571 : // Allow CusomtElementRegistry to call AddStates.
572 : friend class CustomElementRegistry;
573 :
574 : // Also need to allow Link to call UpdateLinkState.
575 : friend class Link;
576 :
577 : void NotifyStateChange(EventStates aStates);
578 :
579 : void NotifyStyleStateChange(EventStates aStates);
580 :
581 : // Style state computed from element's state and style locks.
582 : EventStates StyleStateFromLocks() const;
583 :
584 : protected:
585 : // Methods for the ESM, nsGlobalWindow and focus manager to manage state bits.
586 : // These will handle setting up script blockers when they notify, so no need
587 : // to do it in the callers unless desired. States passed here must only be
588 : // those in EXTERNALLY_MANAGED_STATES.
589 31 : virtual void AddStates(EventStates aStates)
590 : {
591 31 : NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
592 : "Should only be adding externally-managed states here");
593 31 : AddStatesSilently(aStates);
594 31 : NotifyStateChange(aStates);
595 31 : }
596 14 : virtual void RemoveStates(EventStates aStates)
597 : {
598 14 : NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
599 : "Should only be removing externally-managed states here");
600 14 : RemoveStatesSilently(aStates);
601 14 : NotifyStateChange(aStates);
602 14 : }
603 0 : virtual void ToggleStates(EventStates aStates, bool aNotify)
604 : {
605 0 : NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
606 : "Should only be removing externally-managed states here");
607 0 : mState ^= aStates;
608 0 : if (aNotify) {
609 0 : NotifyStateChange(aStates);
610 : }
611 0 : }
612 :
613 : public:
614 : // Public methods to manage state bits in MANUALLY_MANAGED_STATES.
615 0 : void AddManuallyManagedStates(EventStates aStates)
616 : {
617 0 : MOZ_ASSERT(MANUALLY_MANAGED_STATES.HasAllStates(aStates),
618 : "Should only be adding manually-managed states here");
619 0 : AddStates(aStates);
620 0 : }
621 0 : void RemoveManuallyManagedStates(EventStates aStates)
622 : {
623 0 : MOZ_ASSERT(MANUALLY_MANAGED_STATES.HasAllStates(aStates),
624 : "Should only be removing manually-managed states here");
625 0 : RemoveStates(aStates);
626 0 : }
627 :
628 : virtual void UpdateEditableState(bool aNotify) override;
629 :
630 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
631 : nsIContent* aBindingParent,
632 : bool aCompileEventHandlers) override;
633 : virtual void UnbindFromTree(bool aDeep = true,
634 : bool aNullParent = true) override;
635 :
636 : /**
637 : * Normalizes an attribute name and returns it as a nodeinfo if an attribute
638 : * with that name exists. This method is intended for character case
639 : * conversion if the content object is case insensitive (e.g. HTML). Returns
640 : * the nodeinfo of the attribute with the specified name if one exists or
641 : * null otherwise.
642 : *
643 : * @param aStr the unparsed attribute string
644 : * @return the node info. May be nullptr.
645 : */
646 : already_AddRefed<mozilla::dom::NodeInfo>
647 : GetExistingAttrNameFromQName(const nsAString& aStr) const;
648 :
649 : MOZ_ALWAYS_INLINE // Avoid a crashy hook from Avast 10 Beta (Bug 1058131)
650 418 : nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
651 : const nsAString& aValue, bool aNotify)
652 : {
653 418 : return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
654 : }
655 :
656 : /**
657 : * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
658 : * is true or there are mutation listeners that must be triggered, the
659 : * attribute is currently set, and the new value that is about to be set is
660 : * different to the current value. As a perf optimization the new and old
661 : * values will not actually be compared if we aren't notifying and we don't
662 : * have mutation listeners (in which case it's cheap to just return false
663 : * and let the caller go ahead and set the value).
664 : * @param aOldValue [out] Set to the old value of the attribute, but only if
665 : * there are event listeners. If set, the type of aOldValue will be either
666 : * nsAttrValue::eString or nsAttrValue::eAtom.
667 : * @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
668 : * nsIDOMMutationEvent::ADDITION, but only if this helper returns true
669 : * @param aHasListeners [out] Set to true if there are mutation event
670 : * listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
671 : * @param aOldValueSet [out] Indicates whether an old attribute value has been
672 : * stored in aOldValue. The bool will be set to true if a value was stored.
673 : */
674 : bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsIAtom* aName,
675 : nsIAtom* aPrefix,
676 : const nsAttrValueOrString& aValue,
677 : bool aNotify, nsAttrValue& aOldValue,
678 : uint8_t* aModType, bool* aHasListeners,
679 : bool* aOldValueSet);
680 :
681 : /**
682 : * Notifies mutation listeners if aNotify is true, there are mutation
683 : * listeners, and the attribute value is changing.
684 : *
685 : * @param aNamespaceID The namespace of the attribute
686 : * @param aName The local name of the attribute
687 : * @param aPrefix The prefix of the attribute
688 : * @param aValue The value that the attribute is being changed to
689 : * @param aNotify If true, mutation listeners will be notified if they exist
690 : * and the attribute value is changing
691 : * @param aOldValue [out] Set to the old value of the attribute, but only if
692 : * there are event listeners. If set, the type of aOldValue will be either
693 : * nsAttrValue::eString or nsAttrValue::eAtom.
694 : * @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
695 : * nsIDOMMutationEvent::ADDITION, but only if this helper returns true
696 : * @param aHasListeners [out] Set to true if there are mutation event
697 : * listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
698 : * @param aOldValueSet [out] Indicates whether an old attribute value has been
699 : * stored in aOldValue. The bool will be set to true if a value was stored.
700 : */
701 : bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
702 : nsIAtom* aPrefix,
703 : const nsAttrValueOrString& aValue,
704 : bool aNotify, nsAttrValue& aOldValue,
705 : uint8_t* aModType, bool* aHasListeners,
706 : bool* aOldValueSet);
707 :
708 : virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
709 : const nsAString& aValue, bool aNotify) override;
710 : // aParsedValue receives the old value of the attribute. That's useful if
711 : // either the input or output value of aParsedValue is StoresOwnData.
712 : nsresult SetParsedAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
713 : nsAttrValue& aParsedValue, bool aNotify);
714 : // GetAttr is not inlined on purpose, to keep down codesize from all
715 : // the inlined nsAttrValue bits for C++ callers.
716 : bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
717 : nsAString& aResult) const;
718 : inline bool HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const;
719 : // aCaseSensitive == eIgnoreCaase means ASCII case-insensitive matching.
720 : inline bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
721 : const nsAString& aValue,
722 : nsCaseTreatment aCaseSensitive) const;
723 : inline bool AttrValueIs(int32_t aNameSpaceID, nsIAtom* aName,
724 : nsIAtom* aValue,
725 : nsCaseTreatment aCaseSensitive) const;
726 : virtual int32_t FindAttrValueIn(int32_t aNameSpaceID,
727 : nsIAtom* aName,
728 : AttrValuesArray* aValues,
729 : nsCaseTreatment aCaseSensitive) const override;
730 : virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
731 : bool aNotify) override;
732 : virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const override;
733 : virtual BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const override;
734 : virtual uint32_t GetAttrCount() const override;
735 : virtual bool IsNodeOfType(uint32_t aFlags) const override;
736 :
737 : /**
738 : * Get the class list of this element (this corresponds to the value of the
739 : * class attribute). This may be null if there are no classes, but that's not
740 : * guaranteed (e.g. we could have class="").
741 : */
742 30850 : const nsAttrValue* GetClasses() const {
743 30850 : if (MayHaveClass()) {
744 18576 : return DoGetClasses();
745 : }
746 12274 : return nullptr;
747 : }
748 :
749 : #ifdef DEBUG
750 0 : virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override
751 : {
752 0 : List(out, aIndent, EmptyCString());
753 0 : }
754 : virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
755 : void List(FILE* out, int32_t aIndent, const nsCString& aPrefix) const;
756 : void ListAttributes(FILE* out) const;
757 : #endif
758 :
759 : void Describe(nsAString& aOutDescription) const override;
760 :
761 : /*
762 : * Attribute Mapping Helpers
763 : */
764 : struct MappedAttributeEntry {
765 : nsIAtom** attribute;
766 : };
767 :
768 : /**
769 : * A common method where you can just pass in a list of maps to check
770 : * for attribute dependence. Most implementations of
771 : * IsAttributeMapped should use this function as a default
772 : * handler.
773 : */
774 : template<size_t N>
775 : static bool
776 1861 : FindAttributeDependence(const nsIAtom* aAttribute,
777 : const MappedAttributeEntry* const (&aMaps)[N])
778 : {
779 1861 : return FindAttributeDependence(aAttribute, aMaps, N);
780 : }
781 :
782 : static nsIAtom*** HTMLSVGPropertiesToTraverseAndUnlink();
783 :
784 : private:
785 : void DescribeAttribute(uint32_t index, nsAString& aOutDescription) const;
786 :
787 : static bool
788 : FindAttributeDependence(const nsIAtom* aAttribute,
789 : const MappedAttributeEntry* const aMaps[],
790 : uint32_t aMapCount);
791 :
792 : protected:
793 21342 : inline bool GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
794 : DOMString& aResult) const
795 : {
796 21342 : NS_ASSERTION(nullptr != aName, "must have attribute name");
797 21342 : NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
798 : "must have a real namespace ID!");
799 21342 : MOZ_ASSERT(aResult.HasStringBuffer() && aResult.StringBufferLength() == 0,
800 : "Should have empty string coming in");
801 21342 : const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
802 21342 : if (val) {
803 1960 : val->ToString(aResult);
804 1960 : return true;
805 : }
806 : // else DOMString comes pre-emptied.
807 19382 : return false;
808 : }
809 :
810 : public:
811 56070 : bool HasAttrs() const { return mAttrsAndChildren.HasAttrs(); }
812 :
813 0 : inline bool GetAttr(const nsAString& aName, DOMString& aResult) const
814 : {
815 0 : MOZ_ASSERT(aResult.HasStringBuffer() && aResult.StringBufferLength() == 0,
816 : "Should have empty string coming in");
817 0 : const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName);
818 0 : if (val) {
819 0 : val->ToString(aResult);
820 0 : return true;
821 : }
822 : // else DOMString comes pre-emptied.
823 0 : return false;
824 : }
825 :
826 0 : void GetTagName(nsAString& aTagName) const
827 : {
828 0 : aTagName = NodeName();
829 0 : }
830 3 : void GetId(nsAString& aId) const
831 : {
832 3 : GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
833 3 : }
834 74 : void GetId(DOMString& aId) const
835 : {
836 74 : GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
837 74 : }
838 41 : void SetId(const nsAString& aId)
839 : {
840 41 : SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
841 41 : }
842 : void GetClassName(nsAString& aClassName)
843 : {
844 : GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName);
845 : }
846 0 : void GetClassName(DOMString& aClassName)
847 : {
848 0 : GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName);
849 0 : }
850 8 : void SetClassName(const nsAString& aClassName)
851 : {
852 8 : SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aClassName, true);
853 8 : }
854 :
855 : nsDOMTokenList* ClassList();
856 0 : nsDOMAttributeMap* Attributes()
857 : {
858 0 : nsDOMSlots* slots = DOMSlots();
859 0 : if (!slots->mAttributeMap) {
860 0 : slots->mAttributeMap = new nsDOMAttributeMap(this);
861 : }
862 :
863 0 : return slots->mAttributeMap;
864 : }
865 :
866 : void GetAttributeNames(nsTArray<nsString>& aResult);
867 :
868 29 : void GetAttribute(const nsAString& aName, nsString& aReturn)
869 : {
870 58 : DOMString str;
871 29 : GetAttribute(aName, str);
872 29 : str.ToString(aReturn);
873 29 : }
874 :
875 : void GetAttribute(const nsAString& aName, DOMString& aReturn);
876 : void GetAttributeNS(const nsAString& aNamespaceURI,
877 : const nsAString& aLocalName,
878 : nsAString& aReturn);
879 : void SetAttribute(const nsAString& aName, const nsAString& aValue,
880 : ErrorResult& aError);
881 : void SetAttributeNS(const nsAString& aNamespaceURI,
882 : const nsAString& aLocalName,
883 : const nsAString& aValue,
884 : ErrorResult& aError);
885 : void RemoveAttribute(const nsAString& aName,
886 : ErrorResult& aError);
887 : void RemoveAttributeNS(const nsAString& aNamespaceURI,
888 : const nsAString& aLocalName,
889 : ErrorResult& aError);
890 33 : bool HasAttribute(const nsAString& aName) const
891 : {
892 33 : return InternalGetAttrNameFromQName(aName) != nullptr;
893 : }
894 : bool HasAttributeNS(const nsAString& aNamespaceURI,
895 : const nsAString& aLocalName) const;
896 0 : bool HasAttributes() const
897 : {
898 0 : return HasAttrs();
899 : }
900 : Element* Closest(const nsAString& aSelector,
901 : ErrorResult& aResult);
902 : bool Matches(const nsAString& aSelector,
903 : ErrorResult& aError);
904 : already_AddRefed<nsIHTMLCollection>
905 : GetElementsByTagName(const nsAString& aQualifiedName);
906 : already_AddRefed<nsIHTMLCollection>
907 : GetElementsByTagNameNS(const nsAString& aNamespaceURI,
908 : const nsAString& aLocalName,
909 : ErrorResult& aError);
910 : already_AddRefed<nsIHTMLCollection>
911 : GetElementsByClassName(const nsAString& aClassNames);
912 :
913 4223 : CSSPseudoElementType GetPseudoElementType() const {
914 4223 : nsresult rv = NS_OK;
915 4223 : auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
916 4223 : if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
917 4129 : return CSSPseudoElementType::NotPseudo;
918 : }
919 94 : return CSSPseudoElementType(reinterpret_cast<uintptr_t>(raw));
920 : }
921 :
922 10 : void SetPseudoElementType(CSSPseudoElementType aPseudo) {
923 : static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
924 : "Need to be able to store this in a void*");
925 10 : MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
926 10 : SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
927 10 : }
928 :
929 : private:
930 : /**
931 : * Implement the algorithm specified at
932 : * https://dom.spec.whatwg.org/#insert-adjacent for both
933 : * |insertAdjacentElement()| and |insertAdjacentText()| APIs.
934 : */
935 : nsINode* InsertAdjacent(const nsAString& aWhere,
936 : nsINode* aNode,
937 : ErrorResult& aError);
938 :
939 : public:
940 : Element* InsertAdjacentElement(const nsAString& aWhere,
941 : Element& aElement,
942 : ErrorResult& aError);
943 :
944 : void InsertAdjacentText(const nsAString& aWhere,
945 : const nsAString& aData,
946 : ErrorResult& aError);
947 :
948 0 : void SetPointerCapture(int32_t aPointerId, ErrorResult& aError)
949 : {
950 0 : bool activeState = false;
951 0 : if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
952 0 : aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
953 0 : return;
954 : }
955 0 : if (!IsInUncomposedDoc()) {
956 0 : aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
957 0 : return;
958 : }
959 0 : if (!activeState) {
960 0 : return;
961 : }
962 0 : nsIPresShell::SetPointerCapturingContent(aPointerId, this);
963 : }
964 0 : void ReleasePointerCapture(int32_t aPointerId, ErrorResult& aError)
965 : {
966 0 : bool activeState = false;
967 0 : if (!nsIPresShell::GetPointerInfo(aPointerId, activeState)) {
968 0 : aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
969 0 : return;
970 : }
971 0 : if (HasPointerCapture(aPointerId)) {
972 0 : nsIPresShell::ReleasePointerCapturingContent(aPointerId);
973 : }
974 : }
975 0 : bool HasPointerCapture(long aPointerId)
976 : {
977 : nsIPresShell::PointerCaptureInfo* pointerCaptureInfo =
978 0 : nsIPresShell::GetPointerCaptureInfo(aPointerId);
979 0 : if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
980 0 : return true;
981 : }
982 0 : return false;
983 : }
984 0 : void SetCapture(bool aRetargetToElement)
985 : {
986 : // If there is already an active capture, ignore this request. This would
987 : // occur if a splitter, frame resizer, etc had already captured and we don't
988 : // want to override those.
989 0 : if (!nsIPresShell::GetCapturingContent()) {
990 0 : nsIPresShell::SetCapturingContent(this, CAPTURE_PREVENTDRAG |
991 0 : (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
992 : }
993 0 : }
994 :
995 0 : void SetCaptureAlways(bool aRetargetToElement)
996 : {
997 0 : nsIPresShell::SetCapturingContent(this,
998 : CAPTURE_PREVENTDRAG | CAPTURE_IGNOREALLOWED |
999 0 : (aRetargetToElement ? CAPTURE_RETARGETTOELEMENT : 0));
1000 0 : }
1001 :
1002 0 : void ReleaseCapture()
1003 : {
1004 0 : if (nsIPresShell::GetCapturingContent() == this) {
1005 0 : nsIPresShell::SetCapturingContent(nullptr, 0);
1006 : }
1007 0 : }
1008 :
1009 : void RequestFullscreen(CallerType aCallerType, ErrorResult& aError);
1010 : void RequestPointerLock(CallerType aCallerType);
1011 : Attr* GetAttributeNode(const nsAString& aName);
1012 : already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
1013 : ErrorResult& aError);
1014 : already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
1015 : ErrorResult& aError);
1016 : Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
1017 : const nsAString& aLocalName);
1018 : already_AddRefed<Attr> SetAttributeNodeNS(Attr& aNewAttr,
1019 : ErrorResult& aError);
1020 :
1021 : already_AddRefed<DOMRectList> GetClientRects();
1022 : already_AddRefed<DOMRect> GetBoundingClientRect();
1023 :
1024 : already_AddRefed<ShadowRoot> CreateShadowRoot(ErrorResult& aError);
1025 : already_AddRefed<DestinationInsertionPointList> GetDestinationInsertionPoints();
1026 :
1027 17316 : ShadowRoot *FastGetShadowRoot() const
1028 : {
1029 17316 : nsDOMSlots* slots = GetExistingDOMSlots();
1030 17316 : return slots ? slots->mShadowRoot.get() : nullptr;
1031 : }
1032 :
1033 : void ScrollIntoView();
1034 : void ScrollIntoView(bool aTop);
1035 : void ScrollIntoView(const ScrollIntoViewOptions &aOptions);
1036 : void Scroll(double aXScroll, double aYScroll);
1037 : void Scroll(const ScrollToOptions& aOptions);
1038 : void ScrollTo(double aXScroll, double aYScroll);
1039 : void ScrollTo(const ScrollToOptions& aOptions);
1040 : void ScrollBy(double aXScrollDif, double aYScrollDif);
1041 : void ScrollBy(const ScrollToOptions& aOptions);
1042 : /* Scrolls without flushing the layout.
1043 : * aDx is the x offset, aDy the y offset in CSS pixels.
1044 : * Returns true if we actually scrolled.
1045 : */
1046 : bool ScrollByNoFlush(int32_t aDx, int32_t aDy);
1047 : int32_t ScrollTop();
1048 : void SetScrollTop(int32_t aScrollTop);
1049 : int32_t ScrollLeft();
1050 : void SetScrollLeft(int32_t aScrollLeft);
1051 : int32_t ScrollWidth();
1052 : int32_t ScrollHeight();
1053 : void MozScrollSnap();
1054 0 : int32_t ClientTop()
1055 : {
1056 0 : return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
1057 : }
1058 0 : int32_t ClientLeft()
1059 : {
1060 0 : return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
1061 : }
1062 0 : int32_t ClientWidth()
1063 : {
1064 0 : return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().width);
1065 : }
1066 0 : int32_t ClientHeight()
1067 : {
1068 0 : return nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().height);
1069 : }
1070 0 : int32_t ScrollTopMin()
1071 : {
1072 0 : nsIScrollableFrame* sf = GetScrollFrame();
1073 0 : return sf ?
1074 0 : nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().y) : 0;
1075 : }
1076 0 : int32_t ScrollTopMax()
1077 : {
1078 0 : nsIScrollableFrame* sf = GetScrollFrame();
1079 0 : return sf ?
1080 0 : nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().YMost()) :
1081 0 : 0;
1082 : }
1083 1 : int32_t ScrollLeftMin()
1084 : {
1085 1 : nsIScrollableFrame* sf = GetScrollFrame();
1086 3 : return sf ?
1087 3 : nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().x) : 0;
1088 : }
1089 1 : int32_t ScrollLeftMax()
1090 : {
1091 1 : nsIScrollableFrame* sf = GetScrollFrame();
1092 3 : return sf ?
1093 4 : nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollRange().XMost()) :
1094 2 : 0;
1095 : }
1096 :
1097 : void GetGridFragments(nsTArray<RefPtr<Grid>>& aResult);
1098 :
1099 : already_AddRefed<DOMMatrixReadOnly> GetTransformToAncestor(Element& aAncestor);
1100 : already_AddRefed<DOMMatrixReadOnly> GetTransformToParent();
1101 : already_AddRefed<DOMMatrixReadOnly> GetTransformToViewport();
1102 :
1103 : already_AddRefed<Animation>
1104 : Animate(JSContext* aContext,
1105 : JS::Handle<JSObject*> aKeyframes,
1106 : const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
1107 : ErrorResult& aError);
1108 :
1109 : // A helper method that factors out the common functionality needed by
1110 : // Element::Animate and CSSPseudoElement::Animate
1111 : static already_AddRefed<Animation>
1112 : Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
1113 : JSContext* aContext,
1114 : JS::Handle<JSObject*> aKeyframes,
1115 : const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
1116 : ErrorResult& aError);
1117 :
1118 : // Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
1119 : // Callers must keep this element alive because flushing style may destroy
1120 : // this element.
1121 : void GetAnimations(const AnimationFilter& filter,
1122 : nsTArray<RefPtr<Animation>>& aAnimations);
1123 : static void GetAnimationsUnsorted(Element* aElement,
1124 : CSSPseudoElementType aPseudoType,
1125 : nsTArray<RefPtr<Animation>>& aAnimations);
1126 :
1127 : NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
1128 : virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
1129 : void GetOuterHTML(nsAString& aOuterHTML);
1130 : void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
1131 : void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
1132 : ErrorResult& aError);
1133 :
1134 : //----------------------------------------
1135 :
1136 : /**
1137 : * Add a script event listener with the given event handler name
1138 : * (like onclick) and with the value as JS
1139 : * @param aEventName the event listener name
1140 : * @param aValue the JS to attach
1141 : * @param aDefer indicates if deferred execution is allowed
1142 : */
1143 : nsresult SetEventHandler(nsIAtom* aEventName,
1144 : const nsAString& aValue,
1145 : bool aDefer = true);
1146 :
1147 : /**
1148 : * Do whatever needs to be done when the mouse leaves a link
1149 : */
1150 : nsresult LeaveLink(nsPresContext* aPresContext);
1151 :
1152 : static bool ShouldBlur(nsIContent *aContent);
1153 :
1154 : /**
1155 : * Method to create and dispatch a left-click event loosely based on
1156 : * aSourceEvent. If aFullDispatch is true, the event will be dispatched
1157 : * through the full dispatching of the presshell of the aPresContext; if it's
1158 : * false the event will be dispatched only as a DOM event.
1159 : * If aPresContext is nullptr, this does nothing.
1160 : *
1161 : * @param aFlags Extra flags for the dispatching event. The true flags
1162 : * will be respected.
1163 : */
1164 : static nsresult DispatchClickEvent(nsPresContext* aPresContext,
1165 : WidgetInputEvent* aSourceEvent,
1166 : nsIContent* aTarget,
1167 : bool aFullDispatch,
1168 : const EventFlags* aFlags,
1169 : nsEventStatus* aStatus);
1170 :
1171 : /**
1172 : * Method to dispatch aEvent to aTarget. If aFullDispatch is true, the event
1173 : * will be dispatched through the full dispatching of the presshell of the
1174 : * aPresContext; if it's false the event will be dispatched only as a DOM
1175 : * event.
1176 : * If aPresContext is nullptr, this does nothing.
1177 : */
1178 : using nsIContent::DispatchEvent;
1179 : static nsresult DispatchEvent(nsPresContext* aPresContext,
1180 : WidgetEvent* aEvent,
1181 : nsIContent* aTarget,
1182 : bool aFullDispatch,
1183 : nsEventStatus* aStatus);
1184 :
1185 : /**
1186 : * Get the primary frame for this content with flushing
1187 : *
1188 : * @param aType the kind of flush to do, typically FlushType::Frames or
1189 : * FlushType::Layout
1190 : * @return the primary frame
1191 : */
1192 : nsIFrame* GetPrimaryFrame(FlushType aType);
1193 : // Work around silly C++ name hiding stuff
1194 4702 : nsIFrame* GetPrimaryFrame() const { return nsIContent::GetPrimaryFrame(); }
1195 :
1196 93613 : const nsAttrValue* GetParsedAttr(nsIAtom* aAttr) const
1197 : {
1198 93613 : return mAttrsAndChildren.GetAttr(aAttr);
1199 : }
1200 :
1201 2501 : const nsAttrValue* GetParsedAttr(nsIAtom* aAttr, int32_t aNameSpaceID) const
1202 : {
1203 2501 : return mAttrsAndChildren.GetAttr(aAttr, aNameSpaceID);
1204 : }
1205 :
1206 : /**
1207 : * Returns the attribute map, if there is one.
1208 : *
1209 : * @return existing attribute map or nullptr.
1210 : */
1211 0 : nsDOMAttributeMap *GetAttributeMap()
1212 : {
1213 0 : nsDOMSlots *slots = GetExistingDOMSlots();
1214 :
1215 0 : return slots ? slots->mAttributeMap.get() : nullptr;
1216 : }
1217 :
1218 0 : virtual void RecompileScriptEventListeners()
1219 : {
1220 0 : }
1221 :
1222 : /**
1223 : * Get the attr info for the given namespace ID and attribute name. The
1224 : * namespace ID must not be kNameSpaceID_Unknown and the name must not be
1225 : * null. Note that this can only return info on attributes that actually
1226 : * live on this element (and is only virtual to handle XUL prototypes). That
1227 : * is, this should only be called from methods that only care about attrs
1228 : * that effectively live in mAttrsAndChildren.
1229 : */
1230 : virtual BorrowedAttrInfo GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const;
1231 :
1232 : /**
1233 : * Called when we have been adopted, and the information of the
1234 : * node has been changed.
1235 : *
1236 : * The new document can be reached via OwnerDoc().
1237 : *
1238 : * If you override this method,
1239 : * please call up to the parent NodeInfoChanged.
1240 : *
1241 : * If you change this, change also the similar method in Link.
1242 : */
1243 0 : virtual void NodeInfoChanged(nsIDocument* aOldDoc) {}
1244 :
1245 : /**
1246 : * Parse a string into an nsAttrValue for a CORS attribute. This
1247 : * never fails. The resulting value is an enumerated value whose
1248 : * GetEnumValue() returns one of the above constants.
1249 : */
1250 : static void ParseCORSValue(const nsAString& aValue, nsAttrValue& aResult);
1251 :
1252 : /**
1253 : * Return the CORS mode for a given string
1254 : */
1255 : static CORSMode StringToCORSMode(const nsAString& aValue);
1256 :
1257 : /**
1258 : * Return the CORS mode for a given nsAttrValue (which may be null,
1259 : * but if not should have been parsed via ParseCORSValue).
1260 : */
1261 : static CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
1262 :
1263 : virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) final override;
1264 :
1265 : nsINode* GetScopeChainParent() const override;
1266 :
1267 : /**
1268 : * Locate a TextEditor rooted at this content node, if there is one.
1269 : */
1270 : mozilla::TextEditor* GetTextEditorInternal();
1271 :
1272 : /**
1273 : * Helper method for NS_IMPL_BOOL_ATTR macro.
1274 : * Gets value of boolean attribute. Only works for attributes in null
1275 : * namespace.
1276 : *
1277 : * @param aAttr name of attribute.
1278 : * @param aValue Boolean value of attribute.
1279 : */
1280 74 : bool GetBoolAttr(nsIAtom* aAttr) const
1281 : {
1282 74 : return HasAttr(kNameSpaceID_None, aAttr);
1283 : }
1284 :
1285 : /**
1286 : * Helper method for NS_IMPL_BOOL_ATTR macro.
1287 : * Sets value of boolean attribute by removing attribute or setting it to
1288 : * the empty string. Only works for attributes in null namespace.
1289 : *
1290 : * @param aAttr name of attribute.
1291 : * @param aValue Boolean value of attribute.
1292 : */
1293 : nsresult SetBoolAttr(nsIAtom* aAttr, bool aValue);
1294 :
1295 : /**
1296 : * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
1297 : * Gets the enum value string of an attribute and using a default value if
1298 : * the attribute is missing or the string is an invalid enum value.
1299 : *
1300 : * @param aType the name of the attribute.
1301 : * @param aDefault the default value if the attribute is missing or invalid.
1302 : * @param aResult string corresponding to the value [out].
1303 : */
1304 : void GetEnumAttr(nsIAtom* aAttr,
1305 : const char* aDefault,
1306 : nsAString& aResult) const;
1307 :
1308 : /**
1309 : * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES.
1310 : * Gets the enum value string of an attribute and using the default missing
1311 : * value if the attribute is missing or the default invalid value if the
1312 : * string is an invalid enum value.
1313 : *
1314 : * @param aType the name of the attribute.
1315 : * @param aDefaultMissing the default value if the attribute is missing. If
1316 : null and the attribute is missing, aResult will be
1317 : set to the null DOMString; this only matters for
1318 : cases in which we're reflecting a nullable string.
1319 : * @param aDefaultInvalid the default value if the attribute is invalid.
1320 : * @param aResult string corresponding to the value [out].
1321 : */
1322 : void GetEnumAttr(nsIAtom* aAttr,
1323 : const char* aDefaultMissing,
1324 : const char* aDefaultInvalid,
1325 : nsAString& aResult) const;
1326 :
1327 : /**
1328 : * Unset an attribute.
1329 : */
1330 0 : void UnsetAttr(nsIAtom* aAttr, ErrorResult& aError)
1331 : {
1332 0 : aError = UnsetAttr(kNameSpaceID_None, aAttr, true);
1333 0 : }
1334 :
1335 : /**
1336 : * Set an attribute in the simplest way possible.
1337 : */
1338 12 : void SetAttr(nsIAtom* aAttr, const nsAString& aValue, ErrorResult& aError)
1339 : {
1340 12 : aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
1341 12 : }
1342 :
1343 : /**
1344 : * Set a content attribute via a reflecting nullable string IDL
1345 : * attribute (e.g. a CORS attribute). If DOMStringIsNull(aValue),
1346 : * this will actually remove the content attribute.
1347 : */
1348 : void SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue,
1349 : ErrorResult& aError);
1350 :
1351 : /**
1352 : * Retrieve the ratio of font-size-inflated text font size to computed font
1353 : * size for this element. This will query the element for its primary frame,
1354 : * and then use this to get font size inflation information about the frame.
1355 : *
1356 : * @returns The font size inflation ratio (inflated font size to uninflated
1357 : * font size) for the primary frame of this element. Returns 1.0
1358 : * by default if font size inflation is not enabled. Returns -1
1359 : * if the element does not have a primary frame.
1360 : *
1361 : * @note The font size inflation ratio that is returned is actually the
1362 : * font size inflation data for the element's _primary frame_, not the
1363 : * element itself, but for most purposes, this should be sufficient.
1364 : */
1365 : float FontSizeInflation();
1366 :
1367 : net::ReferrerPolicy GetReferrerPolicyAsEnum();
1368 : net::ReferrerPolicy ReferrerPolicyFromAttr(const nsAttrValue* aValue);
1369 :
1370 : /*
1371 : * Helpers for .dataset. This is implemented on Element, though only some
1372 : * sorts of elements expose it to JS as a .dataset property
1373 : */
1374 : // Getter, to be called from bindings.
1375 : already_AddRefed<nsDOMStringMap> Dataset();
1376 : // Callback for destructor of dataset to ensure to null out our weak pointer
1377 : // to it.
1378 : void ClearDataset();
1379 :
1380 : void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
1381 : void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
1382 : bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
1383 :
1384 : protected:
1385 : /*
1386 : * Named-bools for use with SetAttrAndNotify to make call sites easier to
1387 : * read.
1388 : */
1389 : static const bool kFireMutationEvent = true;
1390 : static const bool kDontFireMutationEvent = false;
1391 : static const bool kNotifyDocumentObservers = true;
1392 : static const bool kDontNotifyDocumentObservers = false;
1393 : static const bool kCallAfterSetAttr = true;
1394 : static const bool kDontCallAfterSetAttr = false;
1395 :
1396 : /**
1397 : * Set attribute and (if needed) notify documentobservers and fire off
1398 : * mutation events. This will send the AttributeChanged notification.
1399 : * Callers of this method are responsible for calling AttributeWillChange,
1400 : * since that needs to happen before the new attr value has been set, and
1401 : * in particular before it has been parsed.
1402 : *
1403 : * For the boolean parameters, consider using the named bools above to aid
1404 : * code readability.
1405 : *
1406 : * @param aNamespaceID namespace of attribute
1407 : * @param aAttribute local-name of attribute
1408 : * @param aPrefix aPrefix of attribute
1409 : * @param aOldValue The old value of the attribute to use as a fallback
1410 : * in the cases where the actual old value (i.e.
1411 : * its current value) is !StoresOwnData() --- in which
1412 : * case the current value is probably already useless.
1413 : * If the current value is StoresOwnData() (or absent),
1414 : * aOldValue will not be used. aOldValue will only be set
1415 : * in certain circumstances (there are mutation
1416 : * listeners, element is a custom element, attribute was
1417 : * not previously unset). Otherwise it will be null.
1418 : * @param aParsedValue parsed new value of attribute. Replaced by the
1419 : * old value of the attribute. This old value is only
1420 : * useful if either it or the new value is StoresOwnData.
1421 : * @param aModType nsIDOMMutationEvent::MODIFICATION or ADDITION. Only
1422 : * needed if aFireMutation or aNotify is true.
1423 : * @param aFireMutation should mutation-events be fired?
1424 : * @param aNotify should we notify document-observers?
1425 : * @param aCallAfterSetAttr should we call AfterSetAttr?
1426 : * @param aComposedDocument The current composed document of the element.
1427 : */
1428 : nsresult SetAttrAndNotify(int32_t aNamespaceID,
1429 : nsIAtom* aName,
1430 : nsIAtom* aPrefix,
1431 : const nsAttrValue* aOldValue,
1432 : nsAttrValue& aParsedValue,
1433 : uint8_t aModType,
1434 : bool aFireMutation,
1435 : bool aNotify,
1436 : bool aCallAfterSetAttr,
1437 : nsIDocument* aComposedDocument,
1438 : const mozAutoDocUpdate& aGuard);
1439 :
1440 : /**
1441 : * Scroll to a new position using behavior evaluated from CSS and
1442 : * a CSSOM-View DOM method ScrollOptions dictionary. The scrolling may
1443 : * be performed asynchronously or synchronously depending on the resolved
1444 : * scroll-behavior.
1445 : *
1446 : * @param aScroll Destination of scroll, in CSS pixels
1447 : * @param aOptions Dictionary of options to be evaluated
1448 : */
1449 : void Scroll(const CSSIntPoint& aScroll, const ScrollOptions& aOptions);
1450 :
1451 : /**
1452 : * Convert an attribute string value to attribute type based on the type of
1453 : * attribute. Called by SetAttr(). Note that at the moment we only do this
1454 : * for attributes in the null namespace (kNameSpaceID_None).
1455 : *
1456 : * @param aNamespaceID the namespace of the attribute to convert
1457 : * @param aAttribute the attribute to convert
1458 : * @param aValue the string value to convert
1459 : * @param aResult the nsAttrValue [OUT]
1460 : * @return true if the parsing was successful, false otherwise
1461 : */
1462 : virtual bool ParseAttribute(int32_t aNamespaceID,
1463 : nsIAtom* aAttribute,
1464 : const nsAString& aValue,
1465 : nsAttrValue& aResult);
1466 :
1467 : /**
1468 : * Try to set the attribute as a mapped attribute, if applicable. This will
1469 : * only be called for attributes that are in the null namespace and only on
1470 : * attributes that returned true when passed to IsAttributeMapped. The
1471 : * caller will not try to set the attr in any other way if this method
1472 : * returns true (the value of aRetval does not matter for that purpose).
1473 : *
1474 : * @param aName the name of the attribute
1475 : * @param aValue the nsAttrValue to set. Will be swapped with the existing
1476 : * value of the attribute if the attribute already exists.
1477 : * @param [out] aValueWasSet If the attribute was not set previously,
1478 : * aValue will be swapped with an empty attribute
1479 : * and aValueWasSet will be set to false. Otherwise,
1480 : * aValueWasSet will be set to true and aValue will
1481 : * contain the previous value set.
1482 : * @param [out] aRetval the nsresult status of the operation, if any.
1483 : * @return true if the setting was attempted, false otherwise.
1484 : */
1485 : virtual bool SetAndSwapMappedAttribute(nsIAtom* aName,
1486 : nsAttrValue& aValue,
1487 : bool* aValueWasSet,
1488 : nsresult* aRetval);
1489 :
1490 : /**
1491 : * Hook that is called by Element::SetAttr to allow subclasses to
1492 : * deal with attribute sets. This will only be called after we verify that
1493 : * we're actually doing an attr set and will be called before
1494 : * AttributeWillChange and before ParseAttribute and hence before we've set
1495 : * the new value.
1496 : *
1497 : * @param aNamespaceID the namespace of the attr being set
1498 : * @param aName the localname of the attribute being set
1499 : * @param aValue the value it's being set to represented as either a string or
1500 : * a parsed nsAttrValue. Alternatively, if the attr is being removed it
1501 : * will be null.
1502 : * @param aNotify Whether we plan to notify document observers.
1503 : */
1504 : virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
1505 : const nsAttrValueOrString* aValue,
1506 : bool aNotify);
1507 :
1508 : /**
1509 : * Hook that is called by Element::SetAttr to allow subclasses to
1510 : * deal with attribute sets. This will only be called after we have called
1511 : * SetAndSwapAttr (that is, after we have actually set the attr). It will
1512 : * always be called under a scriptblocker.
1513 : *
1514 : * @param aNamespaceID the namespace of the attr being set
1515 : * @param aName the localname of the attribute being set
1516 : * @param aValue the value it's being set to. If null, the attr is being
1517 : * removed.
1518 : * @param aOldValue the value that the attribute had previously. If null,
1519 : * the attr was not previously set. This argument may not have the
1520 : * correct value for SVG elements, or other cases in which the
1521 : * attribute value doesn't store its own data
1522 : * @param aNotify Whether we plan to notify document observers.
1523 : */
1524 : // Note that this is inlined so that when subclasses call it it gets
1525 : // inlined. Those calls don't go through a vtable.
1526 1952 : virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
1527 : const nsAttrValue* aValue,
1528 : const nsAttrValue* aOldValue, bool aNotify)
1529 : {
1530 1952 : return NS_OK;
1531 : }
1532 :
1533 : /**
1534 : * This function shall be called just before the id attribute changes. It will
1535 : * be called after BeforeSetAttr. If the attribute being changed is not the id
1536 : * attribute, this function does nothing. Otherwise, it will remove the old id
1537 : * from the document's id cache.
1538 : *
1539 : * This must happen after BeforeSetAttr (rather than during) because the
1540 : * the subclasses' calls to BeforeSetAttr may notify on state changes. If they
1541 : * incorrectly determine whether the element had an id, the element may not be
1542 : * restyled properly.
1543 : *
1544 : * @param aNamespaceID the namespace of the attr being set
1545 : * @param aName the localname of the attribute being set
1546 : * @param aValue the new id value. Will be null if the id is being unset.
1547 : */
1548 : void PreIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
1549 : const nsAttrValueOrString* aValue);
1550 :
1551 : /**
1552 : * This function shall be called just after the id attribute changes. It will
1553 : * be called before AfterSetAttr. If the attribute being changed is not the id
1554 : * attribute, this function does nothing. Otherwise, it will add the new id to
1555 : * the document's id cache and properly set the ElementHasID flag.
1556 : *
1557 : * This must happen before AfterSetAttr (rather than during) because the
1558 : * the subclasses' calls to AfterSetAttr may notify on state changes. If they
1559 : * incorrectly determine whether the element now has an id, the element may
1560 : * not be restyled properly.
1561 : *
1562 : * @param aNamespaceID the namespace of the attr being set
1563 : * @param aName the localname of the attribute being set
1564 : * @param aValue the new id value. Will be null if the id is being unset.
1565 : */
1566 : void PostIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
1567 : const nsAttrValue* aValue);
1568 :
1569 : /**
1570 : * Usually, setting an attribute to the value that it already has results in
1571 : * no action. However, in some cases, setting an attribute to its current
1572 : * value should have the effect of, for example, forcing a reload of
1573 : * network data. To address that, this function will be called in this
1574 : * situation to allow the handling of such a case.
1575 : *
1576 : * @param aNamespaceID the namespace of the attr being set
1577 : * @param aName the localname of the attribute being set
1578 : * @param aValue the value it's being set to represented as either a string or
1579 : * a parsed nsAttrValue.
1580 : * @param aNotify Whether we plan to notify document observers.
1581 : */
1582 : // Note that this is inlined so that when subclasses call it it gets
1583 : // inlined. Those calls don't go through a vtable.
1584 101 : virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName,
1585 : const nsAttrValueOrString& aValue,
1586 : bool aNotify)
1587 : {
1588 101 : return NS_OK;
1589 : }
1590 :
1591 : /**
1592 : * Hook to allow subclasses to produce a different EventListenerManager if
1593 : * needed for attachment of attribute-defined handlers
1594 : */
1595 : virtual EventListenerManager*
1596 : GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer);
1597 :
1598 : /**
1599 : * Internal hook for converting an attribute name-string to nsAttrName in
1600 : * case there is such existing attribute. aNameToUse can be passed to get
1601 : * name which was used for looking for the attribute (lowercase in HTML).
1602 : */
1603 : const nsAttrName*
1604 : InternalGetAttrNameFromQName(const nsAString& aStr,
1605 : nsAutoString* aNameToUse = nullptr) const;
1606 :
1607 : nsIFrame* GetStyledFrame();
1608 :
1609 2 : virtual Element* GetNameSpaceElement() override
1610 : {
1611 2 : return this;
1612 : }
1613 :
1614 : Attr* GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
1615 : const nsAString& aLocalName);
1616 :
1617 : inline void RegisterActivityObserver();
1618 : inline void UnregisterActivityObserver();
1619 :
1620 : /**
1621 : * Add/remove this element to the documents id cache
1622 : */
1623 : void AddToIdTable(nsIAtom* aId);
1624 : void RemoveFromIdTable();
1625 :
1626 : /**
1627 : * Functions to carry out event default actions for links of all types
1628 : * (HTML links, XLinks, SVG "XLinks", etc.)
1629 : */
1630 :
1631 : /**
1632 : * Check that we meet the conditions to handle a link event
1633 : * and that we are actually on a link.
1634 : *
1635 : * @param aVisitor event visitor
1636 : * @param aURI the uri of the link, set only if the return value is true [OUT]
1637 : * @return true if we can handle the link event, false otherwise
1638 : */
1639 : bool CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
1640 : nsIURI** aURI) const;
1641 :
1642 : /**
1643 : * Handle status bar updates before they can be cancelled.
1644 : */
1645 : nsresult GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor);
1646 :
1647 : /**
1648 : * Handle default actions for link event if the event isn't consumed yet.
1649 : */
1650 : nsresult PostHandleEventForLinks(EventChainPostVisitor& aVisitor);
1651 :
1652 : /**
1653 : * Get the target of this link element. Consumers should established that
1654 : * this element is a link (probably using IsLink) before calling this
1655 : * function (or else why call it?)
1656 : *
1657 : * Note: for HTML this gets the value of the 'target' attribute; for XLink
1658 : * this gets the value of the xlink:_moz_target attribute, or failing that,
1659 : * the value of xlink:show, converted to a suitably equivalent named target
1660 : * (e.g. _blank).
1661 : */
1662 : virtual void GetLinkTarget(nsAString& aTarget);
1663 :
1664 : nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
1665 : const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
1666 :
1667 : nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
1668 : RegisteredIntersectionObservers();
1669 :
1670 : private:
1671 : /**
1672 : * Hook for implementing GetClasses. This is guaranteed to only be
1673 : * called if the NODE_MAY_HAVE_CLASS flag is set.
1674 : */
1675 : const nsAttrValue* DoGetClasses() const;
1676 :
1677 : /**
1678 : * Get this element's client area rect in app units.
1679 : * @return the frame's client area
1680 : */
1681 : nsRect GetClientAreaRect();
1682 :
1683 : nsIScrollableFrame* GetScrollFrame(nsIFrame **aStyledFrame = nullptr,
1684 : FlushType aFlushType = FlushType::Layout);
1685 :
1686 : // Data members
1687 : EventStates mState;
1688 : // Per-node data managed by Servo.
1689 : mozilla::ServoCell<ServoNodeData*> mServoData;
1690 : };
1691 :
1692 : class RemoveFromBindingManagerRunnable : public mozilla::Runnable
1693 : {
1694 : public:
1695 : RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
1696 : nsIContent* aContent,
1697 : nsIDocument* aDoc);
1698 :
1699 : NS_IMETHOD Run() override;
1700 : private:
1701 : virtual ~RemoveFromBindingManagerRunnable();
1702 : RefPtr<nsBindingManager> mManager;
1703 : RefPtr<nsIContent> mContent;
1704 : nsCOMPtr<nsIDocument> mDoc;
1705 : };
1706 :
1707 : class DestinationInsertionPointList : public nsINodeList
1708 : {
1709 : public:
1710 : explicit DestinationInsertionPointList(Element* aElement);
1711 :
1712 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
1713 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DestinationInsertionPointList)
1714 :
1715 : // nsIDOMNodeList
1716 : NS_DECL_NSIDOMNODELIST
1717 :
1718 : // nsINodeList
1719 : virtual nsIContent* Item(uint32_t aIndex) override;
1720 : virtual int32_t IndexOf(nsIContent* aContent) override;
1721 0 : virtual nsINode* GetParentObject() override { return mParent; }
1722 : virtual uint32_t Length() const;
1723 : virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
1724 : protected:
1725 : virtual ~DestinationInsertionPointList();
1726 :
1727 : RefPtr<Element> mParent;
1728 : nsCOMArray<nsIContent> mDestinationPoints;
1729 : };
1730 :
1731 : NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
1732 :
1733 : inline bool
1734 19670 : Element::HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const
1735 : {
1736 19670 : NS_ASSERTION(nullptr != aName, "must have attribute name");
1737 19670 : NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown,
1738 : "must have a real namespace ID!");
1739 :
1740 19670 : return mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID) >= 0;
1741 : }
1742 :
1743 : inline bool
1744 42685 : Element::AttrValueIs(int32_t aNameSpaceID,
1745 : nsIAtom* aName,
1746 : const nsAString& aValue,
1747 : nsCaseTreatment aCaseSensitive) const
1748 : {
1749 42685 : NS_ASSERTION(aName, "Must have attr name");
1750 42685 : NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
1751 :
1752 42685 : const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
1753 42685 : return val && val->Equals(aValue, aCaseSensitive);
1754 : }
1755 :
1756 : inline bool
1757 3375 : Element::AttrValueIs(int32_t aNameSpaceID,
1758 : nsIAtom* aName,
1759 : nsIAtom* aValue,
1760 : nsCaseTreatment aCaseSensitive) const
1761 : {
1762 3375 : NS_ASSERTION(aName, "Must have attr name");
1763 3375 : NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
1764 3375 : NS_ASSERTION(aValue, "Null value atom");
1765 :
1766 3375 : const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
1767 3375 : return val && val->Equals(aValue, aCaseSensitive);
1768 : }
1769 :
1770 : } // namespace dom
1771 : } // namespace mozilla
1772 :
1773 863300 : inline mozilla::dom::Element* nsINode::AsElement()
1774 : {
1775 863300 : MOZ_ASSERT(IsElement());
1776 863300 : return static_cast<mozilla::dom::Element*>(this);
1777 : }
1778 :
1779 111484 : inline const mozilla::dom::Element* nsINode::AsElement() const
1780 : {
1781 111484 : MOZ_ASSERT(IsElement());
1782 111484 : return static_cast<const mozilla::dom::Element*>(this);
1783 : }
1784 :
1785 3759 : inline void nsINode::UnsetRestyleFlagsIfGecko()
1786 : {
1787 3759 : if (IsElement() && !AsElement()->IsStyledByServo()) {
1788 3644 : UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
1789 : }
1790 3759 : }
1791 :
1792 : /**
1793 : * Macros to implement Clone(). _elementName is the class for which to implement
1794 : * Clone.
1795 : */
1796 : #define NS_IMPL_ELEMENT_CLONE(_elementName) \
1797 : nsresult \
1798 : _elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult, \
1799 : bool aPreallocateChildren) const \
1800 : { \
1801 : *aResult = nullptr; \
1802 : already_AddRefed<mozilla::dom::NodeInfo> ni = \
1803 : RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget(); \
1804 : _elementName *it = new _elementName(ni); \
1805 : if (!it) { \
1806 : return NS_ERROR_OUT_OF_MEMORY; \
1807 : } \
1808 : \
1809 : nsCOMPtr<nsINode> kungFuDeathGrip = it; \
1810 : nsresult rv = const_cast<_elementName*>(this)->CopyInnerTo(it, aPreallocateChildren); \
1811 : if (NS_SUCCEEDED(rv)) { \
1812 : kungFuDeathGrip.swap(*aResult); \
1813 : } \
1814 : \
1815 : return rv; \
1816 : }
1817 :
1818 : #define EXPAND(...) __VA_ARGS__
1819 : #define NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, extra_args_) \
1820 : nsresult \
1821 : _elementName::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult, \
1822 : bool aPreallocateChildren) const \
1823 : { \
1824 : *aResult = nullptr; \
1825 : already_AddRefed<mozilla::dom::NodeInfo> ni = \
1826 : RefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget(); \
1827 : _elementName *it = new _elementName(ni EXPAND extra_args_); \
1828 : if (!it) { \
1829 : return NS_ERROR_OUT_OF_MEMORY; \
1830 : } \
1831 : \
1832 : nsCOMPtr<nsINode> kungFuDeathGrip = it; \
1833 : nsresult rv = it->Init(); \
1834 : nsresult rv2 = const_cast<_elementName*>(this)->CopyInnerTo(it, aPreallocateChildren); \
1835 : if (NS_FAILED(rv2)) { \
1836 : rv = rv2; \
1837 : } \
1838 : if (NS_SUCCEEDED(rv)) { \
1839 : kungFuDeathGrip.swap(*aResult); \
1840 : } \
1841 : \
1842 : return rv; \
1843 : }
1844 :
1845 : #define NS_IMPL_ELEMENT_CLONE_WITH_INIT(_elementName) \
1846 : NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, ())
1847 : #define NS_IMPL_ELEMENT_CLONE_WITH_INIT_AND_PARSER(_elementName) \
1848 : NS_IMPL_ELEMENT_CLONE_WITH_INIT_HELPER(_elementName, (, NOT_FROM_PARSER))
1849 :
1850 : /**
1851 : * A macro to implement the getter and setter for a given string
1852 : * valued content property. The method uses the generic GetAttr and
1853 : * SetAttr methods. We use the 5-argument form of SetAttr, because
1854 : * some consumers only implement that one, hiding superclass
1855 : * 4-argument forms.
1856 : */
1857 : #define NS_IMPL_STRING_ATTR(_class, _method, _atom) \
1858 : NS_IMETHODIMP \
1859 : _class::Get##_method(nsAString& aValue) \
1860 : { \
1861 : GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue); \
1862 : return NS_OK; \
1863 : } \
1864 : NS_IMETHODIMP \
1865 : _class::Set##_method(const nsAString& aValue) \
1866 : { \
1867 : return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, nullptr, aValue, true); \
1868 : }
1869 :
1870 : /**
1871 : * A macro to implement the getter and setter for a given boolean
1872 : * valued content property. The method uses the GetBoolAttr and
1873 : * SetBoolAttr methods.
1874 : */
1875 : #define NS_IMPL_BOOL_ATTR(_class, _method, _atom) \
1876 : NS_IMETHODIMP \
1877 : _class::Get##_method(bool* aValue) \
1878 : { \
1879 : *aValue = GetBoolAttr(nsGkAtoms::_atom); \
1880 : return NS_OK; \
1881 : } \
1882 : NS_IMETHODIMP \
1883 : _class::Set##_method(bool aValue) \
1884 : { \
1885 : return SetBoolAttr(nsGkAtoms::_atom, aValue); \
1886 : }
1887 :
1888 : #define NS_FORWARD_NSIDOMELEMENT_TO_GENERIC \
1889 : typedef mozilla::dom::Element Element; \
1890 : NS_IMETHOD GetTagName(nsAString& aTagName) final override \
1891 : { \
1892 : Element::GetTagName(aTagName); \
1893 : return NS_OK; \
1894 : } \
1895 : NS_IMETHOD GetAttributes(nsIDOMMozNamedAttrMap** aAttributes) final override \
1896 : { \
1897 : NS_ADDREF(*aAttributes = Attributes()); \
1898 : return NS_OK; \
1899 : } \
1900 : using Element::GetAttribute; \
1901 : NS_IMETHOD GetAttribute(const nsAString& name, nsAString& _retval) final \
1902 : override \
1903 : { \
1904 : nsString attr; \
1905 : GetAttribute(name, attr); \
1906 : _retval = attr; \
1907 : return NS_OK; \
1908 : } \
1909 : NS_IMETHOD SetAttribute(const nsAString& name, \
1910 : const nsAString& value) override \
1911 : { \
1912 : mozilla::ErrorResult rv; \
1913 : Element::SetAttribute(name, value, rv); \
1914 : return rv.StealNSResult(); \
1915 : } \
1916 : using Element::HasAttribute; \
1917 : NS_IMETHOD HasAttribute(const nsAString& name, \
1918 : bool* _retval) final override \
1919 : { \
1920 : *_retval = HasAttribute(name); \
1921 : return NS_OK; \
1922 : } \
1923 : NS_IMETHOD GetAttributeNode(const nsAString& name, \
1924 : nsIDOMAttr** _retval) final override \
1925 : { \
1926 : NS_IF_ADDREF(*_retval = Element::GetAttributeNode(name)); \
1927 : return NS_OK; \
1928 : } \
1929 : NS_IMETHOD GetAttributeNodeNS(const nsAString& namespaceURI, \
1930 : const nsAString& localName, \
1931 : nsIDOMAttr** _retval) final override \
1932 : { \
1933 : NS_IF_ADDREF(*_retval = Element::GetAttributeNodeNS(namespaceURI, \
1934 : localName)); \
1935 : return NS_OK; \
1936 : }
1937 : #endif // mozilla_dom_Element_h__
|