LCOV - code coverage report
Current view: top level - dom/base - Element.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 637 1857 34.3 %
Date: 2017-07-14 16:53:18 Functions: 60 183 32.8 %
Legend: Lines: hit not hit

          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             : #include "mozilla/dom/ElementInlines.h"
      14             : 
      15             : #include "AnimationCommon.h"
      16             : #include "mozilla/DebugOnly.h"
      17             : #include "mozilla/dom/Animation.h"
      18             : #include "mozilla/dom/Attr.h"
      19             : #include "mozilla/dom/Grid.h"
      20             : #include "nsDOMAttributeMap.h"
      21             : #include "nsIAtom.h"
      22             : #include "nsIContentInlines.h"
      23             : #include "mozilla/dom/NodeInfo.h"
      24             : #include "nsIDocumentInlines.h"
      25             : #include "mozilla/dom/DocumentTimeline.h"
      26             : #include "nsIDOMNodeList.h"
      27             : #include "nsIDOMDocument.h"
      28             : #include "nsIContentIterator.h"
      29             : #include "nsFocusManager.h"
      30             : #include "nsFrameManager.h"
      31             : #include "nsILinkHandler.h"
      32             : #include "nsIScriptGlobalObject.h"
      33             : #include "nsIURL.h"
      34             : #include "nsContainerFrame.h"
      35             : #include "nsIAnonymousContentCreator.h"
      36             : #include "nsIPresShell.h"
      37             : #include "nsPresContext.h"
      38             : #include "nsStyleConsts.h"
      39             : #include "nsString.h"
      40             : #include "nsUnicharUtils.h"
      41             : #include "nsIDOMEvent.h"
      42             : #include "nsDOMCID.h"
      43             : #include "nsIServiceManager.h"
      44             : #include "nsIDOMCSSStyleDeclaration.h"
      45             : #include "nsDOMCSSAttrDeclaration.h"
      46             : #include "nsNameSpaceManager.h"
      47             : #include "nsContentList.h"
      48             : #include "nsVariant.h"
      49             : #include "nsDOMTokenList.h"
      50             : #include "nsXBLPrototypeBinding.h"
      51             : #include "nsError.h"
      52             : #include "nsDOMString.h"
      53             : #include "nsIScriptSecurityManager.h"
      54             : #include "nsIDOMMutationEvent.h"
      55             : #include "mozilla/dom/AnimatableBinding.h"
      56             : #include "mozilla/dom/HTMLDivElement.h"
      57             : #include "mozilla/dom/HTMLSpanElement.h"
      58             : #include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
      59             : #include "mozilla/AnimationComparator.h"
      60             : #include "mozilla/AsyncEventDispatcher.h"
      61             : #include "mozilla/ContentEvents.h"
      62             : #include "mozilla/DeclarationBlockInlines.h"
      63             : #include "mozilla/EffectSet.h"
      64             : #include "mozilla/EventDispatcher.h"
      65             : #include "mozilla/EventListenerManager.h"
      66             : #include "mozilla/EventStateManager.h"
      67             : #include "mozilla/EventStates.h"
      68             : #include "mozilla/InternalMutationEvent.h"
      69             : #include "mozilla/MouseEvents.h"
      70             : #include "mozilla/TextEditor.h"
      71             : #include "mozilla/TextEvents.h"
      72             : #include "nsNodeUtils.h"
      73             : #include "mozilla/dom/DirectionalityUtils.h"
      74             : #include "nsDocument.h"
      75             : #include "nsAttrValueOrString.h"
      76             : #include "nsAttrValueInlines.h"
      77             : #include "nsCSSPseudoElements.h"
      78             : #ifdef MOZ_XUL
      79             : #include "nsXULElement.h"
      80             : #endif /* MOZ_XUL */
      81             : #include "nsSVGElement.h"
      82             : #include "nsFrameSelection.h"
      83             : #ifdef DEBUG
      84             : #include "nsRange.h"
      85             : #endif
      86             : 
      87             : #include "nsBindingManager.h"
      88             : #include "nsXBLBinding.h"
      89             : #include "nsPIDOMWindow.h"
      90             : #include "nsPIBoxObject.h"
      91             : #include "mozilla/dom/DOMRect.h"
      92             : #include "nsSVGUtils.h"
      93             : #include "nsLayoutUtils.h"
      94             : #include "nsGkAtoms.h"
      95             : #include "nsContentUtils.h"
      96             : #include "ChildIterator.h"
      97             : 
      98             : #include "nsIDOMEventListener.h"
      99             : #include "nsIWebNavigation.h"
     100             : #include "nsIBaseWindow.h"
     101             : #include "nsIWidget.h"
     102             : 
     103             : #include "nsNodeInfoManager.h"
     104             : #include "nsICategoryManager.h"
     105             : #include "nsIDOMDocumentType.h"
     106             : #include "nsGenericHTMLElement.h"
     107             : #include "nsContentCreatorFunctions.h"
     108             : #include "nsIControllers.h"
     109             : #include "nsView.h"
     110             : #include "nsViewManager.h"
     111             : #include "nsIScrollableFrame.h"
     112             : #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
     113             : #include "nsCSSRuleProcessor.h"
     114             : #include "nsRuleProcessorData.h"
     115             : #include "nsTextNode.h"
     116             : 
     117             : #ifdef MOZ_XUL
     118             : #include "nsIXULDocument.h"
     119             : #endif /* MOZ_XUL */
     120             : 
     121             : #include "nsCycleCollectionParticipant.h"
     122             : #include "nsCCUncollectableMarker.h"
     123             : 
     124             : #include "mozAutoDocUpdate.h"
     125             : 
     126             : #include "nsCSSParser.h"
     127             : #include "nsDOMMutationObserver.h"
     128             : #include "nsWrapperCacheInlines.h"
     129             : #include "xpcpublic.h"
     130             : #include "nsIScriptError.h"
     131             : #include "mozilla/Telemetry.h"
     132             : 
     133             : #include "mozilla/CORSMode.h"
     134             : #include "mozilla/dom/ShadowRoot.h"
     135             : #include "mozilla/dom/NodeListBinding.h"
     136             : 
     137             : #include "nsStyledElement.h"
     138             : #include "nsXBLService.h"
     139             : #include "nsITextControlElement.h"
     140             : #include "nsITextControlFrame.h"
     141             : #include "nsISupportsImpl.h"
     142             : #include "mozilla/dom/CSSPseudoElement.h"
     143             : #include "mozilla/dom/DocumentFragment.h"
     144             : #include "mozilla/dom/KeyframeEffect.h"
     145             : #include "mozilla/dom/KeyframeEffectBinding.h"
     146             : #include "mozilla/dom/WindowBinding.h"
     147             : #include "mozilla/dom/ElementBinding.h"
     148             : #include "mozilla/dom/VRDisplay.h"
     149             : #include "mozilla/IntegerPrintfMacros.h"
     150             : #include "mozilla/Preferences.h"
     151             : #include "nsComputedDOMStyle.h"
     152             : #include "nsDOMStringMap.h"
     153             : #include "DOMIntersectionObserver.h"
     154             : 
     155             : #include "nsISpeculativeConnect.h"
     156             : 
     157             : #include "DOMMatrix.h"
     158             : 
     159             : using namespace mozilla;
     160             : using namespace mozilla::dom;
     161             : 
     162             : //
     163             : // Verify sizes of elements on 64-bit platforms. This should catch most memory
     164             : // regressions, and is easy to verify locally since most developers are on
     165             : // 64-bit machines. We use a template rather than a direct static assert so
     166             : // that the error message actually displays the sizes.
     167             : //
     168             : 
     169             : // We need different numbers on certain build types to deal with the owning
     170             : // thread pointer that comes with the non-threadsafe refcount on
     171             : // FragmentOrElement.
     172             : #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
     173             : #define EXTRA_DOM_ELEMENT_BYTES 8
     174             : #else
     175             : #define EXTRA_DOM_ELEMENT_BYTES 0
     176             : #endif
     177             : 
     178             : #define ASSERT_ELEMENT_SIZE(type, opt_size) \
     179             : template<int a, int b> struct Check##type##Size \
     180             : { \
     181             :   static_assert(sizeof(void*) != 8 || a == b, "DOM size changed"); \
     182             : }; \
     183             : Check##type##Size<sizeof(type), opt_size + EXTRA_DOM_ELEMENT_BYTES> g##type##CES;
     184             : 
     185             : // Note that mozjemalloc uses a 16 byte quantum, so 128 is a bin/bucket size.
     186             : ASSERT_ELEMENT_SIZE(Element, 120);
     187             : ASSERT_ELEMENT_SIZE(HTMLDivElement, 128);
     188             : ASSERT_ELEMENT_SIZE(HTMLSpanElement, 128);
     189             : 
     190             : #undef ASSERT_ELEMENT_SIZE
     191             : #undef EXTRA_DOM_ELEMENT_BYTES
     192             : 
     193             : nsIAtom*
     194       75000 : nsIContent::DoGetID() const
     195             : {
     196       75000 :   MOZ_ASSERT(HasID(), "Unexpected call");
     197       75000 :   MOZ_ASSERT(IsElement(), "Only elements can have IDs");
     198             : 
     199       75000 :   return AsElement()->GetParsedAttr(nsGkAtoms::id)->GetAtomValue();
     200             : }
     201             : 
     202             : const nsAttrValue*
     203       18576 : Element::DoGetClasses() const
     204             : {
     205       18576 :   MOZ_ASSERT(MayHaveClass(), "Unexpected call");
     206       18576 :   if (IsSVGElement()) {
     207             :     const nsAttrValue* animClass =
     208         112 :       static_cast<const nsSVGElement*>(this)->GetAnimatedClassName();
     209         112 :     if (animClass) {
     210           0 :       return animClass;
     211             :     }
     212             :   }
     213             : 
     214       18576 :   return GetParsedAttr(nsGkAtoms::_class);
     215             : }
     216             : 
     217             : NS_IMETHODIMP
     218        4495 : Element::QueryInterface(REFNSIID aIID, void** aInstancePtr)
     219             : {
     220        4495 :   NS_ASSERTION(aInstancePtr,
     221             :                "QueryInterface requires a non-NULL destination!");
     222        4495 :   nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr);
     223        4495 :   if (NS_SUCCEEDED(rv)) {
     224        4285 :     return NS_OK;
     225             :   }
     226             : 
     227             :   // Give the binding manager a chance to get an interface for this element.
     228         210 :   return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
     229         210 :                                                                 aInstancePtr);
     230             : }
     231             : 
     232             : EventStates
     233        5711 : Element::IntrinsicState() const
     234             : {
     235        5711 :   return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
     236        5711 :                         NS_EVENT_STATE_MOZ_READONLY;
     237             : }
     238             : 
     239             : void
     240          45 : Element::NotifyStateChange(EventStates aStates)
     241             : {
     242          45 :   nsIDocument* doc = GetComposedDoc();
     243          45 :   if (doc) {
     244          90 :     nsAutoScriptBlocker scriptBlocker;
     245          45 :     doc->ContentStateChanged(this, aStates);
     246             :   }
     247          45 : }
     248             : 
     249             : void
     250           0 : Element::UpdateLinkState(EventStates aState)
     251             : {
     252           0 :   MOZ_ASSERT(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
     253             :                                              NS_EVENT_STATE_UNVISITED)),
     254             :              "Unexpected link state bits");
     255             :   mState =
     256           0 :     (mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
     257           0 :     aState;
     258           0 : }
     259             : 
     260             : void
     261        5711 : Element::UpdateState(bool aNotify)
     262             : {
     263        5711 :   EventStates oldState = mState;
     264        5711 :   mState = IntrinsicState() | (oldState & EXTERNALLY_MANAGED_STATES);
     265        5711 :   if (aNotify) {
     266         616 :     EventStates changedStates = oldState ^ mState;
     267         616 :     if (!changedStates.IsEmpty()) {
     268          10 :       nsIDocument* doc = GetComposedDoc();
     269          10 :       if (doc) {
     270          20 :         nsAutoScriptBlocker scriptBlocker;
     271          10 :         doc->ContentStateChanged(this, changedStates);
     272             :       }
     273             :     }
     274             :   }
     275        5711 : }
     276             : 
     277             : void
     278         567 : nsIContent::UpdateEditableState(bool aNotify)
     279             : {
     280             :   // Guaranteed to be non-element content
     281         567 :   NS_ASSERTION(!IsElement(), "What happened here?");
     282         567 :   nsIContent *parent = GetParent();
     283             : 
     284             :   // Skip over unknown native anonymous content to avoid setting a flag we
     285             :   // can't clear later
     286         567 :   bool isUnknownNativeAnon = false;
     287         567 :   if (IsInNativeAnonymousSubtree()) {
     288          15 :     isUnknownNativeAnon = true;
     289          30 :     nsCOMPtr<nsIContent> root = this;
     290          45 :     while (root && !root->IsRootOfNativeAnonymousSubtree()) {
     291          15 :       root = root->GetParent();
     292             :     }
     293             :     // root should always be true here, but isn't -- bug 999416
     294          15 :     if (root) {
     295          15 :       nsIFrame* rootFrame = root->GetPrimaryFrame();
     296          15 :       if (rootFrame) {
     297           1 :         nsContainerFrame* parentFrame = rootFrame->GetParent();
     298           1 :         nsITextControlFrame* textCtrl = do_QueryFrame(parentFrame);
     299           1 :         isUnknownNativeAnon = !textCtrl;
     300             :       }
     301             :     }
     302             :   }
     303             : 
     304         572 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE) &&
     305         572 :                   !isUnknownNativeAnon);
     306         567 : }
     307             : 
     308             : void
     309        1062 : Element::UpdateEditableState(bool aNotify)
     310             : {
     311        1062 :   nsIContent *parent = GetParent();
     312             : 
     313        1062 :   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
     314        1062 :   if (aNotify) {
     315           0 :     UpdateState(aNotify);
     316             :   } else {
     317             :     // Avoid calling UpdateState in this very common case, because
     318             :     // this gets called for pretty much every single element on
     319             :     // insertion into the document and UpdateState can be slow for
     320             :     // some kinds of elements even when not notifying.
     321        1062 :     if (IsEditable()) {
     322           2 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
     323           2 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
     324             :     } else {
     325        1060 :       RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
     326        1060 :       AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
     327             :     }
     328             :   }
     329        1062 : }
     330             : 
     331             : int32_t
     332           0 : Element::TabIndex()
     333             : {
     334           0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::tabindex);
     335           0 :   if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
     336           0 :     return attrVal->GetIntegerValue();
     337             :   }
     338             : 
     339           0 :   return TabIndexDefault();
     340             : }
     341             : 
     342             : void
     343           2 : Element::Focus(mozilla::ErrorResult& aError)
     344             : {
     345           4 :   nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
     346           2 :   nsFocusManager* fm = nsFocusManager::GetFocusManager();
     347             :   // Also other browsers seem to have the hack to not re-focus (and flush) when
     348             :   // the element is already focused.
     349           2 :   if (fm && domElement) {
     350           2 :     if (fm->CanSkipFocus(this)) {
     351           0 :       fm->NeedsFlushBeforeEventHandling(this);
     352             :     } else {
     353           2 :       aError = fm->SetFocus(domElement, 0);
     354             :     }
     355             :   }
     356           2 : }
     357             : 
     358             : void
     359           0 : Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError)
     360             : {
     361           0 :   nsAutoString value;
     362           0 :   value.AppendInt(aTabIndex);
     363             : 
     364           0 :   SetAttr(nsGkAtoms::tabindex, value, aError);
     365           0 : }
     366             : 
     367             : void
     368           0 : Element::Blur(mozilla::ErrorResult& aError)
     369             : {
     370           0 :   if (!ShouldBlur(this)) {
     371           0 :     return;
     372             :   }
     373             : 
     374           0 :   nsIDocument* doc = GetComposedDoc();
     375           0 :   if (!doc) {
     376           0 :     return;
     377             :   }
     378             : 
     379           0 :   nsPIDOMWindowOuter* win = doc->GetWindow();
     380           0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     381           0 :   if (win && fm) {
     382           0 :     aError = fm->ClearFocus(win);
     383             :   }
     384             : }
     385             : 
     386             : EventStates
     387           0 : Element::StyleStateFromLocks() const
     388             : {
     389           0 :   StyleStateLocks locksAndValues = LockedStyleStates();
     390           0 :   EventStates locks = locksAndValues.mLocks;
     391           0 :   EventStates values = locksAndValues.mValues;
     392           0 :   EventStates state = (mState & ~locks) | (locks & values);
     393             : 
     394           0 :   if (state.HasState(NS_EVENT_STATE_VISITED)) {
     395           0 :     return state & ~NS_EVENT_STATE_UNVISITED;
     396             :   }
     397           0 :   if (state.HasState(NS_EVENT_STATE_UNVISITED)) {
     398           0 :     return state & ~NS_EVENT_STATE_VISITED;
     399             :   }
     400             : 
     401           0 :   return state;
     402             : }
     403             : 
     404             : Element::StyleStateLocks
     405           0 : Element::LockedStyleStates() const
     406             : {
     407             :   StyleStateLocks* locks =
     408           0 :     static_cast<StyleStateLocks*>(GetProperty(nsGkAtoms::lockedStyleStates));
     409           0 :   if (locks) {
     410           0 :     return *locks;
     411             :   }
     412           0 :   return StyleStateLocks();
     413             : }
     414             : 
     415             : void
     416           0 : Element::NotifyStyleStateChange(EventStates aStates)
     417             : {
     418           0 :   nsIDocument* doc = GetComposedDoc();
     419           0 :   if (doc) {
     420           0 :     nsIPresShell *presShell = doc->GetShell();
     421           0 :     if (presShell) {
     422           0 :       nsAutoScriptBlocker scriptBlocker;
     423           0 :       presShell->ContentStateChanged(doc, this, aStates);
     424             :     }
     425             :   }
     426           0 : }
     427             : 
     428             : void
     429           0 : Element::LockStyleStates(EventStates aStates, bool aEnabled)
     430             : {
     431           0 :   StyleStateLocks* locks = new StyleStateLocks(LockedStyleStates());
     432             : 
     433           0 :   locks->mLocks |= aStates;
     434           0 :   if (aEnabled) {
     435           0 :     locks->mValues |= aStates;
     436             :   } else {
     437           0 :     locks->mValues &= ~aStates;
     438             :   }
     439             : 
     440           0 :   if (aStates.HasState(NS_EVENT_STATE_VISITED)) {
     441           0 :     locks->mLocks &= ~NS_EVENT_STATE_UNVISITED;
     442             :   }
     443           0 :   if (aStates.HasState(NS_EVENT_STATE_UNVISITED)) {
     444           0 :     locks->mLocks &= ~NS_EVENT_STATE_VISITED;
     445             :   }
     446             : 
     447           0 :   SetProperty(nsGkAtoms::lockedStyleStates, locks,
     448           0 :               nsINode::DeleteProperty<StyleStateLocks>);
     449           0 :   SetHasLockedStyleStates();
     450             : 
     451           0 :   NotifyStyleStateChange(aStates);
     452           0 : }
     453             : 
     454             : void
     455           0 : Element::UnlockStyleStates(EventStates aStates)
     456             : {
     457           0 :   StyleStateLocks* locks = new StyleStateLocks(LockedStyleStates());
     458             : 
     459           0 :   locks->mLocks &= ~aStates;
     460             : 
     461           0 :   if (locks->mLocks.IsEmpty()) {
     462           0 :     DeleteProperty(nsGkAtoms::lockedStyleStates);
     463           0 :     ClearHasLockedStyleStates();
     464             :     delete locks;
     465             :   }
     466             :   else {
     467           0 :     SetProperty(nsGkAtoms::lockedStyleStates, locks,
     468           0 :                 nsINode::DeleteProperty<StyleStateLocks>);
     469             :   }
     470             : 
     471           0 :   NotifyStyleStateChange(aStates);
     472           0 : }
     473             : 
     474             : void
     475           0 : Element::ClearStyleStateLocks()
     476             : {
     477           0 :   StyleStateLocks locks = LockedStyleStates();
     478             : 
     479           0 :   DeleteProperty(nsGkAtoms::lockedStyleStates);
     480           0 :   ClearHasLockedStyleStates();
     481             : 
     482           0 :   NotifyStyleStateChange(locks.mLocks);
     483           0 : }
     484             : 
     485             : bool
     486         133 : Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
     487             : {
     488             :   // If we have a frame the frame has already loaded the binding.  And
     489             :   // otherwise, don't do anything else here unless we're dealing with
     490             :   // XUL or an HTML element that may have a plugin-related overlay
     491             :   // (i.e. object, embed, or applet).
     492         142 :   bool isXULorPluginElement = (IsXULElement() ||
     493          18 :                                IsHTMLElement(nsGkAtoms::object) ||
     494         151 :                                IsHTMLElement(nsGkAtoms::embed) ||
     495         142 :                                IsHTMLElement(nsGkAtoms::applet));
     496         266 :   nsCOMPtr<nsIPresShell> shell = aDocument->GetShell();
     497         133 :   if (!shell || GetPrimaryFrame() || !isXULorPluginElement) {
     498          36 :     *aResult = nullptr;
     499          36 :     return true;
     500             :   }
     501             : 
     502             :   // Get the computed -moz-binding directly from the style context
     503             :   RefPtr<nsStyleContext> sc =
     504         194 :     nsComputedDOMStyle::GetStyleContextNoFlush(this, nullptr, shell);
     505          97 :   NS_ENSURE_TRUE(sc, false);
     506             : 
     507          97 :   NS_IF_ADDREF(*aResult = sc->StyleDisplay()->mBinding);
     508          97 :   return true;
     509             : }
     510             : 
     511             : JSObject*
     512         395 : Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
     513             : {
     514         790 :   JS::Rooted<JSObject*> givenProto(aCx, aGivenProto);
     515         790 :   JS::Rooted<JSObject*> customProto(aCx);
     516             : 
     517         395 :   if (!givenProto) {
     518             :     // Custom element prototype swizzling.
     519         395 :     CustomElementData* data = GetCustomElementData();
     520         395 :     if (data) {
     521             :       // If this is a registered custom element then fix the prototype.
     522           0 :       nsContentUtils::GetCustomPrototype(OwnerDoc(), NodeInfo()->NamespaceID(),
     523           0 :                                          data->mType, &customProto);
     524           0 :       if (customProto &&
     525           0 :           NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(customProto))) {
     526             :         // Just go ahead and create with the right proto up front.  Set
     527             :         // customProto to null to flag that we don't need to do any post-facto
     528             :         // proto fixups here.
     529           0 :         givenProto = customProto;
     530           0 :         customProto = nullptr;
     531             :       }
     532             :     }
     533             :   }
     534             : 
     535         790 :   JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, givenProto));
     536         395 :   if (!obj) {
     537           0 :     return nullptr;
     538             :   }
     539             : 
     540         395 :   if (customProto) {
     541             :     // We want to set the custom prototype in the compartment where it was
     542             :     // registered. In the case that |obj| and |prototype| are in different
     543             :     // compartments, this will set the prototype on the |obj|'s wrapper and
     544             :     // thus only visible in the wrapper's compartment, since we know obj's
     545             :     // principal does not subsume customProto's in this case.
     546           0 :     JSAutoCompartment ac(aCx, customProto);
     547           0 :     JS::Rooted<JSObject*> wrappedObj(aCx, obj);
     548           0 :     if (!JS_WrapObject(aCx, &wrappedObj) ||
     549           0 :         !JS_SetPrototype(aCx, wrappedObj, customProto)) {
     550           0 :       return nullptr;
     551             :     }
     552             :   }
     553             : 
     554             :   nsIDocument* doc;
     555         395 :   if (HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     556           2 :     doc = OwnerDoc();
     557             :   }
     558             :   else {
     559         393 :     doc = GetComposedDoc();
     560             :   }
     561             : 
     562         395 :   if (!doc) {
     563             :     // There's no baseclass that cares about this call so we just
     564             :     // return here.
     565          57 :     return obj;
     566             :   }
     567             : 
     568             :   // We must ensure that the XBL Binding is installed before we hand
     569             :   // back this object.
     570             : 
     571         338 :   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && GetXBLBinding()) {
     572             :     // There's already a binding for this element so nothing left to
     573             :     // be done here.
     574             : 
     575             :     // In theory we could call ExecuteAttachedHandler here when it's safe to
     576             :     // run script if we also removed the binding from the PAQ queue, but that
     577             :     // seems like a scary change that would mosly just add more
     578             :     // inconsistencies.
     579         205 :     return obj;
     580             :   }
     581             : 
     582             :   // Make sure the style context goes away _before_ we load the binding
     583             :   // since that can destroy the relevant presshell.
     584             : 
     585             :   {
     586             :     // Make a scope so that ~nsRefPtr can GC before returning obj.
     587         266 :     RefPtr<css::URLValue> bindingURL;
     588         133 :     bool ok = GetBindingURL(doc, getter_AddRefs(bindingURL));
     589         133 :     if (!ok) {
     590           0 :       dom::Throw(aCx, NS_ERROR_FAILURE);
     591           0 :       return nullptr;
     592             :     }
     593             : 
     594         133 :     if (bindingURL) {
     595          68 :       nsCOMPtr<nsIURI> uri = bindingURL->GetURI();
     596          68 :       nsCOMPtr<nsIPrincipal> principal = bindingURL->mExtraData->GetPrincipal();
     597             : 
     598             :       // We have a binding that must be installed.
     599             :       bool dummy;
     600             : 
     601          34 :       nsXBLService* xblService = nsXBLService::GetInstance();
     602          34 :       if (!xblService) {
     603           0 :         dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
     604           0 :         return nullptr;
     605             :       }
     606             : 
     607          68 :       RefPtr<nsXBLBinding> binding;
     608          68 :       xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding),
     609          34 :                                &dummy);
     610             : 
     611          34 :       if (binding) {
     612          34 :         if (nsContentUtils::IsSafeToRunScript()) {
     613          34 :           binding->ExecuteAttachedHandler();
     614             :         } else {
     615           0 :           nsContentUtils::AddScriptRunner(
     616           0 :             NewRunnableMethod("nsXBLBinding::ExecuteAttachedHandler",
     617             :                               binding,
     618           0 :                               &nsXBLBinding::ExecuteAttachedHandler));
     619             :         }
     620             :       }
     621             :     }
     622             :   }
     623             : 
     624         133 :   return obj;
     625             : }
     626             : 
     627             : /* virtual */
     628             : nsINode*
     629         170 : Element::GetScopeChainParent() const
     630             : {
     631         170 :   return OwnerDoc();
     632             : }
     633             : 
     634             : nsDOMTokenList*
     635           8 : Element::ClassList()
     636             : {
     637           8 :   Element::nsDOMSlots* slots = DOMSlots();
     638             : 
     639           8 :   if (!slots->mClassList) {
     640           8 :     slots->mClassList = new nsDOMTokenList(this, nsGkAtoms::_class);
     641             :   }
     642             : 
     643           8 :   return slots->mClassList;
     644             : }
     645             : 
     646             : void
     647           0 : Element::GetAttributeNames(nsTArray<nsString>& aResult)
     648             : {
     649           0 :   uint32_t count = mAttrsAndChildren.AttrCount();
     650           0 :   for (uint32_t i = 0; i < count; ++i) {
     651           0 :     const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
     652           0 :     name->GetQualifiedName(*aResult.AppendElement());
     653             :   }
     654           0 : }
     655             : 
     656             : already_AddRefed<nsIHTMLCollection>
     657           1 : Element::GetElementsByTagName(const nsAString& aLocalName)
     658             : {
     659           1 :   return NS_GetContentList(this, kNameSpaceID_Unknown, aLocalName);
     660             : }
     661             : 
     662             : nsIFrame*
     663           0 : Element::GetStyledFrame()
     664             : {
     665           0 :   nsIFrame *frame = GetPrimaryFrame(FlushType::Layout);
     666           0 :   return frame ? nsLayoutUtils::GetStyleFrame(frame) : nullptr;
     667             : }
     668             : 
     669             : nsIScrollableFrame*
     670           2 : Element::GetScrollFrame(nsIFrame **aStyledFrame, FlushType aFlushType)
     671             : {
     672             :   // it isn't clear what to return for SVG nodes, so just return nothing
     673           2 :   if (IsSVGElement()) {
     674           0 :     if (aStyledFrame) {
     675           0 :       *aStyledFrame = nullptr;
     676             :     }
     677           0 :     return nullptr;
     678             :   }
     679             : 
     680             :   // Inline version of GetStyledFrame to use the given FlushType.
     681           2 :   nsIFrame* frame = GetPrimaryFrame(aFlushType);
     682           2 :   if (frame) {
     683           2 :     frame = nsLayoutUtils::GetStyleFrame(frame);
     684             :   }
     685             : 
     686           2 :   if (aStyledFrame) {
     687           0 :     *aStyledFrame = frame;
     688             :   }
     689           2 :   if (frame) {
     690             :     // menu frames implement GetScrollTargetFrame but we don't want
     691             :     // to use it here.  Similar for comboboxes.
     692           2 :     LayoutFrameType type = frame->Type();
     693           2 :     if (type != LayoutFrameType::Menu &&
     694             :         type != LayoutFrameType::ComboboxControl) {
     695           2 :       nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
     696           2 :       if (scrollFrame) {
     697           2 :         MOZ_ASSERT(!OwnerDoc()->IsScrollingElement(this),
     698             :                    "How can we have a scrollframe if we're the "
     699             :                    "scrollingElement for our document?");
     700           2 :         return scrollFrame;
     701             :       }
     702             :     }
     703             :   }
     704             : 
     705           0 :   nsIDocument* doc = OwnerDoc();
     706             :   // Note: This IsScrollingElement() call can flush frames, if we're the body of
     707             :   // a quirks mode document.
     708           0 :   bool isScrollingElement = OwnerDoc()->IsScrollingElement(this);
     709             :   // Now reget *aStyledFrame if the caller asked for it, because that frame
     710             :   // flush can kill it.
     711           0 :   if (aStyledFrame) {
     712           0 :     nsIFrame* frame = GetPrimaryFrame(FlushType::None);
     713           0 :     if (frame) {
     714           0 :       *aStyledFrame = nsLayoutUtils::GetStyleFrame(frame);
     715             :     } else {
     716           0 :       *aStyledFrame = nullptr;
     717             :     }
     718             :   }
     719             : 
     720           0 :   if (isScrollingElement) {
     721             :     // Our scroll info should map to the root scrollable frame if there is one.
     722           0 :     if (nsIPresShell* shell = doc->GetShell()) {
     723           0 :       return shell->GetRootScrollFrameAsScrollable();
     724             :     }
     725             :   }
     726             : 
     727           0 :   return nullptr;
     728             : }
     729             : 
     730             : void
     731           0 : Element::ScrollIntoView()
     732             : {
     733           0 :   ScrollIntoView(ScrollIntoViewOptions());
     734           0 : }
     735             : 
     736             : void
     737           0 : Element::ScrollIntoView(bool aTop)
     738             : {
     739           0 :   ScrollIntoViewOptions options;
     740           0 :   if (!aTop) {
     741           0 :     options.mBlock = ScrollLogicalPosition::End;
     742             :   }
     743           0 :   ScrollIntoView(options);
     744           0 : }
     745             : 
     746             : void
     747           0 : Element::ScrollIntoView(const ScrollIntoViewOptions &aOptions)
     748             : {
     749           0 :   nsIDocument *document = GetComposedDoc();
     750           0 :   if (!document) {
     751           0 :     return;
     752             :   }
     753             : 
     754             :   // Get the presentation shell
     755           0 :   nsCOMPtr<nsIPresShell> presShell = document->GetShell();
     756           0 :   if (!presShell) {
     757           0 :     return;
     758             :   }
     759             : 
     760           0 :   int16_t vpercent = (aOptions.mBlock == ScrollLogicalPosition::Start)
     761             :                        ? nsIPresShell::SCROLL_TOP
     762           0 :                        : nsIPresShell::SCROLL_BOTTOM;
     763             : 
     764           0 :   uint32_t flags = nsIPresShell::SCROLL_OVERFLOW_HIDDEN;
     765           0 :   if (aOptions.mBehavior == ScrollBehavior::Smooth) {
     766           0 :     flags |= nsIPresShell::SCROLL_SMOOTH;
     767           0 :   } else if (aOptions.mBehavior == ScrollBehavior::Auto) {
     768           0 :     flags |= nsIPresShell::SCROLL_SMOOTH_AUTO;
     769             :   }
     770             : 
     771           0 :   presShell->ScrollContentIntoView(this,
     772             :                                    nsIPresShell::ScrollAxis(
     773             :                                      vpercent,
     774             :                                      nsIPresShell::SCROLL_ALWAYS),
     775             :                                    nsIPresShell::ScrollAxis(),
     776           0 :                                    flags);
     777             : }
     778             : 
     779             : void
     780           0 : Element::Scroll(const CSSIntPoint& aScroll, const ScrollOptions& aOptions)
     781             : {
     782           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     783           0 :   if (sf) {
     784           0 :     nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
     785           0 :     if (aOptions.mBehavior == ScrollBehavior::Smooth) {
     786           0 :       scrollMode = nsIScrollableFrame::SMOOTH_MSD;
     787           0 :     } else if (aOptions.mBehavior == ScrollBehavior::Auto) {
     788           0 :       ScrollbarStyles styles = sf->GetScrollbarStyles();
     789           0 :       if (styles.mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
     790           0 :         scrollMode = nsIScrollableFrame::SMOOTH_MSD;
     791             :       }
     792             :     }
     793             : 
     794           0 :     sf->ScrollToCSSPixels(aScroll, scrollMode);
     795             :   }
     796           0 : }
     797             : 
     798             : void
     799           0 : Element::Scroll(double aXScroll, double aYScroll)
     800             : {
     801             :   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
     802           0 :   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
     803           0 :                                          mozilla::ToZeroIfNonfinite(aYScroll));
     804             : 
     805           0 :   Scroll(scrollPos, ScrollOptions());
     806           0 : }
     807             : 
     808             : void
     809           0 : Element::Scroll(const ScrollToOptions& aOptions)
     810             : {
     811           0 :   nsIScrollableFrame *sf = GetScrollFrame();
     812           0 :   if (sf) {
     813           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
     814           0 :     if (aOptions.mLeft.WasPassed()) {
     815           0 :       scrollPos.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
     816             :     }
     817           0 :     if (aOptions.mTop.WasPassed()) {
     818           0 :       scrollPos.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
     819             :     }
     820           0 :     Scroll(scrollPos, aOptions);
     821             :   }
     822           0 : }
     823             : 
     824             : void
     825           0 : Element::ScrollTo(double aXScroll, double aYScroll)
     826             : {
     827           0 :   Scroll(aXScroll, aYScroll);
     828           0 : }
     829             : 
     830             : void
     831           0 : Element::ScrollTo(const ScrollToOptions& aOptions)
     832             : {
     833           0 :   Scroll(aOptions);
     834           0 : }
     835             : 
     836             : void
     837           0 : Element::ScrollBy(double aXScrollDif, double aYScrollDif)
     838             : {
     839           0 :   nsIScrollableFrame *sf = GetScrollFrame();
     840           0 :   if (sf) {
     841           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
     842           0 :     scrollPos += CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScrollDif),
     843           0 :                                        mozilla::ToZeroIfNonfinite(aYScrollDif));
     844           0 :     Scroll(scrollPos, ScrollOptions());
     845             :   }
     846           0 : }
     847             : 
     848             : void
     849           0 : Element::ScrollBy(const ScrollToOptions& aOptions)
     850             : {
     851           0 :   nsIScrollableFrame *sf = GetScrollFrame();
     852           0 :   if (sf) {
     853           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
     854           0 :     if (aOptions.mLeft.WasPassed()) {
     855           0 :       scrollPos.x += mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
     856             :     }
     857           0 :     if (aOptions.mTop.WasPassed()) {
     858           0 :       scrollPos.y += mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
     859             :     }
     860           0 :     Scroll(scrollPos, aOptions);
     861             :   }
     862           0 : }
     863             : 
     864             : int32_t
     865           0 : Element::ScrollTop()
     866             : {
     867           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     868           0 :   return sf ? sf->GetScrollPositionCSSPixels().y : 0;
     869             : }
     870             : 
     871             : void
     872           0 : Element::SetScrollTop(int32_t aScrollTop)
     873             : {
     874             :   // When aScrollTop is 0, we don't need to flush layout to scroll to that
     875             :   // point; we know 0 is always in range.  At least we think so...  But we do
     876             :   // need to flush frames so we ensure we find the right scrollable frame if
     877             :   // there is one.
     878             :   //
     879             :   // If aScrollTop is nonzero, we need to flush layout because we need to figure
     880             :   // out what our real scrollTopMax is.
     881           0 :   FlushType flushType = aScrollTop == 0 ? FlushType::Frames : FlushType::Layout;
     882           0 :   nsIScrollableFrame* sf = GetScrollFrame(nullptr, flushType);
     883           0 :   if (sf) {
     884           0 :     nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
     885           0 :     if (sf->GetScrollbarStyles().mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
     886           0 :       scrollMode = nsIScrollableFrame::SMOOTH_MSD;
     887             :     }
     888           0 :     sf->ScrollToCSSPixels(CSSIntPoint(sf->GetScrollPositionCSSPixels().x,
     889             :                                       aScrollTop),
     890           0 :                           scrollMode);
     891             :   }
     892           0 : }
     893             : 
     894             : int32_t
     895           0 : Element::ScrollLeft()
     896             : {
     897           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     898           0 :   return sf ? sf->GetScrollPositionCSSPixels().x : 0;
     899             : }
     900             : 
     901             : void
     902           0 : Element::SetScrollLeft(int32_t aScrollLeft)
     903             : {
     904             :   // We can't assume things here based on the value of aScrollLeft, because
     905             :   // depending on our direction and layout 0 may or may not be in our scroll
     906             :   // range.  So we need to flush layout no matter what.
     907           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     908           0 :   if (sf) {
     909           0 :     nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
     910           0 :     if (sf->GetScrollbarStyles().mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
     911           0 :       scrollMode = nsIScrollableFrame::SMOOTH_MSD;
     912             :     }
     913             : 
     914           0 :     sf->ScrollToCSSPixels(CSSIntPoint(aScrollLeft,
     915           0 :                                       sf->GetScrollPositionCSSPixels().y),
     916           0 :                           scrollMode);
     917             :   }
     918           0 : }
     919             : 
     920             : 
     921             : bool
     922           0 : Element::ScrollByNoFlush(int32_t aDx, int32_t aDy)
     923             : {
     924           0 :   nsIScrollableFrame* sf = GetScrollFrame(nullptr, FlushType::None);
     925           0 :   if (!sf) {
     926           0 :     return false;
     927             :   }
     928             : 
     929           0 :   AutoWeakFrame weakRef(sf->GetScrolledFrame());
     930             : 
     931           0 :   CSSIntPoint before = sf->GetScrollPositionCSSPixels();
     932           0 :   sf->ScrollToCSSPixelsApproximate(CSSIntPoint(before.x + aDx, before.y + aDy));
     933             : 
     934             :   // The frame was destroyed, can't keep on scrolling.
     935           0 :   if (!weakRef.IsAlive()) {
     936           0 :     return false;
     937             :   }
     938             : 
     939           0 :   CSSIntPoint after = sf->GetScrollPositionCSSPixels();
     940           0 :   return (before != after);
     941             : }
     942             : 
     943             : void
     944           0 : Element::MozScrollSnap()
     945             : {
     946           0 :   nsIScrollableFrame* sf = GetScrollFrame(nullptr, FlushType::None);
     947           0 :   if (sf) {
     948           0 :     sf->ScrollSnap();
     949             :   }
     950           0 : }
     951             : 
     952           0 : static nsSize GetScrollRectSizeForOverflowVisibleFrame(nsIFrame* aFrame)
     953             : {
     954           0 :   if (!aFrame) {
     955           0 :     return nsSize(0,0);
     956             :   }
     957             : 
     958           0 :   nsRect paddingRect = aFrame->GetPaddingRectRelativeToSelf();
     959           0 :   nsOverflowAreas overflowAreas(paddingRect, paddingRect);
     960             :   // Add the scrollable overflow areas of children (if any) to the paddingRect.
     961             :   // It's important to start with the paddingRect, otherwise if there are no
     962             :   // children the overflow rect will be 0,0,0,0 which will force the point 0,0
     963             :   // to be included in the final rect.
     964           0 :   nsLayoutUtils::UnionChildOverflow(aFrame, overflowAreas);
     965             :   // Make sure that an empty padding-rect's edges are included, by adding
     966             :   // the padding-rect in again with UnionEdges.
     967             :   nsRect overflowRect =
     968           0 :     overflowAreas.ScrollableOverflow().UnionEdges(paddingRect);
     969           0 :   return nsLayoutUtils::GetScrolledRect(aFrame,
     970           0 :       overflowRect, paddingRect.Size(),
     971           0 :       aFrame->StyleVisibility()->mDirection).Size();
     972             : }
     973             : 
     974             : int32_t
     975           0 : Element::ScrollHeight()
     976             : {
     977           0 :   if (IsSVGElement())
     978           0 :     return 0;
     979             : 
     980           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     981             :   nscoord height;
     982           0 :   if (sf) {
     983           0 :     height = sf->GetScrollRange().height + sf->GetScrollPortRect().height;
     984             :   } else {
     985           0 :     height = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).height;
     986             :   }
     987             : 
     988           0 :   return nsPresContext::AppUnitsToIntCSSPixels(height);
     989             : }
     990             : 
     991             : int32_t
     992           0 : Element::ScrollWidth()
     993             : {
     994           0 :   if (IsSVGElement())
     995           0 :     return 0;
     996             : 
     997           0 :   nsIScrollableFrame* sf = GetScrollFrame();
     998             :   nscoord width;
     999           0 :   if (sf) {
    1000           0 :     width = sf->GetScrollRange().width + sf->GetScrollPortRect().width;
    1001             :   } else {
    1002           0 :     width = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).width;
    1003             :   }
    1004             : 
    1005           0 :   return nsPresContext::AppUnitsToIntCSSPixels(width);
    1006             : }
    1007             : 
    1008             : nsRect
    1009           0 : Element::GetClientAreaRect()
    1010             : {
    1011             :   nsIFrame* styledFrame;
    1012           0 :   nsIScrollableFrame* sf = GetScrollFrame(&styledFrame);
    1013             : 
    1014           0 :   if (sf) {
    1015           0 :     return sf->GetScrollPortRect();
    1016             :   }
    1017             : 
    1018           0 :   if (styledFrame &&
    1019           0 :       (styledFrame->StyleDisplay()->mDisplay != StyleDisplay::Inline ||
    1020           0 :        styledFrame->IsFrameOfType(nsIFrame::eReplaced))) {
    1021             :     // Special case code to make client area work even when there isn't
    1022             :     // a scroll view, see bug 180552, bug 227567.
    1023           0 :     return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling();
    1024             :   }
    1025             : 
    1026             :   // SVG nodes reach here and just return 0
    1027           0 :   return nsRect(0, 0, 0, 0);
    1028             : }
    1029             : 
    1030             : already_AddRefed<DOMRect>
    1031           2 : Element::GetBoundingClientRect()
    1032             : {
    1033           4 :   RefPtr<DOMRect> rect = new DOMRect(this);
    1034             : 
    1035           2 :   nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
    1036           2 :   if (!frame) {
    1037             :     // display:none, perhaps? Return the empty rect
    1038           0 :     return rect.forget();
    1039             :   }
    1040             : 
    1041             :   nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
    1042             :           nsLayoutUtils::GetContainingBlockForClientRect(frame),
    1043           4 :           nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
    1044           2 :   rect->SetLayoutRect(r);
    1045           2 :   return rect.forget();
    1046             : }
    1047             : 
    1048             : already_AddRefed<DOMRectList>
    1049           0 : Element::GetClientRects()
    1050             : {
    1051           0 :   RefPtr<DOMRectList> rectList = new DOMRectList(this);
    1052             : 
    1053           0 :   nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
    1054           0 :   if (!frame) {
    1055             :     // display:none, perhaps? Return an empty list
    1056           0 :     return rectList.forget();
    1057             :   }
    1058             : 
    1059           0 :   nsLayoutUtils::RectListBuilder builder(rectList);
    1060           0 :   nsLayoutUtils::GetAllInFlowRects(frame,
    1061             :           nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder,
    1062           0 :           nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
    1063           0 :   return rectList.forget();
    1064             : }
    1065             : 
    1066             : //----------------------------------------------------------------------
    1067             : 
    1068             : void
    1069        1343 : Element::AddToIdTable(nsIAtom* aId)
    1070             : {
    1071        1343 :   NS_ASSERTION(HasID(), "Node doesn't have an ID?");
    1072        1343 :   if (IsInShadowTree()) {
    1073           0 :     ShadowRoot* containingShadow = GetContainingShadow();
    1074           0 :     containingShadow->AddToIdTable(this, aId);
    1075             :   } else {
    1076        1343 :     nsIDocument* doc = GetUncomposedDoc();
    1077        1343 :     if (doc && (!IsInAnonymousSubtree() || doc->IsXULDocument())) {
    1078        1052 :       doc->AddToIdTable(this, aId);
    1079             :     }
    1080             :   }
    1081        1343 : }
    1082             : 
    1083             : void
    1084        1032 : Element::RemoveFromIdTable()
    1085             : {
    1086        1032 :   if (!HasID()) {
    1087         890 :     return;
    1088             :   }
    1089             : 
    1090         142 :   nsIAtom* id = DoGetID();
    1091         142 :   if (IsInShadowTree()) {
    1092           0 :     ShadowRoot* containingShadow = GetContainingShadow();
    1093             :     // Check for containingShadow because it may have
    1094             :     // been deleted during unlinking.
    1095           0 :     if (containingShadow) {
    1096           0 :       containingShadow->RemoveFromIdTable(this, id);
    1097             :     }
    1098             :   } else {
    1099         142 :     nsIDocument* doc = GetUncomposedDoc();
    1100         142 :     if (doc && (!IsInAnonymousSubtree() || doc->IsXULDocument())) {
    1101          28 :       doc->RemoveFromIdTable(this, id);
    1102             :     }
    1103             :   }
    1104             : }
    1105             : 
    1106             : already_AddRefed<ShadowRoot>
    1107           0 : Element::CreateShadowRoot(ErrorResult& aError)
    1108             : {
    1109           0 :   nsAutoScriptBlocker scriptBlocker;
    1110             : 
    1111           0 :   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
    1112           0 :   nodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo(
    1113             :     nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None,
    1114           0 :     nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
    1115             : 
    1116           0 :   RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(OwnerDoc());
    1117             : 
    1118           0 :   nsXBLPrototypeBinding* protoBinding = new nsXBLPrototypeBinding();
    1119           0 :   aError = protoBinding->Init(NS_LITERAL_CSTRING("shadowroot"),
    1120           0 :                               docInfo, nullptr, true);
    1121           0 :   if (aError.Failed()) {
    1122           0 :     delete protoBinding;
    1123           0 :     return nullptr;
    1124             :   }
    1125             : 
    1126           0 :   nsIDocument* doc = GetComposedDoc();
    1127           0 :   nsIContent* destroyedFramesFor = nullptr;
    1128           0 :   if (doc) {
    1129           0 :     nsIPresShell* shell = doc->GetShell();
    1130           0 :     if (shell) {
    1131           0 :       shell->DestroyFramesFor(this, &destroyedFramesFor);
    1132           0 :       MOZ_ASSERT(!shell->FrameManager()->GetDisplayContentsStyleFor(this));
    1133             :     }
    1134             :   }
    1135           0 :   MOZ_ASSERT(!GetPrimaryFrame());
    1136             : 
    1137             :   // Unlike for XBL, false is the default for inheriting style.
    1138           0 :   protoBinding->SetInheritsStyle(false);
    1139             : 
    1140             :   // Calling SetPrototypeBinding takes ownership of protoBinding.
    1141           0 :   docInfo->SetPrototypeBinding(NS_LITERAL_CSTRING("shadowroot"), protoBinding);
    1142             : 
    1143           0 :   RefPtr<ShadowRoot> shadowRoot = new ShadowRoot(this, nodeInfo.forget(),
    1144           0 :                                                    protoBinding);
    1145             : 
    1146           0 :   shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
    1147             : 
    1148             :   // Replace the old ShadowRoot with the new one and let the old
    1149             :   // ShadowRoot know about the younger ShadowRoot because the old
    1150             :   // ShadowRoot is projected into the younger ShadowRoot's shadow
    1151             :   // insertion point (if it exists).
    1152           0 :   ShadowRoot* olderShadow = GetShadowRoot();
    1153           0 :   SetShadowRoot(shadowRoot);
    1154           0 :   if (olderShadow) {
    1155           0 :     olderShadow->SetYoungerShadow(shadowRoot);
    1156             : 
    1157             :     // Unbind children of older shadow root because they
    1158             :     // are no longer in the composed tree.
    1159           0 :     for (nsIContent* child = olderShadow->GetFirstChild(); child;
    1160           0 :          child = child->GetNextSibling()) {
    1161           0 :       child->UnbindFromTree(true, false);
    1162             :     }
    1163             : 
    1164           0 :     olderShadow->SetIsComposedDocParticipant(false);
    1165             :   }
    1166             : 
    1167             :   // xblBinding takes ownership of docInfo.
    1168           0 :   RefPtr<nsXBLBinding> xblBinding = new nsXBLBinding(shadowRoot, protoBinding);
    1169           0 :   shadowRoot->SetAssociatedBinding(xblBinding);
    1170           0 :   xblBinding->SetBoundElement(this);
    1171             : 
    1172           0 :   SetXBLBinding(xblBinding);
    1173             : 
    1174             :   // Recreate the frame for the bound content because binding a ShadowRoot
    1175             :   // changes how things are rendered.
    1176           0 :   if (doc) {
    1177           0 :     MOZ_ASSERT(doc == GetComposedDoc());
    1178           0 :     nsIPresShell* shell = doc->GetShell();
    1179           0 :     if (shell) {
    1180           0 :       shell->CreateFramesFor(destroyedFramesFor);
    1181             :     }
    1182             :   }
    1183             : 
    1184           0 :   return shadowRoot.forget();
    1185             : }
    1186             : 
    1187           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DestinationInsertionPointList, mParent,
    1188             :                                       mDestinationPoints)
    1189             : 
    1190           0 : NS_INTERFACE_TABLE_HEAD(DestinationInsertionPointList)
    1191           0 :   NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
    1192           0 :   NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList, nsIDOMNodeList)
    1193           0 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DestinationInsertionPointList)
    1194           0 : NS_INTERFACE_MAP_END
    1195             : 
    1196           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DestinationInsertionPointList)
    1197           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DestinationInsertionPointList)
    1198             : 
    1199           0 : DestinationInsertionPointList::DestinationInsertionPointList(Element* aElement)
    1200           0 :   : mParent(aElement)
    1201             : {
    1202           0 :   nsTArray<nsIContent*>* destPoints = aElement->GetExistingDestInsertionPoints();
    1203           0 :   if (destPoints) {
    1204           0 :     for (uint32_t i = 0; i < destPoints->Length(); i++) {
    1205           0 :       mDestinationPoints.AppendElement(destPoints->ElementAt(i));
    1206             :     }
    1207             :   }
    1208           0 : }
    1209             : 
    1210           0 : DestinationInsertionPointList::~DestinationInsertionPointList()
    1211             : {
    1212           0 : }
    1213             : 
    1214             : nsIContent*
    1215           0 : DestinationInsertionPointList::Item(uint32_t aIndex)
    1216             : {
    1217           0 :   return mDestinationPoints.SafeElementAt(aIndex);
    1218             : }
    1219             : 
    1220             : NS_IMETHODIMP
    1221           0 : DestinationInsertionPointList::Item(uint32_t aIndex, nsIDOMNode** aReturn)
    1222             : {
    1223           0 :   nsIContent* item = Item(aIndex);
    1224           0 :   if (!item) {
    1225           0 :     return NS_ERROR_FAILURE;
    1226             :   }
    1227             : 
    1228           0 :   return CallQueryInterface(item, aReturn);
    1229             : }
    1230             : 
    1231             : uint32_t
    1232           0 : DestinationInsertionPointList::Length() const
    1233             : {
    1234           0 :   return mDestinationPoints.Length();
    1235             : }
    1236             : 
    1237             : NS_IMETHODIMP
    1238           0 : DestinationInsertionPointList::GetLength(uint32_t* aLength)
    1239             : {
    1240           0 :   *aLength = Length();
    1241           0 :   return NS_OK;
    1242             : }
    1243             : 
    1244             : int32_t
    1245           0 : DestinationInsertionPointList::IndexOf(nsIContent* aContent)
    1246             : {
    1247           0 :   return mDestinationPoints.IndexOf(aContent);
    1248             : }
    1249             : 
    1250             : JSObject*
    1251           0 : DestinationInsertionPointList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
    1252             : {
    1253           0 :   return NodeListBinding::Wrap(aCx, this, aGivenProto);
    1254             : }
    1255             : 
    1256             : already_AddRefed<DestinationInsertionPointList>
    1257           0 : Element::GetDestinationInsertionPoints()
    1258             : {
    1259             :   RefPtr<DestinationInsertionPointList> list =
    1260           0 :     new DestinationInsertionPointList(this);
    1261           0 :   return list.forget();
    1262             : }
    1263             : 
    1264             : void
    1265         253 : Element::GetAttribute(const nsAString& aName, DOMString& aReturn)
    1266             : {
    1267             :   const nsAttrValue* val =
    1268         260 :     mAttrsAndChildren.GetAttr(aName,
    1269         260 :                               IsHTMLElement() && IsInHTMLDocument() ?
    1270         253 :                                 eIgnoreCase : eCaseMatters);
    1271         253 :   if (val) {
    1272         134 :     val->ToString(aReturn);
    1273             :   } else {
    1274         119 :     if (IsXULElement()) {
    1275             :       // XXX should be SetDOMStringToNull(aReturn);
    1276             :       // See bug 232598
    1277             :       // aReturn is already empty
    1278             :     } else {
    1279           7 :       aReturn.SetNull();
    1280             :     }
    1281             :   }
    1282         253 : }
    1283             : 
    1284             : void
    1285         366 : Element::SetAttribute(const nsAString& aName,
    1286             :                       const nsAString& aValue,
    1287             :                       ErrorResult& aError)
    1288             : {
    1289         366 :   aError = nsContentUtils::CheckQName(aName, false);
    1290         366 :   if (aError.Failed()) {
    1291           0 :     return;
    1292             :   }
    1293             : 
    1294         732 :   nsAutoString nameToUse;
    1295         366 :   const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
    1296         366 :   if (!name) {
    1297         556 :     nsCOMPtr<nsIAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
    1298         278 :     if (!nameAtom) {
    1299           0 :       aError.Throw(NS_ERROR_OUT_OF_MEMORY);
    1300           0 :       return;
    1301             :     }
    1302         278 :     aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
    1303         278 :     return;
    1304             :   }
    1305             : 
    1306          88 :   aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
    1307         176 :                    aValue, true);
    1308          88 :   return;
    1309             : }
    1310             : 
    1311             : void
    1312         101 : Element::RemoveAttribute(const nsAString& aName, ErrorResult& aError)
    1313             : {
    1314         101 :   const nsAttrName* name = InternalGetAttrNameFromQName(aName);
    1315             : 
    1316         101 :   if (!name) {
    1317             :     // If there is no canonical nsAttrName for this attribute name, then the
    1318             :     // attribute does not exist and we can't get its namespace ID and
    1319             :     // local name below, so we return early.
    1320          85 :     return;
    1321             :   }
    1322             : 
    1323             :   // Hold a strong reference here so that the atom or nodeinfo doesn't go
    1324             :   // away during UnsetAttr. If it did UnsetAttr would be left with a
    1325             :   // dangling pointer as argument without knowing it.
    1326          32 :   nsAttrName tmp(*name);
    1327             : 
    1328          16 :   aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true);
    1329             : }
    1330             : 
    1331             : Attr*
    1332           0 : Element::GetAttributeNode(const nsAString& aName)
    1333             : {
    1334           0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNode);
    1335           0 :   return Attributes()->GetNamedItem(aName);
    1336             : }
    1337             : 
    1338             : already_AddRefed<Attr>
    1339           0 : Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError)
    1340             : {
    1341             :   // XXXbz can we just remove this warning and the one in setAttributeNodeNS and
    1342             :   // alias setAttributeNode to setAttributeNodeNS?
    1343           0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
    1344             : 
    1345           0 :   return Attributes()->SetNamedItemNS(aNewAttr, aError);
    1346             : }
    1347             : 
    1348             : already_AddRefed<Attr>
    1349           0 : Element::RemoveAttributeNode(Attr& aAttribute,
    1350             :                              ErrorResult& aError)
    1351             : {
    1352           0 :   Element *elem = aAttribute.GetElement();
    1353           0 :   if (elem != this) {
    1354           0 :     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
    1355           0 :     return nullptr;
    1356             :   }
    1357             : 
    1358           0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
    1359           0 :   nsAutoString nameSpaceURI;
    1360           0 :   aAttribute.NodeInfo()->GetNamespaceURI(nameSpaceURI);
    1361           0 :   return Attributes()->RemoveNamedItemNS(nameSpaceURI, aAttribute.NodeInfo()->LocalName(), aError);
    1362             : }
    1363             : 
    1364             : void
    1365           0 : Element::GetAttributeNS(const nsAString& aNamespaceURI,
    1366             :                         const nsAString& aLocalName,
    1367             :                         nsAString& aReturn)
    1368             : {
    1369             :   int32_t nsid =
    1370           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
    1371           0 :                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
    1372             : 
    1373           0 :   if (nsid == kNameSpaceID_Unknown) {
    1374             :     // Unknown namespace means no attribute.
    1375           0 :     SetDOMStringToNull(aReturn);
    1376           0 :     return;
    1377             :   }
    1378             : 
    1379           0 :   nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
    1380           0 :   bool hasAttr = GetAttr(nsid, name, aReturn);
    1381           0 :   if (!hasAttr) {
    1382           0 :     SetDOMStringToNull(aReturn);
    1383             :   }
    1384             : }
    1385             : 
    1386             : void
    1387           0 : Element::SetAttributeNS(const nsAString& aNamespaceURI,
    1388             :                         const nsAString& aQualifiedName,
    1389             :                         const nsAString& aValue,
    1390             :                         ErrorResult& aError)
    1391             : {
    1392           0 :   RefPtr<mozilla::dom::NodeInfo> ni;
    1393           0 :   aError =
    1394             :     nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
    1395             :                                          mNodeInfo->NodeInfoManager(),
    1396             :                                          nsIDOMNode::ATTRIBUTE_NODE,
    1397           0 :                                          getter_AddRefs(ni));
    1398           0 :   if (aError.Failed()) {
    1399           0 :     return;
    1400             :   }
    1401             : 
    1402           0 :   aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
    1403           0 :                    aValue, true);
    1404             : }
    1405             : 
    1406             : void
    1407           0 : Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
    1408             :                            const nsAString& aLocalName,
    1409             :                            ErrorResult& aError)
    1410             : {
    1411           0 :   nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
    1412             :   int32_t nsid =
    1413           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
    1414           0 :                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
    1415             : 
    1416           0 :   if (nsid == kNameSpaceID_Unknown) {
    1417             :     // If the namespace ID is unknown, it means there can't possibly be an
    1418             :     // existing attribute. We would need a known namespace ID to pass into
    1419             :     // UnsetAttr, so we return early if we don't have one.
    1420           0 :     return;
    1421             :   }
    1422             : 
    1423           0 :   aError = UnsetAttr(nsid, name, true);
    1424             : }
    1425             : 
    1426             : Attr*
    1427           0 : Element::GetAttributeNodeNS(const nsAString& aNamespaceURI,
    1428             :                             const nsAString& aLocalName)
    1429             : {
    1430           0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
    1431             : 
    1432           0 :   return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName);
    1433             : }
    1434             : 
    1435             : Attr*
    1436           0 : Element::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
    1437             :                                     const nsAString& aLocalName)
    1438             : {
    1439           0 :   return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName);
    1440             : }
    1441             : 
    1442             : already_AddRefed<Attr>
    1443           0 : Element::SetAttributeNodeNS(Attr& aNewAttr,
    1444             :                             ErrorResult& aError)
    1445             : {
    1446           0 :   OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS);
    1447           0 :   return Attributes()->SetNamedItemNS(aNewAttr, aError);
    1448             : }
    1449             : 
    1450             : already_AddRefed<nsIHTMLCollection>
    1451           1 : Element::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
    1452             :                                 const nsAString& aLocalName,
    1453             :                                 ErrorResult& aError)
    1454             : {
    1455           1 :   int32_t nameSpaceId = kNameSpaceID_Wildcard;
    1456             : 
    1457           1 :   if (!aNamespaceURI.EqualsLiteral("*")) {
    1458           1 :     aError =
    1459             :       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
    1460           1 :                                                             nameSpaceId);
    1461           1 :     if (aError.Failed()) {
    1462           0 :       return nullptr;
    1463             :     }
    1464             :   }
    1465             : 
    1466           1 :   NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
    1467             : 
    1468           1 :   return NS_GetContentList(this, nameSpaceId, aLocalName);
    1469             : }
    1470             : 
    1471             : bool
    1472           0 : Element::HasAttributeNS(const nsAString& aNamespaceURI,
    1473             :                         const nsAString& aLocalName) const
    1474             : {
    1475             :   int32_t nsid =
    1476           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
    1477           0 :                                                        nsContentUtils::IsChromeDoc(OwnerDoc()));
    1478             : 
    1479           0 :   if (nsid == kNameSpaceID_Unknown) {
    1480             :     // Unknown namespace means no attr...
    1481           0 :     return false;
    1482             :   }
    1483             : 
    1484           0 :   nsCOMPtr<nsIAtom> name = NS_AtomizeMainThread(aLocalName);
    1485           0 :   return HasAttr(nsid, name);
    1486             : }
    1487             : 
    1488             : already_AddRefed<nsIHTMLCollection>
    1489           0 : Element::GetElementsByClassName(const nsAString& aClassNames)
    1490             : {
    1491           0 :   return nsContentUtils::GetElementsByClassName(this, aClassNames);
    1492             : }
    1493             : 
    1494             : /**
    1495             :  * Returns the count of descendants (inclusive of aContent) in
    1496             :  * the uncomposed document that are explicitly set as editable.
    1497             :  */
    1498             : static uint32_t
    1499        3649 : EditableInclusiveDescendantCount(nsIContent* aContent)
    1500             : {
    1501        3649 :   auto htmlElem = nsGenericHTMLElement::FromContent(aContent);
    1502        3649 :   if (htmlElem) {
    1503         121 :     return htmlElem->EditableInclusiveDescendantCount();
    1504             :   }
    1505             : 
    1506        3528 :   return aContent->EditableDescendantCount();
    1507             : }
    1508             : 
    1509             : nsresult
    1510        4764 : Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
    1511             :                     nsIContent* aBindingParent,
    1512             :                     bool aCompileEventHandlers)
    1513             : {
    1514        4764 :   NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
    1515        4764 :   NS_PRECONDITION((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()),
    1516             :                   "Must have the same owner document");
    1517        4764 :   NS_PRECONDITION(!aParent || aDocument == aParent->GetUncomposedDoc(),
    1518             :                   "aDocument must be current doc of aParent");
    1519        4764 :   NS_PRECONDITION(!GetUncomposedDoc(), "Already have a document.  Unbind first!");
    1520             :   // Note that as we recurse into the kids, they'll have a non-null parent.  So
    1521             :   // only assert if our parent is _changing_ while we have a parent.
    1522        4764 :   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
    1523             :                   "Already have a parent.  Unbind first!");
    1524        4764 :   NS_PRECONDITION(!GetBindingParent() ||
    1525             :                   aBindingParent == GetBindingParent() ||
    1526             :                   (!aBindingParent && aParent &&
    1527             :                    aParent->GetBindingParent() == GetBindingParent()),
    1528             :                   "Already have a binding parent.  Unbind first!");
    1529        4764 :   NS_PRECONDITION(!aParent || !aDocument ||
    1530             :                   !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
    1531             :                   "Parent in document but flagged as forcing XBL");
    1532        4764 :   NS_PRECONDITION(aBindingParent != this,
    1533             :                   "Content must not be its own binding parent");
    1534        4764 :   NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
    1535             :                   aBindingParent == aParent,
    1536             :                   "Native anonymous content must have its parent as its "
    1537             :                   "own binding parent");
    1538        4764 :   NS_PRECONDITION(aBindingParent || !aParent ||
    1539             :                   aBindingParent == aParent->GetBindingParent(),
    1540             :                   "We should be passed the right binding parent");
    1541             : 
    1542             : #ifdef MOZ_XUL
    1543             :   // First set the binding parent
    1544        4764 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
    1545        4764 :   if (xulElem) {
    1546        3702 :     xulElem->SetXULBindingParent(aBindingParent);
    1547             :   }
    1548             :   else
    1549             : #endif
    1550             :   {
    1551        1062 :     if (aBindingParent) {
    1552         231 :       nsDOMSlots *slots = DOMSlots();
    1553             : 
    1554         231 :       slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
    1555             :     }
    1556             :   }
    1557        4764 :   NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
    1558             :                !HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
    1559             :                (aParent && aParent->IsInNativeAnonymousSubtree()),
    1560             :                "Trying to re-bind content from native anonymous subtree to "
    1561             :                "non-native anonymous parent!");
    1562        4764 :   if (aParent) {
    1563        4709 :     if (aParent->IsInNativeAnonymousSubtree()) {
    1564          28 :       SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
    1565             :     }
    1566        4709 :     if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
    1567           0 :       SetFlags(NODE_CHROME_ONLY_ACCESS);
    1568             :     }
    1569        4709 :     if (HasFlag(NODE_IS_ANONYMOUS_ROOT)) {
    1570         416 :       aParent->SetMayHaveAnonymousChildren();
    1571             :     }
    1572        4709 :     if (aParent->IsInShadowTree()) {
    1573           0 :       ClearSubtreeRootPointer();
    1574           0 :       SetFlags(NODE_IS_IN_SHADOW_TREE);
    1575             :     }
    1576        4709 :     ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
    1577        4709 :     if (parentContainingShadow) {
    1578           0 :       DOMSlots()->mContainingShadow = parentContainingShadow;
    1579             :     }
    1580             :   }
    1581             : 
    1582        4764 :   bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
    1583             : 
    1584        4764 :   bool hadParent = !!GetParentNode();
    1585             : 
    1586             :   // Now set the parent and set the "Force attach xbl" flag if needed.
    1587        4764 :   if (aParent) {
    1588        4709 :     if (!GetParent()) {
    1589        3377 :       NS_ADDREF(aParent);
    1590             :     }
    1591        4709 :     mParent = aParent;
    1592             : 
    1593        4709 :     if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    1594           4 :       SetFlags(NODE_FORCE_XBL_BINDINGS);
    1595             :     }
    1596             :   }
    1597             :   else {
    1598          55 :     mParent = aDocument;
    1599             :   }
    1600        4764 :   SetParentIsContent(aParent);
    1601             : 
    1602             :   // XXXbz sXBL/XBL2 issue!
    1603             : 
    1604             :   // Finally, set the document
    1605        4764 :   if (aDocument) {
    1606             :     // Notify XBL- & nsIAnonymousContentCreator-generated
    1607             :     // anonymous content that the document is changing.
    1608             :     // XXXbz ordering issues here?  Probably not, since ChangeDocumentFor is
    1609             :     // just pretty broken anyway....  Need to get it working.
    1610             :     // XXXbz XBL doesn't handle this (asserts), and we don't really want
    1611             :     // to be doing this during parsing anyway... sort this out.
    1612             :     //    aDocument->BindingManager()->ChangeDocumentFor(this, nullptr,
    1613             :     //                                                   aDocument);
    1614             : 
    1615             :     // We no longer need to track the subtree pointer (and in fact we'll assert
    1616             :     // if we do this any later).
    1617        2995 :     ClearSubtreeRootPointer();
    1618             : 
    1619             :     // Being added to a document.
    1620        2995 :     SetIsInDocument();
    1621             : 
    1622             :     // Unset this flag since we now really are in a document.
    1623        2995 :     UnsetFlags(NODE_FORCE_XBL_BINDINGS |
    1624             :                // And clear the lazy frame construction bits.
    1625        2995 :                NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
    1626             :     // And the restyle bits
    1627        2995 :     UnsetRestyleFlagsIfGecko();
    1628        1769 :   } else if (IsInShadowTree()) {
    1629             :     // We're not in a document, but we did get inserted into a shadow tree.
    1630             :     // Since we won't have any restyle data in the document's restyle trackers,
    1631             :     // don't let us get inserted with restyle bits set incorrectly.
    1632             :     //
    1633             :     // Also clear all the other flags that are cleared above when we do get
    1634             :     // inserted into a document.
    1635           0 :     UnsetFlags(NODE_FORCE_XBL_BINDINGS |
    1636           0 :                NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
    1637           0 :     UnsetRestyleFlagsIfGecko();
    1638             :   } else {
    1639             :     // If we're not in the doc and not in a shadow tree,
    1640             :     // update our subtree pointer.
    1641        1769 :     SetSubtreeRootPointer(aParent->SubtreeRoot());
    1642             :   }
    1643             : 
    1644        4764 :   nsIDocument* composedDoc = GetComposedDoc();
    1645        4764 :   if (composedDoc) {
    1646             :     // Attached callback must be enqueued whenever custom element is inserted into a
    1647             :     // document and this document has a browsing context.
    1648        2995 :     if (GetCustomElementData() && composedDoc->GetDocShell()) {
    1649             :       // Enqueue an attached callback for the custom element.
    1650             :       nsContentUtils::EnqueueLifecycleCallback(
    1651           0 :         composedDoc, nsIDocument::eAttached, this);
    1652             :     }
    1653             :   }
    1654             : 
    1655             :   // Propagate scoped style sheet tracking bit.
    1656        4764 :   if (mParent->IsContent()) {
    1657             :     nsIContent* parent;
    1658        4709 :     ShadowRoot* shadowRootParent = ShadowRoot::FromNode(mParent);
    1659        4709 :     if (shadowRootParent) {
    1660           0 :       parent = shadowRootParent->GetHost();
    1661             :     } else {
    1662        4709 :       parent = mParent->AsContent();
    1663             :     }
    1664             : 
    1665        4709 :     bool inStyleScope = parent->IsElementInStyleScope();
    1666             : 
    1667        4709 :     SetIsElementInStyleScope(inStyleScope);
    1668        4709 :     SetIsElementInStyleScopeFlagOnShadowTree(inStyleScope);
    1669             :   }
    1670             : 
    1671             :   // This has to be here, rather than in nsGenericHTMLElement::BindToTree,
    1672             :   //  because it has to happen after updating the parent pointer, but before
    1673             :   //  recursively binding the kids.
    1674        4764 :   if (IsHTMLElement()) {
    1675         130 :     SetDirOnBind(this, aParent);
    1676             :   }
    1677             : 
    1678        4764 :   uint32_t editableDescendantCount = 0;
    1679             : 
    1680             :   // If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
    1681             :   // that also need to be told that they are moving.
    1682             :   nsresult rv;
    1683        4764 :   if (hadForceXBL) {
    1684           6 :     nsBindingManager* bmgr = OwnerDoc()->BindingManager();
    1685             : 
    1686           6 :     nsXBLBinding* contBinding = bmgr->GetBindingWithContent(this);
    1687             :     // First check if we have a binding...
    1688           6 :     if (contBinding) {
    1689           4 :       nsCOMPtr<nsIContent> anonRoot = contBinding->GetAnonymousContent();
    1690           2 :       bool allowScripts = contBinding->AllowScripts();
    1691           4 :       for (nsCOMPtr<nsIContent> child = anonRoot->GetFirstChild();
    1692             :            child;
    1693           2 :            child = child->GetNextSibling()) {
    1694           2 :         rv = child->BindToTree(aDocument, this, this, allowScripts);
    1695           2 :         NS_ENSURE_SUCCESS(rv, rv);
    1696             : 
    1697           2 :         editableDescendantCount += EditableInclusiveDescendantCount(child);
    1698             :       }
    1699             :     }
    1700             :   }
    1701             : 
    1702        4764 :   UpdateEditableState(false);
    1703             : 
    1704             :   // Now recurse into our kids
    1705        6260 :   for (nsIContent* child = GetFirstChild(); child;
    1706        1496 :        child = child->GetNextSibling()) {
    1707        1496 :     rv = child->BindToTree(aDocument, this, aBindingParent,
    1708        2992 :                            aCompileEventHandlers);
    1709        1496 :     NS_ENSURE_SUCCESS(rv, rv);
    1710             : 
    1711        1496 :     editableDescendantCount += EditableInclusiveDescendantCount(child);
    1712             :   }
    1713             : 
    1714        4764 :   if (aDocument) {
    1715             :     // Update our editable descendant count because we don't keep track of it
    1716             :     // for content that is not in the uncomposed document.
    1717        2995 :     MOZ_ASSERT(EditableDescendantCount() == 0);
    1718        2995 :     ChangeEditableDescendantCount(editableDescendantCount);
    1719             : 
    1720        2995 :     if (!hadParent) {
    1721        2116 :       uint32_t editableDescendantChange = EditableInclusiveDescendantCount(this);
    1722        2116 :       if (editableDescendantChange != 0) {
    1723             :       // If we are binding a subtree root to the document, we need to update
    1724             :       // the editable descendant count of all the ancestors.
    1725           0 :         nsIContent* parent = GetParent();
    1726           0 :         while (parent) {
    1727           0 :           parent->ChangeEditableDescendantCount(editableDescendantChange);
    1728           0 :           parent = parent->GetParent();
    1729             :         }
    1730             :       }
    1731             :     }
    1732             :   }
    1733             : 
    1734        4764 :   nsNodeUtils::ParentChainChanged(this);
    1735        4764 :   if (!hadParent && IsRootOfNativeAnonymousSubtree()) {
    1736          45 :     nsNodeUtils::NativeAnonymousChildListChange(this, false);
    1737             :   }
    1738             : 
    1739        4764 :   if (HasID()) {
    1740        1227 :     AddToIdTable(DoGetID());
    1741             :   }
    1742             : 
    1743        4764 :   if (MayHaveStyle() && !IsXULElement()) {
    1744             :     // XXXbz if we already have a style attr parsed, this won't do
    1745             :     // anything... need to fix that.
    1746             :     // If MayHaveStyle() is true, we must be an nsStyledElement
    1747           0 :     static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false, false);
    1748             :   }
    1749             : 
    1750             :   // Call BindToTree on shadow root children.
    1751        4764 :   ShadowRoot* shadowRoot = GetShadowRoot();
    1752        4764 :   if (shadowRoot) {
    1753           0 :     shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
    1754           0 :     for (nsIContent* child = shadowRoot->GetFirstChild(); child;
    1755           0 :          child = child->GetNextSibling()) {
    1756           0 :       rv = child->BindToTree(nullptr, shadowRoot,
    1757           0 :                              shadowRoot->GetBindingParent(),
    1758           0 :                              aCompileEventHandlers);
    1759           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1760             :     }
    1761             :   }
    1762             : 
    1763             :   // Pseudo-elements implemented by JS must have the NODE_IS_NATIVE_ANONYMOUS
    1764             :   // flag set on them. For C++-created pseudo-elements, this is done in
    1765             :   // nsCSSFrameConstructor::GetAnonymousContent, but any JS that creates
    1766             :   // pseudo-elements would run after that. So we set that flag here,
    1767             :   // when the element implementing the pseudo is inserted into the document.
    1768             :   // We maintain the invariant that any NAC-implemented pseudo-element's
    1769             :   // anonymous ancestors are also flagged as NAC, which the style system relies on.
    1770        4764 :   if (aDocument) {
    1771        2995 :     CSSPseudoElementType pseudoType = GetPseudoElementType();
    1772        3005 :     if (pseudoType != CSSPseudoElementType::NotPseudo &&
    1773          10 :         nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType)) {
    1774           0 :       SetFlags(NODE_IS_NATIVE_ANONYMOUS);
    1775           0 :       nsIContent* parent = aParent;
    1776           0 :       while (parent && !parent->IsRootOfNativeAnonymousSubtree()) {
    1777           0 :         MOZ_ASSERT(parent->IsInNativeAnonymousSubtree());
    1778           0 :         parent->SetFlags(NODE_IS_NATIVE_ANONYMOUS);
    1779           0 :         parent = parent->GetParent();
    1780             :       }
    1781           0 :       MOZ_ASSERT(parent);
    1782             :     }
    1783             :   }
    1784             : 
    1785             :   // XXXbz script execution during binding can trigger some of these
    1786             :   // postcondition asserts....  But we do want that, since things will
    1787             :   // generally be quite broken when that happens.
    1788        4764 :   NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
    1789        4764 :   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
    1790        4764 :   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
    1791             :                    "Bound to wrong binding parent");
    1792             : 
    1793        4764 :   return NS_OK;
    1794             : }
    1795             : 
    1796          12 : RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(
    1797             :   nsBindingManager* aManager,
    1798             :   nsIContent* aContent,
    1799          12 :   nsIDocument* aDoc)
    1800             :   : mozilla::Runnable("dom::RemoveFromBindingManagerRunnable")
    1801             :   , mManager(aManager)
    1802             :   , mContent(aContent)
    1803          12 :   , mDoc(aDoc)
    1804          12 : {}
    1805             : 
    1806          36 : RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
    1807             : 
    1808             : NS_IMETHODIMP
    1809          12 : RemoveFromBindingManagerRunnable::Run()
    1810             : {
    1811             :   // It may be the case that the element was removed from the
    1812             :   // DOM, causing this runnable to be created, then inserted back
    1813             :   // into the document before the this runnable had a chance to
    1814             :   // tear down the binding. Only tear down the binding if the element
    1815             :   // is still no longer in the DOM. nsXBLService::LoadBinding tears
    1816             :   // down the old binding if the element is inserted back into the
    1817             :   // DOM and loads a different binding.
    1818          12 :   if (!mContent->IsInComposedDoc()) {
    1819          12 :     mManager->RemovedFromDocumentInternal(mContent, mDoc,
    1820          12 :                                           nsBindingManager::eRunDtor);
    1821             :   }
    1822             : 
    1823          12 :   return NS_OK;
    1824             : }
    1825             : 
    1826             : 
    1827             : void
    1828         912 : Element::UnbindFromTree(bool aDeep, bool aNullParent)
    1829             : {
    1830         912 :   NS_PRECONDITION(aDeep || (!GetUncomposedDoc() && !GetBindingParent()),
    1831             :                   "Shallow unbind won't clear document and binding parent on "
    1832             :                   "kids!");
    1833             : 
    1834         912 :   RemoveFromIdTable();
    1835             : 
    1836             :   // Make sure to unbind this node before doing the kids
    1837             :   nsIDocument* document =
    1838         912 :     HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetComposedDoc();
    1839             : 
    1840         912 :   if (HasPointerLock()) {
    1841           0 :     nsIDocument::UnlockPointer();
    1842             :   }
    1843         912 :   if (mState.HasState(NS_EVENT_STATE_FULL_SCREEN)) {
    1844             :     // The element being removed is an ancestor of the full-screen element,
    1845             :     // exit full-screen state.
    1846           0 :     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1847           0 :                                     NS_LITERAL_CSTRING("DOM"), OwnerDoc(),
    1848             :                                     nsContentUtils::eDOM_PROPERTIES,
    1849           0 :                                     "RemovedFullscreenElement");
    1850             :     // Fully exit full-screen.
    1851           0 :     nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
    1852             :   }
    1853         912 :   if (aNullParent) {
    1854         511 :     if (GetParent() && GetParent()->IsInUncomposedDoc()) {
    1855             :       // Update the editable descendant count in the ancestors before we
    1856             :       // lose the reference to the parent.
    1857          35 :       int32_t editableDescendantChange = -1 * EditableInclusiveDescendantCount(this);
    1858          35 :       if (editableDescendantChange != 0) {
    1859           0 :         nsIContent* parent = GetParent();
    1860           0 :         while (parent) {
    1861           0 :           parent->ChangeEditableDescendantCount(editableDescendantChange);
    1862           0 :           parent = parent->GetParent();
    1863             :         }
    1864             :       }
    1865             :     }
    1866             : 
    1867         511 :     if (this->IsRootOfNativeAnonymousSubtree()) {
    1868           4 :       nsNodeUtils::NativeAnonymousChildListChange(this, true);
    1869             :     }
    1870             : 
    1871         511 :     if (GetParent()) {
    1872         966 :       RefPtr<nsINode> p;
    1873         483 :       p.swap(mParent);
    1874             :     } else {
    1875          28 :       mParent = nullptr;
    1876             :     }
    1877         511 :     SetParentIsContent(false);
    1878             :   }
    1879             : 
    1880             : #ifdef DEBUG
    1881             :   // If we can get access to the PresContext, then we sanity-check that
    1882             :   // we're not leaving behind a pointer to ourselves as the PresContext's
    1883             :   // cached provider of the viewport's scrollbar styles.
    1884         912 :   if (document) {
    1885          66 :     nsIPresShell* presShell = document->GetShell();
    1886          66 :     if (presShell) {
    1887          66 :       nsPresContext* presContext = presShell->GetPresContext();
    1888          66 :       if (presContext) {
    1889          66 :         MOZ_ASSERT(this !=
    1890             :                    presContext->GetViewportScrollbarStylesOverrideNode(),
    1891             :                    "Leaving behind a raw pointer to this node (as having "
    1892             :                    "propagated scrollbar styles) - that's dangerous...");
    1893             :       }
    1894             :     }
    1895             :   }
    1896             : #endif
    1897             : 
    1898             :   // Ensure that CSS transitions don't continue on an element at a
    1899             :   // different place in the tree (even if reinserted before next
    1900             :   // animation refresh).
    1901             :   // We need to delete the properties while we're still in document
    1902             :   // (if we were in document).
    1903             :   // FIXME (Bug 522599): Need a test for this.
    1904         912 :   if (MayHaveAnimations()) {
    1905           0 :     DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
    1906           0 :     DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
    1907           0 :     DeleteProperty(nsGkAtoms::transitionsProperty);
    1908           0 :     DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
    1909           0 :     DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
    1910           0 :     DeleteProperty(nsGkAtoms::animationsProperty);
    1911             :   }
    1912             : 
    1913         912 :   ClearInDocument();
    1914             : 
    1915             :   // Computed styled data isn't useful for detached nodes, and we'll need to
    1916             :   // recomputed it anyway if we ever insert the nodes back into a document.
    1917         912 :   if (IsStyledByServo()) {
    1918           0 :     ClearServoData();
    1919             :   } else {
    1920         912 :     MOZ_ASSERT(!HasServoData());
    1921             :   }
    1922             : 
    1923             :   // Editable descendant count only counts descendants that
    1924             :   // are in the uncomposed document.
    1925         912 :   ResetEditableDescendantCount();
    1926             : 
    1927         912 :   if (aNullParent || !mParent->IsInShadowTree()) {
    1928         912 :     UnsetFlags(NODE_IS_IN_SHADOW_TREE);
    1929             : 
    1930             :     // Begin keeping track of our subtree root.
    1931         912 :     SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
    1932             :   }
    1933             : 
    1934         912 :   if (document) {
    1935             :     // Notify XBL- & nsIAnonymousContentCreator-generated
    1936             :     // anonymous content that the document is changing.
    1937             :     // Unlike XBL, bindings for web components shadow DOM
    1938             :     // do not get uninstalled.
    1939          66 :     if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && !GetShadowRoot()) {
    1940             :       nsContentUtils::AddScriptRunner(
    1941          12 :         new RemoveFromBindingManagerRunnable(document->BindingManager(), this,
    1942          12 :                                              document));
    1943             :     }
    1944             : 
    1945          66 :     document->ClearBoxObjectFor(this);
    1946             : 
    1947             :     // Detached must be enqueued whenever custom element is removed from
    1948             :     // the document and this document has a browsing context.
    1949          66 :     if (GetCustomElementData() && document->GetDocShell()) {
    1950             :       // Enqueue a detached callback for the custom element.
    1951             :       nsContentUtils::EnqueueLifecycleCallback(
    1952           0 :         document, nsIDocument::eDetached, this);
    1953             :     }
    1954             :   }
    1955             : 
    1956             :   // Unset this since that's what the old code effectively did.
    1957         912 :   UnsetFlags(NODE_FORCE_XBL_BINDINGS);
    1958         912 :   bool clearBindingParent = true;
    1959             : 
    1960             : #ifdef MOZ_XUL
    1961         912 :   nsXULElement* xulElem = nsXULElement::FromContent(this);
    1962         912 :   if (xulElem) {
    1963         716 :     xulElem->SetXULBindingParent(nullptr);
    1964         716 :     clearBindingParent = false;
    1965             :   }
    1966             : #endif
    1967             : 
    1968         912 :   nsDOMSlots* slots = GetExistingDOMSlots();
    1969         912 :   if (slots) {
    1970          49 :     if (clearBindingParent) {
    1971          29 :       slots->mBindingParent = nullptr;
    1972             :     }
    1973          49 :     if (aNullParent || !mParent->IsInShadowTree()) {
    1974          49 :       slots->mContainingShadow = nullptr;
    1975             :     }
    1976             :   }
    1977             : 
    1978             :   // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
    1979             :   //  because it has to happen after unsetting the parent pointer, but before
    1980             :   //  recursively unbinding the kids.
    1981         912 :   if (IsHTMLElement()) {
    1982          10 :     ResetDir(this);
    1983             :   }
    1984             : 
    1985         912 :   if (aDeep) {
    1986             :     // Do the kids. Don't call GetChildCount() here since that'll force
    1987             :     // XUL to generate template children, which there is no need for since
    1988             :     // all we're going to do is unbind them anyway.
    1989         907 :     uint32_t i, n = mAttrsAndChildren.ChildCount();
    1990             : 
    1991        1339 :     for (i = 0; i < n; ++i) {
    1992             :       // Note that we pass false for aNullParent here, since we don't want
    1993             :       // the kids to forget us.  We _do_ want them to forget their binding
    1994             :       // parent, though, since this only walks non-anonymous kids.
    1995         432 :       mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false);
    1996             :     }
    1997             :   }
    1998             : 
    1999         912 :   nsNodeUtils::ParentChainChanged(this);
    2000             : 
    2001             :   // Unbind children of shadow root.
    2002         912 :   ShadowRoot* shadowRoot = GetShadowRoot();
    2003         912 :   if (shadowRoot) {
    2004           0 :     for (nsIContent* child = shadowRoot->GetFirstChild(); child;
    2005           0 :          child = child->GetNextSibling()) {
    2006           0 :       child->UnbindFromTree(true, false);
    2007             :     }
    2008             : 
    2009           0 :     shadowRoot->SetIsComposedDocParticipant(false);
    2010             :   }
    2011         912 : }
    2012             : 
    2013             : nsICSSDeclaration*
    2014           0 : Element::GetSMILOverrideStyle()
    2015             : {
    2016           0 :   Element::nsDOMSlots *slots = DOMSlots();
    2017             : 
    2018           0 :   if (!slots->mSMILOverrideStyle) {
    2019           0 :     slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
    2020             :   }
    2021             : 
    2022           0 :   return slots->mSMILOverrideStyle;
    2023             : }
    2024             : 
    2025             : DeclarationBlock*
    2026        2504 : Element::GetSMILOverrideStyleDeclaration()
    2027             : {
    2028        2504 :   Element::nsDOMSlots *slots = GetExistingDOMSlots();
    2029        2504 :   return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
    2030             : }
    2031             : 
    2032             : nsresult
    2033           0 : Element::SetSMILOverrideStyleDeclaration(DeclarationBlock* aDeclaration,
    2034             :                                          bool aNotify)
    2035             : {
    2036           0 :   Element::nsDOMSlots *slots = DOMSlots();
    2037             : 
    2038           0 :   slots->mSMILOverrideStyleDeclaration = aDeclaration;
    2039             : 
    2040           0 :   if (aNotify) {
    2041           0 :     nsIDocument* doc = GetComposedDoc();
    2042             :     // Only need to request a restyle if we're in a document.  (We might not
    2043             :     // be in a document, if we're clearing animation effects on a target node
    2044             :     // that's been detached since the previous animation sample.)
    2045           0 :     if (doc) {
    2046           0 :       nsCOMPtr<nsIPresShell> shell = doc->GetShell();
    2047           0 :       if (shell) {
    2048           0 :         shell->RestyleForAnimation(this, eRestyle_StyleAttribute_Animations);
    2049             :       }
    2050             :     }
    2051             :   }
    2052             : 
    2053           0 :   return NS_OK;
    2054             : }
    2055             : 
    2056             : bool
    2057           0 : Element::IsLabelable() const
    2058             : {
    2059           0 :   return false;
    2060             : }
    2061             : 
    2062             : bool
    2063           0 : Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
    2064             : {
    2065           0 :   return false;
    2066             : }
    2067             : 
    2068             : DeclarationBlock*
    2069        2532 : Element::GetInlineStyleDeclaration() const
    2070             : {
    2071        2532 :   if (!MayHaveStyle()) {
    2072        2468 :     return nullptr;
    2073             :   }
    2074          64 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
    2075             : 
    2076          64 :   if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) {
    2077          35 :     return attrVal->GetCSSDeclarationValue();
    2078             :   }
    2079             : 
    2080          29 :   return nullptr;
    2081             : }
    2082             : 
    2083             : const nsMappedAttributes*
    2084           0 : Element::GetMappedAttributes() const
    2085             : {
    2086           0 :   return mAttrsAndChildren.GetMapped();
    2087             : }
    2088             : 
    2089             : nsresult
    2090           0 : Element::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
    2091             :                                    const nsAString* aSerialized,
    2092             :                                    bool aNotify)
    2093             : {
    2094           0 :   NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
    2095           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2096             : }
    2097             : 
    2098             : NS_IMETHODIMP_(bool)
    2099        1137 : Element::IsAttributeMapped(const nsIAtom* aAttribute) const
    2100             : {
    2101        1137 :   return false;
    2102             : }
    2103             : 
    2104             : nsChangeHint
    2105           1 : Element::GetAttributeChangeHint(const nsIAtom* aAttribute,
    2106             :                                 int32_t aModType) const
    2107             : {
    2108           1 :   return nsChangeHint(0);
    2109             : }
    2110             : 
    2111             : bool
    2112        1861 : Element::FindAttributeDependence(const nsIAtom* aAttribute,
    2113             :                                  const MappedAttributeEntry* const aMaps[],
    2114             :                                  uint32_t aMapCount)
    2115             : {
    2116        7847 :   for (uint32_t mapindex = 0; mapindex < aMapCount; ++mapindex) {
    2117       40645 :     for (const MappedAttributeEntry* map = aMaps[mapindex];
    2118       40645 :          map->attribute; ++map) {
    2119       34659 :       if (aAttribute == *map->attribute) {
    2120         192 :         return true;
    2121             :       }
    2122             :     }
    2123             :   }
    2124             : 
    2125        1669 :   return false;
    2126             : }
    2127             : 
    2128             : already_AddRefed<mozilla::dom::NodeInfo>
    2129           2 : Element::GetExistingAttrNameFromQName(const nsAString& aStr) const
    2130             : {
    2131           2 :   const nsAttrName* name = InternalGetAttrNameFromQName(aStr);
    2132           2 :   if (!name) {
    2133           0 :     return nullptr;
    2134             :   }
    2135             : 
    2136           4 :   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
    2137           2 :   if (name->IsAtom()) {
    2138             :     nodeInfo = mNodeInfo->NodeInfoManager()->
    2139           4 :       GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
    2140           2 :                   nsIDOMNode::ATTRIBUTE_NODE);
    2141             :   }
    2142             :   else {
    2143           0 :     nodeInfo = name->NodeInfo();
    2144             :   }
    2145             : 
    2146           2 :   return nodeInfo.forget();
    2147             : }
    2148             : 
    2149             : // static
    2150             : bool
    2151           0 : Element::ShouldBlur(nsIContent *aContent)
    2152             : {
    2153             :   // Determine if the current element is focused, if it is not focused
    2154             :   // then we should not try to blur
    2155           0 :   nsIDocument* document = aContent->GetComposedDoc();
    2156           0 :   if (!document)
    2157           0 :     return false;
    2158             : 
    2159           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
    2160           0 :   if (!window)
    2161           0 :     return false;
    2162             : 
    2163           0 :   nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
    2164             :   nsIContent* contentToBlur =
    2165           0 :     nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame));
    2166           0 :   if (contentToBlur == aContent)
    2167           0 :     return true;
    2168             : 
    2169             :   // if focus on this element would get redirected, then check the redirected
    2170             :   // content as well when blurring.
    2171           0 :   return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
    2172             : }
    2173             : 
    2174             : bool
    2175        4888 : Element::IsNodeOfType(uint32_t aFlags) const
    2176             : {
    2177        4888 :   return !(aFlags & ~eCONTENT);
    2178             : }
    2179             : 
    2180             : /* static */
    2181             : nsresult
    2182           0 : Element::DispatchEvent(nsPresContext* aPresContext,
    2183             :                        WidgetEvent* aEvent,
    2184             :                        nsIContent* aTarget,
    2185             :                        bool aFullDispatch,
    2186             :                        nsEventStatus* aStatus)
    2187             : {
    2188           0 :   NS_PRECONDITION(aTarget, "Must have target");
    2189           0 :   NS_PRECONDITION(aEvent, "Must have source event");
    2190           0 :   NS_PRECONDITION(aStatus, "Null out param?");
    2191             : 
    2192           0 :   if (!aPresContext) {
    2193           0 :     return NS_OK;
    2194             :   }
    2195             : 
    2196           0 :   nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
    2197           0 :   if (!shell) {
    2198           0 :     return NS_OK;
    2199             :   }
    2200             : 
    2201           0 :   if (aFullDispatch) {
    2202           0 :     return shell->HandleEventWithTarget(aEvent, nullptr, aTarget, aStatus);
    2203             :   }
    2204             : 
    2205           0 :   return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
    2206             : }
    2207             : 
    2208             : /* static */
    2209             : nsresult
    2210           0 : Element::DispatchClickEvent(nsPresContext* aPresContext,
    2211             :                             WidgetInputEvent* aSourceEvent,
    2212             :                             nsIContent* aTarget,
    2213             :                             bool aFullDispatch,
    2214             :                             const EventFlags* aExtraEventFlags,
    2215             :                             nsEventStatus* aStatus)
    2216             : {
    2217           0 :   NS_PRECONDITION(aTarget, "Must have target");
    2218           0 :   NS_PRECONDITION(aSourceEvent, "Must have source event");
    2219           0 :   NS_PRECONDITION(aStatus, "Null out param?");
    2220             : 
    2221           0 :   WidgetMouseEvent event(aSourceEvent->IsTrusted(), eMouseClick,
    2222           0 :                          aSourceEvent->mWidget, WidgetMouseEvent::eReal);
    2223           0 :   event.mRefPoint = aSourceEvent->mRefPoint;
    2224           0 :   uint32_t clickCount = 1;
    2225           0 :   float pressure = 0;
    2226           0 :   uint32_t pointerId = 0; // Use the default value here.
    2227           0 :   uint16_t inputSource = 0;
    2228           0 :   WidgetMouseEvent* sourceMouseEvent = aSourceEvent->AsMouseEvent();
    2229           0 :   if (sourceMouseEvent) {
    2230           0 :     clickCount = sourceMouseEvent->mClickCount;
    2231           0 :     pressure = sourceMouseEvent->pressure;
    2232           0 :     pointerId = sourceMouseEvent->pointerId;
    2233           0 :     inputSource = sourceMouseEvent->inputSource;
    2234           0 :   } else if (aSourceEvent->mClass == eKeyboardEventClass) {
    2235           0 :     event.mFlags.mIsPositionless = true;
    2236           0 :     inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
    2237             :   }
    2238           0 :   event.pressure = pressure;
    2239           0 :   event.mClickCount = clickCount;
    2240           0 :   event.pointerId = pointerId;
    2241           0 :   event.inputSource = inputSource;
    2242           0 :   event.mModifiers = aSourceEvent->mModifiers;
    2243           0 :   if (aExtraEventFlags) {
    2244             :     // Be careful not to overwrite existing flags!
    2245           0 :     event.mFlags.Union(*aExtraEventFlags);
    2246             :   }
    2247             : 
    2248           0 :   return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
    2249             : }
    2250             : 
    2251             : nsIFrame*
    2252           4 : Element::GetPrimaryFrame(FlushType aType)
    2253             : {
    2254           4 :   nsIDocument* doc = GetComposedDoc();
    2255           4 :   if (!doc) {
    2256           0 :     return nullptr;
    2257             :   }
    2258             : 
    2259             :   // Cause a flush, so we get up-to-date frame
    2260             :   // information
    2261           4 :   if (aType != FlushType::None) {
    2262           4 :     doc->FlushPendingNotifications(aType);
    2263             :   }
    2264             : 
    2265           4 :   return GetPrimaryFrame();
    2266             : }
    2267             : 
    2268             : //----------------------------------------------------------------------
    2269             : nsresult
    2270           0 : Element::LeaveLink(nsPresContext* aPresContext)
    2271             : {
    2272           0 :   nsILinkHandler *handler = aPresContext->GetLinkHandler();
    2273           0 :   if (!handler) {
    2274           0 :     return NS_OK;
    2275             :   }
    2276             : 
    2277           0 :   return handler->OnLeaveLink();
    2278             : }
    2279             : 
    2280             : nsresult
    2281         554 : Element::SetEventHandler(nsIAtom* aEventName,
    2282             :                          const nsAString& aValue,
    2283             :                          bool aDefer)
    2284             : {
    2285         554 :   nsIDocument *ownerDoc = OwnerDoc();
    2286         554 :   if (ownerDoc->IsLoadedAsData()) {
    2287             :     // Make this a no-op rather than throwing an error to avoid
    2288             :     // the error causing problems setting the attribute.
    2289           0 :     return NS_OK;
    2290             :   }
    2291             : 
    2292         554 :   NS_PRECONDITION(aEventName, "Must have event name!");
    2293         554 :   bool defer = true;
    2294             :   EventListenerManager* manager =
    2295         554 :     GetEventListenerManagerForAttr(aEventName, &defer);
    2296         554 :   if (!manager) {
    2297           0 :     return NS_OK;
    2298             :   }
    2299             : 
    2300         554 :   defer = defer && aDefer; // only defer if everyone agrees...
    2301         554 :   manager->SetEventHandler(aEventName, aValue,
    2302         554 :                            defer, !nsContentUtils::IsChromeDoc(ownerDoc),
    2303         554 :                            this);
    2304         554 :   return NS_OK;
    2305             : }
    2306             : 
    2307             : 
    2308             : //----------------------------------------------------------------------
    2309             : 
    2310             : const nsAttrName*
    2311         502 : Element::InternalGetAttrNameFromQName(const nsAString& aStr,
    2312             :                                       nsAutoString* aNameToUse) const
    2313             : {
    2314         502 :   MOZ_ASSERT(!aNameToUse || aNameToUse->IsEmpty());
    2315         502 :   const nsAttrName* val = nullptr;
    2316         502 :   if (IsHTMLElement() && IsInHTMLDocument()) {
    2317           2 :     nsAutoString lower;
    2318           1 :     nsAutoString& outStr = aNameToUse ? *aNameToUse : lower;
    2319           1 :     nsContentUtils::ASCIIToLower(aStr, outStr);
    2320           1 :     val = mAttrsAndChildren.GetExistingAttrNameFromQName(outStr);
    2321           1 :     if (val) {
    2322           0 :       outStr.Truncate();
    2323             :     }
    2324             :   } else {
    2325         501 :     val = mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
    2326         501 :     if (!val && aNameToUse) {
    2327         277 :       *aNameToUse = aStr;
    2328             :     }
    2329             :   }
    2330             : 
    2331         502 :   return val;
    2332             : }
    2333             : 
    2334             : bool
    2335        1917 : Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
    2336             :                                nsIAtom* aName,
    2337             :                                nsIAtom* aPrefix,
    2338             :                                const nsAttrValueOrString& aValue,
    2339             :                                bool aNotify,
    2340             :                                nsAttrValue& aOldValue,
    2341             :                                uint8_t* aModType,
    2342             :                                bool* aHasListeners,
    2343             :                                bool* aOldValueSet)
    2344             : {
    2345        1917 :   bool modification = false;
    2346        2568 :   *aHasListeners = aNotify &&
    2347         651 :     nsContentUtils::HasMutationListeners(this,
    2348             :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    2349             :                                          this);
    2350        1917 :   *aOldValueSet = false;
    2351             : 
    2352             :   // If we have no listeners and aNotify is false, we are almost certainly
    2353             :   // coming from the content sink and will almost certainly have no previous
    2354             :   // value.  Even if we do, setting the value is cheap when we have no
    2355             :   // listeners and don't plan to notify.  The check for aNotify here is an
    2356             :   // optimization, the check for *aHasListeners is a correctness issue.
    2357        1917 :   if (*aHasListeners || aNotify) {
    2358         651 :     BorrowedAttrInfo info(GetAttrInfo(aNamespaceID, aName));
    2359         651 :     if (info.mValue) {
    2360             :       // Check whether the old value is the same as the new one.  Note that we
    2361             :       // only need to actually _get_ the old value if we have listeners or
    2362             :       // if the element is a custom element (because it may have an
    2363             :       // attribute changed callback).
    2364         134 :       if (*aHasListeners || GetCustomElementData()) {
    2365             :         // Need to store the old value.
    2366             :         //
    2367             :         // If the current attribute value contains a pointer to some other data
    2368             :         // structure that gets updated in the process of setting the attribute
    2369             :         // we'll no longer have the old value of the attribute. Therefore, we
    2370             :         // should serialize the attribute value now to keep a snapshot.
    2371             :         //
    2372             :         // We have to serialize the value anyway in order to create the
    2373             :         // mutation event so there's no cost in doing it now.
    2374           0 :         aOldValue.SetToSerialized(*info.mValue);
    2375           0 :         *aOldValueSet = true;
    2376             :       }
    2377         134 :       bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
    2378         134 :       if (valueMatches && aPrefix == info.mName->GetPrefix()) {
    2379         101 :         return true;
    2380             :       }
    2381          33 :       modification = true;
    2382             :     }
    2383             :   }
    2384        1816 :   *aModType = modification ?
    2385             :     static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
    2386             :     static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
    2387        1816 :   return false;
    2388             : }
    2389             : 
    2390             : bool
    2391        1917 : Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
    2392             :                                 nsIAtom* aPrefix,
    2393             :                                 const nsAttrValueOrString& aValue,
    2394             :                                 bool aNotify, nsAttrValue& aOldValue,
    2395             :                                 uint8_t* aModType, bool* aHasListeners,
    2396             :                                 bool* aOldValueSet)
    2397             : {
    2398        1917 :   if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify,
    2399             :                              aOldValue, aModType, aHasListeners,
    2400             :                              aOldValueSet)) {
    2401        1816 :     return false;
    2402             :   }
    2403             : 
    2404         202 :   nsAutoScriptBlocker scriptBlocker;
    2405         101 :   nsNodeUtils::AttributeSetToCurrentValue(this, aNamespaceID, aName);
    2406         101 :   return true;
    2407             : }
    2408             : 
    2409             : nsresult
    2410        1917 : Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
    2411             :                  nsIAtom* aPrefix, const nsAString& aValue,
    2412             :                  bool aNotify)
    2413             : {
    2414             :   // Keep this in sync with SetParsedAttr below
    2415             : 
    2416        1917 :   NS_ENSURE_ARG_POINTER(aName);
    2417        1917 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    2418             :                "Don't call SetAttr with unknown namespace");
    2419             : 
    2420        1917 :   if (!mAttrsAndChildren.CanFitMoreAttrs()) {
    2421           0 :     return NS_ERROR_FAILURE;
    2422             :   }
    2423             : 
    2424             :   uint8_t modType;
    2425             :   bool hasListeners;
    2426             :   // We don't want to spend time preparsing class attributes if the value is not
    2427             :   // changing, so just init our nsAttrValueOrString with aValue for the
    2428             :   // OnlyNotifySameValueSet call.
    2429        3834 :   nsAttrValueOrString value(aValue);
    2430        3834 :   nsAttrValue oldValue;
    2431             :   bool oldValueSet;
    2432             : 
    2433        1917 :   if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
    2434             :                              oldValue, &modType, &hasListeners, &oldValueSet)) {
    2435         101 :     return OnAttrSetButNotChanged(aNamespaceID, aName, value, aNotify);
    2436             :   }
    2437             : 
    2438        3632 :   nsAttrValue attrValue;
    2439             :   nsAttrValue* preparsedAttrValue;
    2440        1816 :   if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::_class) {
    2441          90 :     attrValue.ParseAtomArray(aValue);
    2442          90 :     value.ResetToAttrValue(attrValue);
    2443          90 :     preparsedAttrValue = &attrValue;
    2444             :   } else {
    2445        1726 :     preparsedAttrValue = nullptr;
    2446             :   }
    2447             : 
    2448        1816 :   if (aNotify) {
    2449         550 :     nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
    2450         550 :                                      preparsedAttrValue);
    2451             :   }
    2452             : 
    2453             :   // Hold a script blocker while calling ParseAttribute since that can call
    2454             :   // out to id-observers
    2455        1816 :   nsIDocument* document = GetComposedDoc();
    2456        3632 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
    2457             : 
    2458        1816 :   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
    2459        1816 :   NS_ENSURE_SUCCESS(rv, rv);
    2460             : 
    2461        3542 :   if (!preparsedAttrValue &&
    2462        1726 :       !ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
    2463         466 :     attrValue.SetTo(aValue);
    2464             :   }
    2465             : 
    2466        1816 :   PreIdMaybeChange(aNamespaceID, aName, &value);
    2467             : 
    2468        1816 :   return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
    2469             :                           oldValueSet ? &oldValue : nullptr,
    2470             :                           attrValue, modType, hasListeners, aNotify,
    2471        1816 :                           kCallAfterSetAttr, document, updateBatch);
    2472             : }
    2473             : 
    2474             : nsresult
    2475           0 : Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
    2476             :                        nsIAtom* aPrefix, nsAttrValue& aParsedValue,
    2477             :                        bool aNotify)
    2478             : {
    2479             :   // Keep this in sync with SetAttr above
    2480             : 
    2481           0 :   NS_ENSURE_ARG_POINTER(aName);
    2482           0 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    2483             :                "Don't call SetAttr with unknown namespace");
    2484             : 
    2485           0 :   if (!mAttrsAndChildren.CanFitMoreAttrs()) {
    2486           0 :     return NS_ERROR_FAILURE;
    2487             :   }
    2488             : 
    2489             : 
    2490             :   uint8_t modType;
    2491             :   bool hasListeners;
    2492           0 :   nsAttrValueOrString value(aParsedValue);
    2493           0 :   nsAttrValue oldValue;
    2494             :   bool oldValueSet;
    2495             : 
    2496           0 :   if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
    2497             :                              oldValue, &modType, &hasListeners, &oldValueSet)) {
    2498           0 :     return OnAttrSetButNotChanged(aNamespaceID, aName, value, aNotify);
    2499             :   }
    2500             : 
    2501           0 :   if (aNotify) {
    2502           0 :     nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
    2503           0 :                                      &aParsedValue);
    2504             :   }
    2505             : 
    2506           0 :   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
    2507           0 :   NS_ENSURE_SUCCESS(rv, rv);
    2508             : 
    2509           0 :   PreIdMaybeChange(aNamespaceID, aName, &value);
    2510             : 
    2511           0 :   nsIDocument* document = GetComposedDoc();
    2512           0 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
    2513           0 :   return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
    2514             :                           oldValueSet ? &oldValue : nullptr,
    2515             :                           aParsedValue, modType, hasListeners, aNotify,
    2516           0 :                           kCallAfterSetAttr, document, updateBatch);
    2517             : }
    2518             : 
    2519             : nsresult
    2520        1825 : Element::SetAttrAndNotify(int32_t aNamespaceID,
    2521             :                           nsIAtom* aName,
    2522             :                           nsIAtom* aPrefix,
    2523             :                           const nsAttrValue* aOldValue,
    2524             :                           nsAttrValue& aParsedValue,
    2525             :                           uint8_t aModType,
    2526             :                           bool aFireMutation,
    2527             :                           bool aNotify,
    2528             :                           bool aCallAfterSetAttr,
    2529             :                           nsIDocument* aComposedDocument,
    2530             :                           const mozAutoDocUpdate&)
    2531             : {
    2532             :   nsresult rv;
    2533        1825 :   nsMutationGuard::DidMutate();
    2534             : 
    2535             :   // Copy aParsedValue for later use since it will be lost when we call
    2536             :   // SetAndSwapMappedAttr below
    2537        3650 :   nsAttrValue valueForAfterSetAttr;
    2538        1825 :   if (aCallAfterSetAttr) {
    2539        1816 :     valueForAfterSetAttr.SetTo(aParsedValue);
    2540             :   }
    2541             : 
    2542        1825 :   bool hadValidDir = false;
    2543        1825 :   bool hadDirAuto = false;
    2544             :   bool oldValueSet;
    2545             : 
    2546        1825 :   if (aNamespaceID == kNameSpaceID_None) {
    2547        1742 :     if (aName == nsGkAtoms::dir) {
    2548           0 :       hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
    2549           0 :       hadDirAuto = HasDirAuto(); // already takes bdi into account
    2550             :     }
    2551             : 
    2552             :     // XXXbz Perhaps we should push up the attribute mapping function
    2553             :     // stuff to Element?
    2554        1865 :     if (!IsAttributeMapped(aName) ||
    2555         123 :         !SetAndSwapMappedAttribute(aName, aParsedValue, &oldValueSet, &rv)) {
    2556        1716 :       rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
    2557             :     }
    2558             :   }
    2559             :   else {
    2560         166 :     RefPtr<mozilla::dom::NodeInfo> ni;
    2561         166 :     ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
    2562             :                                                    aNamespaceID,
    2563          83 :                                                    nsIDOMNode::ATTRIBUTE_NODE);
    2564             : 
    2565          83 :     rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue, &oldValueSet);
    2566             :   }
    2567        1825 :   NS_ENSURE_SUCCESS(rv, rv);
    2568             : 
    2569        1825 :   PostIdMaybeChange(aNamespaceID, aName, &valueForAfterSetAttr);
    2570             : 
    2571             :   // If the old value owns its own data, we know it is OK to keep using it.
    2572             :   // oldValue will be null if there was no previously set value
    2573             :   const nsAttrValue* oldValue;
    2574        1825 :   if (aParsedValue.StoresOwnData()) {
    2575        1820 :     if (oldValueSet) {
    2576          78 :       oldValue = &aParsedValue;
    2577             :     } else {
    2578        1742 :       oldValue = nullptr;
    2579             :     }
    2580             :   } else {
    2581             :     // No need to conditionally assign null here. If there was no previously
    2582             :     // set value for the attribute, aOldValue will already be null.
    2583           5 :     oldValue = aOldValue;
    2584             :   }
    2585             : 
    2586        1825 :   if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    2587        1638 :     RefPtr<nsXBLBinding> binding = GetXBLBinding();
    2588         819 :     if (binding) {
    2589         210 :       binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
    2590             :     }
    2591             :   }
    2592             : 
    2593        1825 :   nsIDocument* ownerDoc = OwnerDoc();
    2594        1825 :   if (ownerDoc && GetCustomElementData()) {
    2595           0 :     nsCOMPtr<nsIAtom> oldValueAtom;
    2596           0 :     if (oldValue) {
    2597           0 :       oldValueAtom = oldValue->GetAsAtom();
    2598             :     } else {
    2599             :       // If there is no old value, get the value of the uninitialized attribute
    2600             :       // that was swapped with aParsedValue.
    2601           0 :       oldValueAtom = aParsedValue.GetAsAtom();
    2602             :     }
    2603           0 :     nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
    2604             :     LifecycleCallbackArgs args = {
    2605           0 :       nsDependentAtomString(aName),
    2606             :       aModType == nsIDOMMutationEvent::ADDITION ?
    2607           0 :         NullString() : nsDependentAtomString(oldValueAtom),
    2608           0 :       nsDependentAtomString(newValueAtom)
    2609           0 :     };
    2610             : 
    2611             :     nsContentUtils::EnqueueLifecycleCallback(
    2612           0 :       ownerDoc, nsIDocument::eAttributeChanged, this, &args);
    2613             :   }
    2614             : 
    2615        1825 :   if (aCallAfterSetAttr) {
    2616        1816 :     rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, oldValue,
    2617        1816 :                       aNotify);
    2618        1816 :     NS_ENSURE_SUCCESS(rv, rv);
    2619             : 
    2620        1816 :     if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
    2621           0 :       OnSetDirAttr(this, &valueForAfterSetAttr,
    2622           0 :                    hadValidDir, hadDirAuto, aNotify);
    2623             :     }
    2624             :   }
    2625             : 
    2626        1825 :   UpdateState(aNotify);
    2627             : 
    2628        1825 :   if (aNotify) {
    2629             :     // Don't pass aOldValue to AttributeChanged since it may not be reliable.
    2630             :     // Callers only compute aOldValue under certain conditions which may not
    2631             :     // be triggered by all nsIMutationObservers.
    2632         555 :     nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType,
    2633        1110 :         aParsedValue.StoresOwnData() ? &aParsedValue : nullptr);
    2634             :   }
    2635             : 
    2636        1825 :   if (aFireMutation) {
    2637           0 :     InternalMutationEvent mutation(true, eLegacyAttrModified);
    2638             : 
    2639           0 :     nsAutoString ns;
    2640           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
    2641             :     Attr* attrNode =
    2642           0 :       GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
    2643           0 :     mutation.mRelatedNode = attrNode;
    2644             : 
    2645           0 :     mutation.mAttrName = aName;
    2646           0 :     nsAutoString newValue;
    2647           0 :     GetAttr(aNamespaceID, aName, newValue);
    2648           0 :     if (!newValue.IsEmpty()) {
    2649           0 :       mutation.mNewAttrValue = NS_Atomize(newValue);
    2650             :     }
    2651           0 :     if (oldValue && !oldValue->IsEmptyString()) {
    2652           0 :       mutation.mPrevAttrValue = oldValue->GetAsAtom();
    2653             :     }
    2654           0 :     mutation.mAttrChange = aModType;
    2655             : 
    2656           0 :     mozAutoSubtreeModified subtree(OwnerDoc(), this);
    2657           0 :     (new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe();
    2658             :   }
    2659             : 
    2660        1825 :   return NS_OK;
    2661             : }
    2662             : 
    2663             : bool
    2664        1498 : Element::ParseAttribute(int32_t aNamespaceID,
    2665             :                         nsIAtom* aAttribute,
    2666             :                         const nsAString& aValue,
    2667             :                         nsAttrValue& aResult)
    2668             : {
    2669        1498 :   if (aAttribute == nsGkAtoms::lang) {
    2670           0 :     aResult.ParseAtom(aValue);
    2671           0 :     return true;
    2672             :   }
    2673             : 
    2674        1498 :   if (aNamespaceID == kNameSpaceID_None) {
    2675        1438 :     MOZ_ASSERT(aAttribute != nsGkAtoms::_class,
    2676             :                "The class attribute should be preparsed and therefore should "
    2677             :                "never be passed to Element::ParseAttribute");
    2678        1438 :     if (aAttribute == nsGkAtoms::id) {
    2679             :       // Store id as an atom.  id="" means that the element has no id,
    2680             :       // not that it has an emptystring as the id.
    2681         116 :       if (aValue.IsEmpty()) {
    2682           0 :         return false;
    2683             :       }
    2684         116 :       aResult.ParseAtom(aValue);
    2685         116 :       return true;
    2686             :     }
    2687             :   }
    2688             : 
    2689        1382 :   return false;
    2690             : }
    2691             : 
    2692             : bool
    2693          97 : Element::SetAndSwapMappedAttribute(nsIAtom* aName,
    2694             :                                    nsAttrValue& aValue,
    2695             :                                    bool* aValueWasSet,
    2696             :                                    nsresult* aRetval)
    2697             : {
    2698          97 :   *aRetval = NS_OK;
    2699          97 :   return false;
    2700             : }
    2701             : 
    2702             : nsresult
    2703        1952 : Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
    2704             :                        const nsAttrValueOrString* aValue, bool aNotify)
    2705             : {
    2706        1952 :   if (aNamespaceID == kNameSpaceID_None) {
    2707        1869 :     if (aName == nsGkAtoms::_class) {
    2708          90 :       if (aValue) {
    2709             :         // Note: This flag is asymmetrical. It is never unset and isn't exact.
    2710             :         // If it is ever made to be exact, we probably need to handle this
    2711             :         // similarly to how ids are handled in PreIdMaybeChange and
    2712             :         // PostIdMaybeChange.
    2713          90 :         SetMayHaveClass();
    2714             :       }
    2715             :     }
    2716             :   }
    2717             : 
    2718        1952 :   return NS_OK;
    2719             : }
    2720             : 
    2721             : void
    2722        1952 : Element::PreIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
    2723             :                           const nsAttrValueOrString* aValue)
    2724             : {
    2725        1952 :   if (aNamespaceID != kNameSpaceID_None || aName != nsGkAtoms::id) {
    2726        1832 :     return;
    2727             :   }
    2728         120 :   RemoveFromIdTable();
    2729             : 
    2730         120 :   return;
    2731             : }
    2732             : 
    2733             : void
    2734        1961 : Element::PostIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
    2735             :                            const nsAttrValue* aValue)
    2736             : {
    2737        1961 :   if (aNamespaceID != kNameSpaceID_None || aName != nsGkAtoms::id) {
    2738        1841 :     return;
    2739             :   }
    2740             : 
    2741             :   // id="" means that the element has no id, not that it has an empty
    2742             :   // string as the id.
    2743         120 :   if (aValue && !aValue->IsEmptyString()) {
    2744         116 :     SetHasID();
    2745         116 :     AddToIdTable(aValue->GetAtomValue());
    2746             :   } else {
    2747           4 :     ClearHasID();
    2748             :   }
    2749             : 
    2750         120 :   return;
    2751             : }
    2752             : 
    2753             : EventListenerManager*
    2754         551 : Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
    2755             :                                         bool* aDefer)
    2756             : {
    2757         551 :   *aDefer = true;
    2758         551 :   return GetOrCreateListenerManager();
    2759             : }
    2760             : 
    2761             : BorrowedAttrInfo
    2762         666 : Element::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const
    2763             : {
    2764         666 :   NS_ASSERTION(nullptr != aName, "must have attribute name");
    2765         666 :   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
    2766             :                "must have a real namespace ID!");
    2767             : 
    2768         666 :   int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
    2769         666 :   if (index < 0) {
    2770         523 :     return BorrowedAttrInfo(nullptr, nullptr);
    2771             :   }
    2772             : 
    2773         143 :   return mAttrsAndChildren.AttrInfoAt(index);
    2774             : }
    2775             : 
    2776             : BorrowedAttrInfo
    2777         242 : Element::GetAttrInfoAt(uint32_t aIndex) const
    2778             : {
    2779         242 :   if (aIndex >= mAttrsAndChildren.AttrCount()) {
    2780         150 :     return BorrowedAttrInfo(nullptr, nullptr);
    2781             :   }
    2782             : 
    2783          92 :   return mAttrsAndChildren.AttrInfoAt(aIndex);
    2784             : }
    2785             : 
    2786             : bool
    2787       21268 : Element::GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    2788             :                  nsAString& aResult) const
    2789             : {
    2790       42536 :   DOMString str;
    2791       21268 :   bool haveAttr = GetAttr(aNameSpaceID, aName, str);
    2792       21268 :   str.ToString(aResult);
    2793       42536 :   return haveAttr;
    2794             : }
    2795             : 
    2796             : int32_t
    2797        6184 : Element::FindAttrValueIn(int32_t aNameSpaceID,
    2798             :                          nsIAtom* aName,
    2799             :                          AttrValuesArray* aValues,
    2800             :                          nsCaseTreatment aCaseSensitive) const
    2801             : {
    2802        6184 :   NS_ASSERTION(aName, "Must have attr name");
    2803        6184 :   NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
    2804        6184 :   NS_ASSERTION(aValues, "Null value array");
    2805             : 
    2806        6184 :   const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
    2807        6184 :   if (val) {
    2808         859 :     for (int32_t i = 0; aValues[i]; ++i) {
    2809         710 :       if (val->Equals(*aValues[i], aCaseSensitive)) {
    2810         175 :         return i;
    2811             :       }
    2812             :     }
    2813         149 :     return ATTR_VALUE_NO_MATCH;
    2814             :   }
    2815        5860 :   return ATTR_MISSING;
    2816             : }
    2817             : 
    2818             : nsresult
    2819         172 : Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    2820             :                    bool aNotify)
    2821             : {
    2822         172 :   NS_ASSERTION(nullptr != aName, "must have attribute name");
    2823             : 
    2824         172 :   int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
    2825         172 :   if (index < 0) {
    2826          36 :     return NS_OK;
    2827             :   }
    2828             : 
    2829         136 :   nsIDocument *document = GetComposedDoc();
    2830         272 :   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
    2831             : 
    2832         136 :   if (aNotify) {
    2833             :     nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
    2834             :                                      nsIDOMMutationEvent::REMOVAL,
    2835          40 :                                      nullptr);
    2836             :   }
    2837             : 
    2838         136 :   nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
    2839         136 :   NS_ENSURE_SUCCESS(rv, rv);
    2840             : 
    2841         176 :   bool hasMutationListeners = aNotify &&
    2842          40 :     nsContentUtils::HasMutationListeners(this,
    2843             :                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
    2844         136 :                                          this);
    2845             : 
    2846         136 :   PreIdMaybeChange(aNameSpaceID, aName, nullptr);
    2847             : 
    2848             :   // Grab the attr node if needed before we remove it from the attr map
    2849         272 :   RefPtr<Attr> attrNode;
    2850         136 :   if (hasMutationListeners) {
    2851           0 :     nsAutoString ns;
    2852           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
    2853           0 :     attrNode = GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
    2854             :   }
    2855             : 
    2856             :   // Clear binding to nsIDOMMozNamedAttrMap
    2857         136 :   nsDOMSlots *slots = GetExistingDOMSlots();
    2858         136 :   if (slots && slots->mAttributeMap) {
    2859           0 :     slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
    2860             :   }
    2861             : 
    2862             :   // The id-handling code, and in the future possibly other code, need to
    2863             :   // react to unexpected attribute changes.
    2864         136 :   nsMutationGuard::DidMutate();
    2865             : 
    2866         136 :   bool hadValidDir = false;
    2867         136 :   bool hadDirAuto = false;
    2868             : 
    2869         136 :   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
    2870           0 :     hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
    2871           0 :     hadDirAuto = HasDirAuto(); // already takes bdi into account
    2872             :   }
    2873             : 
    2874         272 :   nsAttrValue oldValue;
    2875         136 :   rv = mAttrsAndChildren.RemoveAttrAt(index, oldValue);
    2876         136 :   NS_ENSURE_SUCCESS(rv, rv);
    2877             : 
    2878         136 :   PostIdMaybeChange(aNameSpaceID, aName, nullptr);
    2879             : 
    2880         136 :   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
    2881          88 :     RefPtr<nsXBLBinding> binding = GetXBLBinding();
    2882          44 :     if (binding) {
    2883          17 :       binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
    2884             :     }
    2885             :   }
    2886             : 
    2887         136 :   nsIDocument* ownerDoc = OwnerDoc();
    2888         136 :   if (ownerDoc && GetCustomElementData()) {
    2889           0 :     nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
    2890             :     LifecycleCallbackArgs args = {
    2891           0 :       nsDependentAtomString(aName),
    2892           0 :       nsDependentAtomString(oldValueAtom),
    2893           0 :       NullString()
    2894           0 :     };
    2895             : 
    2896             :     nsContentUtils::EnqueueLifecycleCallback(
    2897           0 :       ownerDoc, nsIDocument::eAttributeChanged, this, &args);
    2898             :   }
    2899             : 
    2900         136 :   rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, aNotify);
    2901         136 :   NS_ENSURE_SUCCESS(rv, rv);
    2902             : 
    2903         136 :   UpdateState(aNotify);
    2904             : 
    2905         136 :   if (aNotify) {
    2906             :     // We can always pass oldValue here since there is no new value which could
    2907             :     // have corrupted it.
    2908             :     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
    2909          40 :                                   nsIDOMMutationEvent::REMOVAL, &oldValue);
    2910             :   }
    2911             : 
    2912         136 :   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
    2913           0 :     OnSetDirAttr(this, nullptr, hadValidDir, hadDirAuto, aNotify);
    2914             :   }
    2915             : 
    2916         136 :   if (hasMutationListeners) {
    2917           0 :     InternalMutationEvent mutation(true, eLegacyAttrModified);
    2918             : 
    2919           0 :     mutation.mRelatedNode = attrNode;
    2920           0 :     mutation.mAttrName = aName;
    2921             : 
    2922           0 :     nsAutoString value;
    2923           0 :     oldValue.ToString(value);
    2924           0 :     if (!value.IsEmpty())
    2925           0 :       mutation.mPrevAttrValue = NS_Atomize(value);
    2926           0 :     mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
    2927             : 
    2928           0 :     mozAutoSubtreeModified subtree(OwnerDoc(), this);
    2929           0 :     (new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe();
    2930             :   }
    2931             : 
    2932         136 :   return NS_OK;
    2933             : }
    2934             : 
    2935             : const nsAttrName*
    2936         322 : Element::GetAttrNameAt(uint32_t aIndex) const
    2937             : {
    2938         322 :   return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
    2939             : }
    2940             : 
    2941             : uint32_t
    2942          94 : Element::GetAttrCount() const
    2943             : {
    2944          94 :   return mAttrsAndChildren.AttrCount();
    2945             : }
    2946             : 
    2947             : void
    2948           0 : Element::DescribeAttribute(uint32_t index, nsAString& aOutDescription) const
    2949             : {
    2950             :   // name
    2951           0 :   mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(aOutDescription);
    2952             : 
    2953             :   // value
    2954           0 :   aOutDescription.AppendLiteral("=\"");
    2955           0 :   nsAutoString value;
    2956           0 :   mAttrsAndChildren.AttrAt(index)->ToString(value);
    2957           0 :   for (uint32_t i = value.Length(); i > 0; --i) {
    2958           0 :     if (value[i - 1] == char16_t('"'))
    2959           0 :       value.Insert(char16_t('\\'), i - 1);
    2960             :   }
    2961           0 :   aOutDescription.Append(value);
    2962           0 :   aOutDescription.Append('"');
    2963           0 : }
    2964             : 
    2965             : #ifdef DEBUG
    2966             : void
    2967           0 : Element::ListAttributes(FILE* out) const
    2968             : {
    2969           0 :   uint32_t index, count = mAttrsAndChildren.AttrCount();
    2970           0 :   for (index = 0; index < count; index++) {
    2971           0 :     nsAutoString attributeDescription;
    2972           0 :     DescribeAttribute(index, attributeDescription);
    2973             : 
    2974           0 :     fputs(" ", out);
    2975           0 :     fputs(NS_LossyConvertUTF16toASCII(attributeDescription).get(), out);
    2976             :   }
    2977           0 : }
    2978             : 
    2979             : void
    2980           0 : Element::List(FILE* out, int32_t aIndent,
    2981             :               const nsCString& aPrefix) const
    2982             : {
    2983             :   int32_t indent;
    2984           0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    2985             : 
    2986           0 :   fputs(aPrefix.get(), out);
    2987             : 
    2988           0 :   fputs(NS_LossyConvertUTF16toASCII(mNodeInfo->QualifiedName()).get(), out);
    2989             : 
    2990           0 :   fprintf(out, "@%p", (void *)this);
    2991             : 
    2992           0 :   ListAttributes(out);
    2993             : 
    2994             :   fprintf(out, " state=[%llx]",
    2995           0 :           static_cast<unsigned long long>(State().GetInternalValue()));
    2996           0 :   fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
    2997           0 :   if (IsCommonAncestorForRangeInSelection()) {
    2998             :     nsRange::RangeHashTable* ranges =
    2999           0 :       static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
    3000           0 :     fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
    3001             :   }
    3002           0 :   fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
    3003           0 :   fprintf(out, " refcount=%" PRIuPTR "<", mRefCnt.get());
    3004             : 
    3005           0 :   nsIContent* child = GetFirstChild();
    3006           0 :   if (child) {
    3007           0 :     fputs("\n", out);
    3008             : 
    3009           0 :     for (; child; child = child->GetNextSibling()) {
    3010           0 :       child->List(out, aIndent + 1);
    3011             :     }
    3012             : 
    3013           0 :     for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3014             :   }
    3015             : 
    3016           0 :   fputs(">\n", out);
    3017             : 
    3018           0 :   Element* nonConstThis = const_cast<Element*>(this);
    3019             : 
    3020             :   // XXX sXBL/XBL2 issue! Owner or current document?
    3021           0 :   nsIDocument *document = OwnerDoc();
    3022             : 
    3023             :   // Note: not listing nsIAnonymousContentCreator-created content...
    3024             : 
    3025           0 :   nsBindingManager* bindingManager = document->BindingManager();
    3026           0 :   nsCOMPtr<nsIDOMNodeList> anonymousChildren;
    3027           0 :   bindingManager->GetAnonymousNodesFor(nonConstThis,
    3028           0 :                                        getter_AddRefs(anonymousChildren));
    3029             : 
    3030           0 :   if (anonymousChildren) {
    3031           0 :     uint32_t length = 0;
    3032           0 :     anonymousChildren->GetLength(&length);
    3033             : 
    3034           0 :     for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3035           0 :     fputs("anonymous-children<\n", out);
    3036             : 
    3037           0 :     for (uint32_t i = 0; i < length; ++i) {
    3038           0 :       nsCOMPtr<nsIDOMNode> node;
    3039           0 :       anonymousChildren->Item(i, getter_AddRefs(node));
    3040           0 :       nsCOMPtr<nsIContent> child = do_QueryInterface(node);
    3041           0 :       child->List(out, aIndent + 1);
    3042             :     }
    3043             : 
    3044           0 :     for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3045           0 :     fputs(">\n", out);
    3046             : 
    3047           0 :     bool outHeader = false;
    3048           0 :     ExplicitChildIterator iter(nonConstThis);
    3049           0 :     for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
    3050           0 :       if (!outHeader) {
    3051           0 :         outHeader = true;
    3052             : 
    3053           0 :         for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3054           0 :         fputs("content-list<\n", out);
    3055             :       }
    3056             : 
    3057           0 :       child->List(out, aIndent + 1);
    3058             :     }
    3059             : 
    3060           0 :     if (outHeader) {
    3061           0 :       for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3062           0 :       fputs(">\n", out);
    3063             :     }
    3064             :   }
    3065           0 : }
    3066             : 
    3067             : void
    3068           0 : Element::DumpContent(FILE* out, int32_t aIndent,
    3069             :                      bool aDumpAll) const
    3070             : {
    3071             :   int32_t indent;
    3072           0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3073             : 
    3074           0 :   const nsString& buf = mNodeInfo->QualifiedName();
    3075           0 :   fputs("<", out);
    3076           0 :   fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
    3077             : 
    3078           0 :   if(aDumpAll) ListAttributes(out);
    3079             : 
    3080           0 :   fputs(">", out);
    3081             : 
    3082           0 :   if(aIndent) fputs("\n", out);
    3083             : 
    3084           0 :   for (nsIContent* child = GetFirstChild();
    3085           0 :        child;
    3086           0 :        child = child->GetNextSibling()) {
    3087           0 :     int32_t indent = aIndent ? aIndent + 1 : 0;
    3088           0 :     child->DumpContent(out, indent, aDumpAll);
    3089             :   }
    3090           0 :   for (indent = aIndent; --indent >= 0; ) fputs("  ", out);
    3091           0 :   fputs("</", out);
    3092           0 :   fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
    3093           0 :   fputs(">", out);
    3094             : 
    3095           0 :   if(aIndent) fputs("\n", out);
    3096           0 : }
    3097             : #endif
    3098             : 
    3099             : void
    3100           0 : Element::Describe(nsAString& aOutDescription) const
    3101             : {
    3102           0 :   aOutDescription.Append(mNodeInfo->QualifiedName());
    3103           0 :   aOutDescription.AppendPrintf("@%p", (void *)this);
    3104             : 
    3105           0 :   uint32_t index, count = mAttrsAndChildren.AttrCount();
    3106           0 :   for (index = 0; index < count; index++) {
    3107           0 :     aOutDescription.Append(' ');
    3108           0 :     nsAutoString attributeDescription;
    3109           0 :     DescribeAttribute(index, attributeDescription);
    3110           0 :     aOutDescription.Append(attributeDescription);
    3111             :   }
    3112           0 : }
    3113             : 
    3114             : bool
    3115           0 : Element::CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
    3116             :                                               nsIURI** aURI) const
    3117             : {
    3118           0 :   if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
    3119           0 :       (!aVisitor.mEvent->IsTrusted() &&
    3120           0 :        (aVisitor.mEvent->mMessage != eMouseClick) &&
    3121           0 :        (aVisitor.mEvent->mMessage != eKeyPress) &&
    3122           0 :        (aVisitor.mEvent->mMessage != eLegacyDOMActivate)) ||
    3123           0 :       !aVisitor.mPresContext ||
    3124           0 :       aVisitor.mEvent->mFlags.mMultipleActionsPrevented) {
    3125           0 :     return false;
    3126             :   }
    3127             : 
    3128             :   // Make sure we actually are a link
    3129           0 :   return IsLink(aURI);
    3130             : }
    3131             : 
    3132             : nsresult
    3133           0 : Element::GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor)
    3134             : {
    3135             :   // Optimisation: return early if this event doesn't interest us.
    3136             :   // IMPORTANT: this switch and the switch below it must be kept in sync!
    3137           0 :   switch (aVisitor.mEvent->mMessage) {
    3138             :   case eMouseOver:
    3139             :   case eFocus:
    3140             :   case eMouseOut:
    3141             :   case eBlur:
    3142           0 :     break;
    3143             :   default:
    3144           0 :     return NS_OK;
    3145             :   }
    3146             : 
    3147             :   // Make sure we meet the preconditions before continuing
    3148           0 :   nsCOMPtr<nsIURI> absURI;
    3149           0 :   if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
    3150           0 :     return NS_OK;
    3151             :   }
    3152             : 
    3153           0 :   nsresult rv = NS_OK;
    3154             : 
    3155             :   // We do the status bar updates in GetEventTargetParent so that the status bar
    3156             :   // gets updated even if the event is consumed before we have a chance to set
    3157             :   // it.
    3158           0 :   switch (aVisitor.mEvent->mMessage) {
    3159             :   // Set the status bar similarly for mouseover and focus
    3160             :   case eMouseOver:
    3161           0 :     aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    3162             :     MOZ_FALLTHROUGH;
    3163             :   case eFocus: {
    3164           0 :     InternalFocusEvent* focusEvent = aVisitor.mEvent->AsFocusEvent();
    3165           0 :     if (!focusEvent || !focusEvent->mIsRefocus) {
    3166           0 :       nsAutoString target;
    3167           0 :       GetLinkTarget(target);
    3168           0 :       nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
    3169           0 :                                   false, true, true);
    3170             :       // Make sure any ancestor links don't also TriggerLink
    3171           0 :       aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
    3172             :     }
    3173           0 :     break;
    3174             :   }
    3175             :   case eMouseOut:
    3176           0 :     aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    3177             :     MOZ_FALLTHROUGH;
    3178             :   case eBlur:
    3179           0 :     rv = LeaveLink(aVisitor.mPresContext);
    3180           0 :     if (NS_SUCCEEDED(rv)) {
    3181           0 :       aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
    3182             :     }
    3183           0 :     break;
    3184             : 
    3185             :   default:
    3186             :     // switch not in sync with the optimization switch earlier in this function
    3187           0 :     NS_NOTREACHED("switch statements not in sync");
    3188           0 :     return NS_ERROR_UNEXPECTED;
    3189             :   }
    3190             : 
    3191           0 :   return rv;
    3192             : }
    3193             : 
    3194             : nsresult
    3195           0 : Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor)
    3196             : {
    3197             :   // Optimisation: return early if this event doesn't interest us.
    3198             :   // IMPORTANT: this switch and the switch below it must be kept in sync!
    3199           0 :   switch (aVisitor.mEvent->mMessage) {
    3200             :   case eMouseDown:
    3201             :   case eMouseClick:
    3202             :   case eLegacyDOMActivate:
    3203             :   case eKeyPress:
    3204           0 :     break;
    3205             :   default:
    3206           0 :     return NS_OK;
    3207             :   }
    3208             : 
    3209             :   // Make sure we meet the preconditions before continuing
    3210           0 :   nsCOMPtr<nsIURI> absURI;
    3211           0 :   if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
    3212           0 :     return NS_OK;
    3213             :   }
    3214             : 
    3215           0 :   nsresult rv = NS_OK;
    3216             : 
    3217           0 :   switch (aVisitor.mEvent->mMessage) {
    3218             :   case eMouseDown:
    3219             :     {
    3220           0 :       if (aVisitor.mEvent->AsMouseEvent()->button ==
    3221             :             WidgetMouseEvent::eLeftButton) {
    3222             :         // don't make the link grab the focus if there is no link handler
    3223           0 :         nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
    3224           0 :         nsIDocument *document = GetComposedDoc();
    3225           0 :         if (handler && document) {
    3226           0 :           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    3227           0 :           if (fm) {
    3228           0 :             aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
    3229           0 :             nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
    3230           0 :             fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
    3231           0 :                                nsIFocusManager::FLAG_NOSCROLL);
    3232             :           }
    3233             : 
    3234           0 :           EventStateManager::SetActiveManager(
    3235           0 :             aVisitor.mPresContext->EventStateManager(), this);
    3236             : 
    3237             :           // OK, we're pretty sure we're going to load, so warm up a speculative
    3238             :           // connection to be sure we have one ready when we open the channel.
    3239             :           nsCOMPtr<nsISpeculativeConnect> sc =
    3240           0 :             do_QueryInterface(nsContentUtils::GetIOService());
    3241           0 :           nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(handler);
    3242           0 :           sc->SpeculativeConnect2(absURI, NodePrincipal(), ir);
    3243             :         }
    3244             :       }
    3245             :     }
    3246           0 :     break;
    3247             : 
    3248             :   case eMouseClick: {
    3249           0 :     WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
    3250           0 :     if (mouseEvent->IsLeftClickEvent()) {
    3251           0 :       if (mouseEvent->IsControl() || mouseEvent->IsMeta() ||
    3252           0 :           mouseEvent->IsAlt() ||mouseEvent->IsShift()) {
    3253           0 :         break;
    3254             :       }
    3255             : 
    3256             :       // The default action is simply to dispatch DOMActivate
    3257           0 :       nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
    3258           0 :       if (shell) {
    3259             :         // single-click
    3260           0 :         nsEventStatus status = nsEventStatus_eIgnore;
    3261             :         // DOMActive event should be trusted since the activation is actually
    3262             :         // occurred even if the cause is an untrusted click event.
    3263           0 :         InternalUIEvent actEvent(true, eLegacyDOMActivate, mouseEvent);
    3264           0 :         actEvent.mDetail = 1;
    3265             : 
    3266           0 :         rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
    3267           0 :         if (NS_SUCCEEDED(rv)) {
    3268           0 :           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    3269             :         }
    3270             :       }
    3271             :     }
    3272           0 :     break;
    3273             :   }
    3274             :   case eLegacyDOMActivate:
    3275             :     {
    3276           0 :       if (aVisitor.mEvent->mOriginalTarget == this) {
    3277           0 :         nsAutoString target;
    3278           0 :         GetLinkTarget(target);
    3279           0 :         const InternalUIEvent* activeEvent = aVisitor.mEvent->AsUIEvent();
    3280           0 :         MOZ_ASSERT(activeEvent);
    3281           0 :         nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
    3282           0 :                                     true, true, activeEvent->IsTrustable());
    3283           0 :         aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    3284             :       }
    3285             :     }
    3286           0 :     break;
    3287             : 
    3288             :   case eKeyPress:
    3289             :     {
    3290           0 :       WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
    3291           0 :       if (keyEvent && keyEvent->mKeyCode == NS_VK_RETURN) {
    3292           0 :         nsEventStatus status = nsEventStatus_eIgnore;
    3293           0 :         rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
    3294           0 :                                 false, nullptr, &status);
    3295           0 :         if (NS_SUCCEEDED(rv)) {
    3296           0 :           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
    3297             :         }
    3298             :       }
    3299             :     }
    3300           0 :     break;
    3301             : 
    3302             :   default:
    3303             :     // switch not in sync with the optimization switch earlier in this function
    3304           0 :     NS_NOTREACHED("switch statements not in sync");
    3305           0 :     return NS_ERROR_UNEXPECTED;
    3306             :   }
    3307             : 
    3308           0 :   return rv;
    3309             : }
    3310             : 
    3311             : void
    3312           0 : Element::GetLinkTarget(nsAString& aTarget)
    3313             : {
    3314           0 :   aTarget.Truncate();
    3315           0 : }
    3316             : 
    3317             : static void
    3318           0 : nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
    3319             :                                  void *aPropertyValue, void *aData)
    3320             : {
    3321             :   nsDOMTokenList* list =
    3322           0 :     static_cast<nsDOMTokenList*>(aPropertyValue);
    3323           0 :   NS_RELEASE(list);
    3324           0 : }
    3325             : 
    3326             : static nsIAtom** sPropertiesToTraverseAndUnlink[] =
    3327             :   {
    3328             :     &nsGkAtoms::sandbox,
    3329             :     &nsGkAtoms::sizes,
    3330             :     &nsGkAtoms::dirAutoSetBy,
    3331             :     nullptr
    3332             :   };
    3333             : 
    3334             : // static
    3335             : nsIAtom***
    3336           0 : Element::HTMLSVGPropertiesToTraverseAndUnlink()
    3337             : {
    3338           0 :   return sPropertiesToTraverseAndUnlink;
    3339             : }
    3340             : 
    3341             : nsDOMTokenList*
    3342           0 : Element::GetTokenList(nsIAtom* aAtom,
    3343             :                       const DOMTokenListSupportedTokenArray aSupportedTokens)
    3344             : {
    3345             : #ifdef DEBUG
    3346             :   nsIAtom*** props =
    3347           0 :     HTMLSVGPropertiesToTraverseAndUnlink();
    3348           0 :   bool found = false;
    3349           0 :   for (uint32_t i = 0; props[i]; ++i) {
    3350           0 :     if (*props[i] == aAtom) {
    3351           0 :       found = true;
    3352           0 :       break;
    3353             :     }
    3354             :   }
    3355           0 :   MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
    3356             : #endif
    3357             : 
    3358           0 :   nsDOMTokenList* list = nullptr;
    3359           0 :   if (HasProperties()) {
    3360           0 :     list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
    3361             :   }
    3362           0 :   if (!list) {
    3363           0 :     list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
    3364           0 :     NS_ADDREF(list);
    3365           0 :     SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
    3366             :   }
    3367           0 :   return list;
    3368             : }
    3369             : 
    3370             : Element*
    3371           0 : Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
    3372             : {
    3373           0 :   nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
    3374           0 :   if (!selectorList) {
    3375             :     // Either we failed (and aResult already has the exception), or this
    3376             :     // is a pseudo-element-only selector that matches nothing.
    3377           0 :     return nullptr;
    3378             :   }
    3379             :   TreeMatchContext matchingContext(false,
    3380             :                                    nsRuleWalker::eRelevantLinkUnvisited,
    3381             :                                    OwnerDoc(),
    3382           0 :                                    TreeMatchContext::eNeverMatchVisited);
    3383           0 :   matchingContext.SetHasSpecifiedScope();
    3384           0 :   matchingContext.AddScopeElement(this);
    3385           0 :   for (nsINode* node = this; node; node = node->GetParentNode()) {
    3386           0 :     if (node->IsElement() &&
    3387           0 :         nsCSSRuleProcessor::SelectorListMatches(node->AsElement(),
    3388             :                                                 matchingContext,
    3389             :                                                 selectorList)) {
    3390           0 :       return node->AsElement();
    3391             :     }
    3392             :   }
    3393           0 :   return nullptr;
    3394             : }
    3395             : 
    3396             : bool
    3397           0 : Element::Matches(const nsAString& aSelector, ErrorResult& aError)
    3398             : {
    3399           0 :   nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError);
    3400           0 :   if (!selectorList) {
    3401             :     // Either we failed (and aError already has the exception), or this
    3402             :     // is a pseudo-element-only selector that matches nothing.
    3403           0 :     return false;
    3404             :   }
    3405             : 
    3406             :   TreeMatchContext matchingContext(false,
    3407             :                                    nsRuleWalker::eRelevantLinkUnvisited,
    3408             :                                    OwnerDoc(),
    3409           0 :                                    TreeMatchContext::eNeverMatchVisited);
    3410           0 :   matchingContext.SetHasSpecifiedScope();
    3411           0 :   matchingContext.AddScopeElement(this);
    3412             :   return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
    3413           0 :                                                  selectorList);
    3414             : }
    3415             : 
    3416             : static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
    3417             :   // Order matters here
    3418             :   // See ParseCORSValue
    3419             :   { "anonymous",       CORS_ANONYMOUS       },
    3420             :   { "use-credentials", CORS_USE_CREDENTIALS },
    3421             :   { nullptr,           0 }
    3422             : };
    3423             : 
    3424             : /* static */ void
    3425           0 : Element::ParseCORSValue(const nsAString& aValue,
    3426             :                         nsAttrValue& aResult)
    3427             : {
    3428             :   DebugOnly<bool> success =
    3429           0 :     aResult.ParseEnumValue(aValue, kCORSAttributeTable, false,
    3430             :                            // default value is anonymous if aValue is
    3431             :                            // not a value we understand
    3432           0 :                            &kCORSAttributeTable[0]);
    3433           0 :   MOZ_ASSERT(success);
    3434           0 : }
    3435             : 
    3436             : /* static */ CORSMode
    3437           4 : Element::StringToCORSMode(const nsAString& aValue)
    3438             : {
    3439           4 :   if (aValue.IsVoid()) {
    3440           4 :     return CORS_NONE;
    3441             :   }
    3442             : 
    3443           0 :   nsAttrValue val;
    3444           0 :   Element::ParseCORSValue(aValue, val);
    3445           0 :   return CORSMode(val.GetEnumValue());
    3446             : }
    3447             : 
    3448             : /* static */ CORSMode
    3449           8 : Element::AttrValueToCORSMode(const nsAttrValue* aValue)
    3450             : {
    3451           8 :   if (!aValue) {
    3452           8 :     return CORS_NONE;
    3453             :   }
    3454             : 
    3455           0 :   return CORSMode(aValue->GetEnumValue());
    3456             : }
    3457             : 
    3458             : static const char*
    3459           0 : GetFullScreenError(CallerType aCallerType)
    3460             : {
    3461           0 :   if (!nsContentUtils::IsRequestFullScreenAllowed(aCallerType)) {
    3462           0 :     return "FullscreenDeniedNotInputDriven";
    3463             :   }
    3464             : 
    3465           0 :   return nullptr;
    3466             : }
    3467             : 
    3468             : void
    3469           0 : Element::RequestFullscreen(CallerType aCallerType, ErrorResult& aError)
    3470             : {
    3471             :   // Only grant full-screen requests if this is called from inside a trusted
    3472             :   // event handler (i.e. inside an event handler for a user initiated event).
    3473             :   // This stops the full-screen from being abused similar to the popups of old,
    3474             :   // and it also makes it harder for bad guys' script to go full-screen and
    3475             :   // spoof the browser chrome/window and phish logins etc.
    3476             :   // Note that requests for fullscreen inside a web app's origin are exempt
    3477             :   // from this restriction.
    3478           0 :   if (const char* error = GetFullScreenError(aCallerType)) {
    3479           0 :     OwnerDoc()->DispatchFullscreenError(error);
    3480           0 :     return;
    3481             :   }
    3482             : 
    3483           0 :   auto request = MakeUnique<FullscreenRequest>(this);
    3484           0 :   request->mIsCallerChrome = (aCallerType == CallerType::System);
    3485             : 
    3486           0 :   OwnerDoc()->AsyncRequestFullScreen(Move(request));
    3487             : }
    3488             : 
    3489             : void
    3490           0 : Element::RequestPointerLock(CallerType aCallerType)
    3491             : {
    3492           0 :   OwnerDoc()->RequestPointerLock(this, aCallerType);
    3493           0 : }
    3494             : 
    3495             : void
    3496           0 : Element::GetGridFragments(nsTArray<RefPtr<Grid>>& aResult)
    3497             : {
    3498             :   nsGridContainerFrame* frame =
    3499           0 :     nsGridContainerFrame::GetGridFrameWithComputedInfo(GetPrimaryFrame());
    3500             : 
    3501             :   // If we get a nsGridContainerFrame from the prior call,
    3502             :   // all the next-in-flow frames will also be nsGridContainerFrames.
    3503           0 :   while (frame) {
    3504           0 :     aResult.AppendElement(
    3505           0 :       new Grid(this, frame)
    3506           0 :     );
    3507           0 :     frame = static_cast<nsGridContainerFrame*>(frame->GetNextInFlow());
    3508             :   }
    3509           0 : }
    3510             : 
    3511             : already_AddRefed<DOMMatrixReadOnly>
    3512           0 : Element::GetTransformToAncestor(Element& aAncestor)
    3513             : {
    3514           0 :   nsIFrame* primaryFrame = GetPrimaryFrame();
    3515           0 :   nsIFrame* ancestorFrame = aAncestor.GetPrimaryFrame();
    3516             : 
    3517           0 :   Matrix4x4 transform;
    3518           0 :   if (primaryFrame) {
    3519             :     // If aAncestor is not actually an ancestor of this (including nullptr),
    3520             :     // then the call to GetTransformToAncestor will return the transform
    3521             :     // all the way up through the parent chain.
    3522           0 :     transform = nsLayoutUtils::GetTransformToAncestor(primaryFrame,
    3523             :       ancestorFrame, true);
    3524             :   }
    3525             : 
    3526           0 :   DOMMatrixReadOnly* matrix = new DOMMatrix(this, transform);
    3527           0 :   RefPtr<DOMMatrixReadOnly> result(matrix);
    3528           0 :   return result.forget();
    3529             : }
    3530             : 
    3531             : already_AddRefed<DOMMatrixReadOnly>
    3532           0 : Element::GetTransformToParent()
    3533             : {
    3534           0 :   nsIFrame* primaryFrame = GetPrimaryFrame();
    3535             : 
    3536           0 :   Matrix4x4 transform;
    3537           0 :   if (primaryFrame) {
    3538           0 :     nsIFrame* parentFrame = primaryFrame->GetParent();
    3539           0 :     transform = nsLayoutUtils::GetTransformToAncestor(primaryFrame,
    3540             :       parentFrame, true);
    3541             :   }
    3542             : 
    3543           0 :   DOMMatrixReadOnly* matrix = new DOMMatrix(this, transform);
    3544           0 :   RefPtr<DOMMatrixReadOnly> result(matrix);
    3545           0 :   return result.forget();
    3546             : }
    3547             : 
    3548             : already_AddRefed<DOMMatrixReadOnly>
    3549           0 : Element::GetTransformToViewport()
    3550             : {
    3551           0 :   nsIFrame* primaryFrame = GetPrimaryFrame();
    3552           0 :   Matrix4x4 transform;
    3553           0 :   if (primaryFrame) {
    3554           0 :     transform = nsLayoutUtils::GetTransformToAncestor(primaryFrame,
    3555           0 :       nsLayoutUtils::GetDisplayRootFrame(primaryFrame), true);
    3556             :   }
    3557             : 
    3558           0 :   DOMMatrixReadOnly* matrix = new DOMMatrix(this, transform);
    3559           0 :   RefPtr<DOMMatrixReadOnly> result(matrix);
    3560           0 :   return result.forget();
    3561             : }
    3562             : 
    3563             : already_AddRefed<Animation>
    3564           0 : Element::Animate(JSContext* aContext,
    3565             :                  JS::Handle<JSObject*> aKeyframes,
    3566             :                  const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
    3567             :                  ErrorResult& aError)
    3568             : {
    3569           0 :   Nullable<ElementOrCSSPseudoElement> target;
    3570           0 :   target.SetValue().SetAsElement() = this;
    3571           0 :   return Animate(target, aContext, aKeyframes, aOptions, aError);
    3572             : }
    3573             : 
    3574             : /* static */ already_AddRefed<Animation>
    3575           0 : Element::Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
    3576             :                  JSContext* aContext,
    3577             :                  JS::Handle<JSObject*> aKeyframes,
    3578             :                  const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
    3579             :                  ErrorResult& aError)
    3580             : {
    3581           0 :   MOZ_ASSERT(!aTarget.IsNull() &&
    3582             :              (aTarget.Value().IsElement() ||
    3583             :               aTarget.Value().IsCSSPseudoElement()),
    3584             :              "aTarget should be initialized");
    3585             : 
    3586           0 :   RefPtr<Element> referenceElement;
    3587           0 :   if (aTarget.Value().IsElement()) {
    3588           0 :     referenceElement = &aTarget.Value().GetAsElement();
    3589             :   } else {
    3590           0 :     referenceElement = aTarget.Value().GetAsCSSPseudoElement().ParentElement();
    3591             :   }
    3592             : 
    3593           0 :   nsCOMPtr<nsIGlobalObject> ownerGlobal = referenceElement->GetOwnerGlobal();
    3594           0 :   if (!ownerGlobal) {
    3595           0 :     aError.Throw(NS_ERROR_FAILURE);
    3596           0 :     return nullptr;
    3597             :   }
    3598           0 :   GlobalObject global(aContext, ownerGlobal->GetGlobalJSObject());
    3599           0 :   MOZ_ASSERT(!global.Failed());
    3600             : 
    3601             :   // Wrap the aKeyframes object for the cross-compartment case.
    3602           0 :   JS::Rooted<JSObject*> keyframes(aContext);
    3603           0 :   keyframes = aKeyframes;
    3604           0 :   Maybe<JSAutoCompartment> ac;
    3605           0 :   if (js::GetContextCompartment(aContext) !=
    3606           0 :       js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
    3607           0 :     ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
    3608           0 :     if (!JS_WrapObject(aContext, &keyframes)) {
    3609           0 :       return nullptr;
    3610             :     }
    3611             :   }
    3612             : 
    3613             :   RefPtr<KeyframeEffect> effect =
    3614           0 :     KeyframeEffect::Constructor(global, aTarget, keyframes, aOptions, aError);
    3615           0 :   if (aError.Failed()) {
    3616           0 :     return nullptr;
    3617             :   }
    3618             : 
    3619           0 :   AnimationTimeline* timeline = referenceElement->OwnerDoc()->Timeline();
    3620             :   RefPtr<Animation> animation =
    3621           0 :     Animation::Constructor(global, effect,
    3622           0 :                            Optional<AnimationTimeline*>(timeline), aError);
    3623           0 :   if (aError.Failed()) {
    3624           0 :     return nullptr;
    3625             :   }
    3626             : 
    3627           0 :   if (aOptions.IsKeyframeAnimationOptions()) {
    3628           0 :     animation->SetId(aOptions.GetAsKeyframeAnimationOptions().mId);
    3629             :   }
    3630             : 
    3631           0 :   animation->Play(aError, Animation::LimitBehavior::AutoRewind);
    3632           0 :   if (aError.Failed()) {
    3633           0 :     return nullptr;
    3634             :   }
    3635             : 
    3636           0 :   return animation.forget();
    3637             : }
    3638             : 
    3639             : void
    3640           0 : Element::GetAnimations(const AnimationFilter& filter,
    3641             :                        nsTArray<RefPtr<Animation>>& aAnimations)
    3642             : {
    3643           0 :   nsIDocument* doc = GetComposedDoc();
    3644           0 :   if (doc) {
    3645           0 :     doc->FlushPendingNotifications(FlushType::Style);
    3646             :   }
    3647             : 
    3648           0 :   Element* elem = this;
    3649           0 :   CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
    3650             :   // For animations on generated-content elements, the animations are stored
    3651             :   // on the parent element.
    3652           0 :   if (IsGeneratedContentContainerForBefore()) {
    3653           0 :     elem = GetParentElement();
    3654           0 :     pseudoType = CSSPseudoElementType::before;
    3655           0 :   } else if (IsGeneratedContentContainerForAfter()) {
    3656           0 :     elem = GetParentElement();
    3657           0 :     pseudoType = CSSPseudoElementType::after;
    3658             :   }
    3659             : 
    3660           0 :   if (!elem) {
    3661           0 :     return;
    3662             :   }
    3663             : 
    3664           0 :   if (!filter.mSubtree ||
    3665           0 :       pseudoType == CSSPseudoElementType::before ||
    3666             :       pseudoType == CSSPseudoElementType::after) {
    3667           0 :     GetAnimationsUnsorted(elem, pseudoType, aAnimations);
    3668             :   } else {
    3669           0 :     for (nsIContent* node = this;
    3670           0 :          node;
    3671           0 :          node = node->GetNextNode(this)) {
    3672           0 :       if (!node->IsElement()) {
    3673           0 :         continue;
    3674             :       }
    3675           0 :       Element* element = node->AsElement();
    3676             :       Element::GetAnimationsUnsorted(element, CSSPseudoElementType::NotPseudo,
    3677           0 :                                      aAnimations);
    3678             :       Element::GetAnimationsUnsorted(element, CSSPseudoElementType::before,
    3679           0 :                                      aAnimations);
    3680             :       Element::GetAnimationsUnsorted(element, CSSPseudoElementType::after,
    3681           0 :                                      aAnimations);
    3682             :     }
    3683             :   }
    3684           0 :   aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
    3685             : }
    3686             : 
    3687             : /* static */ void
    3688           0 : Element::GetAnimationsUnsorted(Element* aElement,
    3689             :                                CSSPseudoElementType aPseudoType,
    3690             :                                nsTArray<RefPtr<Animation>>& aAnimations)
    3691             : {
    3692           0 :   MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo ||
    3693             :              aPseudoType == CSSPseudoElementType::after ||
    3694             :              aPseudoType == CSSPseudoElementType::before,
    3695             :              "Unsupported pseudo type");
    3696           0 :   MOZ_ASSERT(aElement, "Null element");
    3697             : 
    3698           0 :   EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
    3699           0 :   if (!effects) {
    3700           0 :     return;
    3701             :   }
    3702             : 
    3703           0 :   for (KeyframeEffectReadOnly* effect : *effects) {
    3704           0 :     MOZ_ASSERT(effect && effect->GetAnimation(),
    3705             :                "Only effects associated with an animation should be "
    3706             :                "added to an element's effect set");
    3707           0 :     Animation* animation = effect->GetAnimation();
    3708             : 
    3709           0 :     MOZ_ASSERT(animation->IsRelevant(),
    3710             :                "Only relevant animations should be added to an element's "
    3711             :                "effect set");
    3712           0 :     aAnimations.AppendElement(animation);
    3713             :   }
    3714             : }
    3715             : 
    3716             : NS_IMETHODIMP
    3717           0 : Element::GetInnerHTML(nsAString& aInnerHTML)
    3718             : {
    3719           0 :   GetMarkup(false, aInnerHTML);
    3720           0 :   return NS_OK;
    3721             : }
    3722             : 
    3723             : void
    3724           0 : Element::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
    3725             : {
    3726           0 :   SetInnerHTMLInternal(aInnerHTML, aError);
    3727           0 : }
    3728             : 
    3729             : void
    3730           0 : Element::GetOuterHTML(nsAString& aOuterHTML)
    3731             : {
    3732           0 :   GetMarkup(true, aOuterHTML);
    3733           0 : }
    3734             : 
    3735             : void
    3736           0 : Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError)
    3737             : {
    3738           0 :   nsCOMPtr<nsINode> parent = GetParentNode();
    3739           0 :   if (!parent) {
    3740           0 :     return;
    3741             :   }
    3742             : 
    3743           0 :   if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) {
    3744           0 :     aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    3745           0 :     return;
    3746             :   }
    3747             : 
    3748           0 :   if (OwnerDoc()->IsHTMLDocument()) {
    3749             :     nsIAtom* localName;
    3750             :     int32_t namespaceID;
    3751           0 :     if (parent->IsElement()) {
    3752           0 :       localName = parent->NodeInfo()->NameAtom();
    3753           0 :       namespaceID = parent->NodeInfo()->NamespaceID();
    3754             :     } else {
    3755           0 :       NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
    3756             :         "How come the parent isn't a document, a fragment or an element?");
    3757           0 :       localName = nsGkAtoms::body;
    3758           0 :       namespaceID = kNameSpaceID_XHTML;
    3759             :     }
    3760             :     RefPtr<DocumentFragment> fragment =
    3761           0 :       new DocumentFragment(OwnerDoc()->NodeInfoManager());
    3762           0 :     nsContentUtils::ParseFragmentHTML(aOuterHTML,
    3763             :                                       fragment,
    3764             :                                       localName,
    3765             :                                       namespaceID,
    3766           0 :                                       OwnerDoc()->GetCompatibilityMode() ==
    3767             :                                         eCompatibility_NavQuirks,
    3768           0 :                                       true);
    3769           0 :     parent->ReplaceChild(*fragment, *this, aError);
    3770           0 :     return;
    3771             :   }
    3772             : 
    3773           0 :   nsCOMPtr<nsINode> context;
    3774           0 :   if (parent->IsElement()) {
    3775           0 :     context = parent;
    3776             :   } else {
    3777           0 :     NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
    3778             :       "How come the parent isn't a document, a fragment or an element?");
    3779             :     RefPtr<mozilla::dom::NodeInfo> info =
    3780           0 :       OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body,
    3781             :                                                  nullptr,
    3782             :                                                  kNameSpaceID_XHTML,
    3783           0 :                                                  nsIDOMNode::ELEMENT_NODE);
    3784           0 :     context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT);
    3785             :   }
    3786             : 
    3787           0 :   nsCOMPtr<nsIDOMDocumentFragment> df;
    3788           0 :   aError = nsContentUtils::CreateContextualFragment(context,
    3789             :                                                     aOuterHTML,
    3790             :                                                     true,
    3791           0 :                                                     getter_AddRefs(df));
    3792           0 :   if (aError.Failed()) {
    3793           0 :     return;
    3794             :   }
    3795           0 :   nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
    3796           0 :   parent->ReplaceChild(*fragment, *this, aError);
    3797             : }
    3798             : 
    3799             : enum nsAdjacentPosition {
    3800             :   eBeforeBegin,
    3801             :   eAfterBegin,
    3802             :   eBeforeEnd,
    3803             :   eAfterEnd
    3804             : };
    3805             : 
    3806             : void
    3807           0 : Element::InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
    3808             :                             ErrorResult& aError)
    3809             : {
    3810             :   nsAdjacentPosition position;
    3811           0 :   if (aPosition.LowerCaseEqualsLiteral("beforebegin")) {
    3812           0 :     position = eBeforeBegin;
    3813           0 :   } else if (aPosition.LowerCaseEqualsLiteral("afterbegin")) {
    3814           0 :     position = eAfterBegin;
    3815           0 :   } else if (aPosition.LowerCaseEqualsLiteral("beforeend")) {
    3816           0 :     position = eBeforeEnd;
    3817           0 :   } else if (aPosition.LowerCaseEqualsLiteral("afterend")) {
    3818           0 :     position = eAfterEnd;
    3819             :   } else {
    3820           0 :     aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
    3821           0 :     return;
    3822             :   }
    3823             : 
    3824           0 :   nsCOMPtr<nsIContent> destination;
    3825           0 :   if (position == eBeforeBegin || position == eAfterEnd) {
    3826           0 :     destination = GetParent();
    3827           0 :     if (!destination) {
    3828           0 :       aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
    3829           0 :       return;
    3830             :     }
    3831             :   } else {
    3832           0 :     destination = this;
    3833             :   }
    3834             : 
    3835           0 :   nsIDocument* doc = OwnerDoc();
    3836             : 
    3837             :   // Needed when insertAdjacentHTML is used in combination with contenteditable
    3838           0 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
    3839           0 :   nsAutoScriptLoaderDisabler sld(doc);
    3840             : 
    3841             :   // Batch possible DOMSubtreeModified events.
    3842           0 :   mozAutoSubtreeModified subtree(doc, nullptr);
    3843             : 
    3844             :   // Parse directly into destination if possible
    3845           0 :   if (doc->IsHTMLDocument() && !OwnerDoc()->MayHaveDOMMutationObservers() &&
    3846           0 :       (position == eBeforeEnd ||
    3847           0 :        (position == eAfterEnd && !GetNextSibling()) ||
    3848           0 :        (position == eAfterBegin && !GetFirstChild()))) {
    3849           0 :     int32_t oldChildCount = destination->GetChildCount();
    3850           0 :     int32_t contextNs = destination->GetNameSpaceID();
    3851           0 :     nsIAtom* contextLocal = destination->NodeInfo()->NameAtom();
    3852           0 :     if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) {
    3853             :       // For compat with IE6 through IE9. Willful violation of HTML5 as of
    3854             :       // 2011-04-06. CreateContextualFragment does the same already.
    3855             :       // Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434
    3856           0 :       contextLocal = nsGkAtoms::body;
    3857             :     }
    3858           0 :     aError = nsContentUtils::ParseFragmentHTML(aText,
    3859             :                                                destination,
    3860             :                                                contextLocal,
    3861             :                                                contextNs,
    3862           0 :                                                doc->GetCompatibilityMode() ==
    3863             :                                                  eCompatibility_NavQuirks,
    3864           0 :                                                true);
    3865             :     // HTML5 parser has notified, but not fired mutation events.
    3866           0 :     nsContentUtils::FireMutationEventsForDirectParsing(doc, destination,
    3867           0 :                                                        oldChildCount);
    3868           0 :     return;
    3869             :   }
    3870             : 
    3871             :   // couldn't parse directly
    3872           0 :   nsCOMPtr<nsIDOMDocumentFragment> df;
    3873           0 :   aError = nsContentUtils::CreateContextualFragment(destination,
    3874             :                                                     aText,
    3875             :                                                     true,
    3876           0 :                                                     getter_AddRefs(df));
    3877           0 :   if (aError.Failed()) {
    3878           0 :     return;
    3879             :   }
    3880             : 
    3881           0 :   nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
    3882             : 
    3883             :   // Suppress assertion about node removal mutation events that can't have
    3884             :   // listeners anyway, because no one has had the chance to register mutation
    3885             :   // listeners on the fragment that comes from the parser.
    3886           0 :   nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
    3887             : 
    3888           0 :   nsAutoMutationBatch mb(destination, true, false);
    3889           0 :   switch (position) {
    3890             :     case eBeforeBegin:
    3891           0 :       destination->InsertBefore(*fragment, this, aError);
    3892           0 :       break;
    3893             :     case eAfterBegin:
    3894           0 :       static_cast<nsINode*>(this)->InsertBefore(*fragment, GetFirstChild(),
    3895           0 :                                                 aError);
    3896           0 :       break;
    3897             :     case eBeforeEnd:
    3898           0 :       static_cast<nsINode*>(this)->AppendChild(*fragment, aError);
    3899           0 :       break;
    3900             :     case eAfterEnd:
    3901           0 :       destination->InsertBefore(*fragment, GetNextSibling(), aError);
    3902           0 :       break;
    3903             :   }
    3904             : }
    3905             : 
    3906             : nsINode*
    3907           0 : Element::InsertAdjacent(const nsAString& aWhere,
    3908             :                         nsINode* aNode,
    3909             :                         ErrorResult& aError)
    3910             : {
    3911           0 :   if (aWhere.LowerCaseEqualsLiteral("beforebegin")) {
    3912           0 :     nsCOMPtr<nsINode> parent = GetParentNode();
    3913           0 :     if (!parent) {
    3914           0 :       return nullptr;
    3915             :     }
    3916           0 :     parent->InsertBefore(*aNode, this, aError);
    3917           0 :   } else if (aWhere.LowerCaseEqualsLiteral("afterbegin")) {
    3918           0 :     nsCOMPtr<nsINode> refNode = GetFirstChild();
    3919           0 :     static_cast<nsINode*>(this)->InsertBefore(*aNode, refNode, aError);
    3920           0 :   } else if (aWhere.LowerCaseEqualsLiteral("beforeend")) {
    3921           0 :     static_cast<nsINode*>(this)->AppendChild(*aNode, aError);
    3922           0 :   } else if (aWhere.LowerCaseEqualsLiteral("afterend")) {
    3923           0 :     nsCOMPtr<nsINode> parent = GetParentNode();
    3924           0 :     if (!parent) {
    3925           0 :       return nullptr;
    3926             :     }
    3927           0 :     nsCOMPtr<nsINode> refNode = GetNextSibling();
    3928           0 :     parent->InsertBefore(*aNode, refNode, aError);
    3929             :   } else {
    3930           0 :     aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
    3931           0 :     return nullptr;
    3932             :   }
    3933             : 
    3934           0 :   return aError.Failed() ? nullptr : aNode;
    3935             : }
    3936             : 
    3937             : Element*
    3938           0 : Element::InsertAdjacentElement(const nsAString& aWhere,
    3939             :                                Element& aElement,
    3940             :                                ErrorResult& aError) {
    3941           0 :   nsINode* newNode = InsertAdjacent(aWhere, &aElement, aError);
    3942           0 :   MOZ_ASSERT(!newNode || newNode->IsElement());
    3943             : 
    3944           0 :   return newNode ? newNode->AsElement() : nullptr;
    3945             : }
    3946             : 
    3947             : void
    3948           0 : Element::InsertAdjacentText(
    3949             :   const nsAString& aWhere, const nsAString& aData, ErrorResult& aError)
    3950             : {
    3951           0 :   RefPtr<nsTextNode> textNode = OwnerDoc()->CreateTextNode(aData);
    3952           0 :   InsertAdjacent(aWhere, textNode, aError);
    3953           0 : }
    3954             : 
    3955             : TextEditor*
    3956           0 : Element::GetTextEditorInternal()
    3957             : {
    3958           0 :   nsCOMPtr<nsITextControlElement> textCtrl = do_QueryInterface(this);
    3959           0 :   return textCtrl ? textCtrl->GetTextEditor() : nullptr;
    3960             : }
    3961             : 
    3962             : nsresult
    3963           0 : Element::SetBoolAttr(nsIAtom* aAttr, bool aValue)
    3964             : {
    3965           0 :   if (aValue) {
    3966           0 :     return SetAttr(kNameSpaceID_None, aAttr, EmptyString(), true);
    3967             :   }
    3968             : 
    3969           0 :   return UnsetAttr(kNameSpaceID_None, aAttr, true);
    3970             : }
    3971             : 
    3972             : void
    3973           0 : Element::GetEnumAttr(nsIAtom* aAttr,
    3974             :                      const char* aDefault,
    3975             :                      nsAString& aResult) const
    3976             : {
    3977           0 :   GetEnumAttr(aAttr, aDefault, aDefault, aResult);
    3978           0 : }
    3979             : 
    3980             : void
    3981           0 : Element::GetEnumAttr(nsIAtom* aAttr,
    3982             :                      const char* aDefaultMissing,
    3983             :                      const char* aDefaultInvalid,
    3984             :                      nsAString& aResult) const
    3985             : {
    3986           0 :   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
    3987             : 
    3988           0 :   aResult.Truncate();
    3989             : 
    3990           0 :   if (!attrVal) {
    3991           0 :     if (aDefaultMissing) {
    3992           0 :       AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult);
    3993             :     } else {
    3994           0 :       SetDOMStringToNull(aResult);
    3995             :     }
    3996             :   } else {
    3997           0 :     if (attrVal->Type() == nsAttrValue::eEnum) {
    3998           0 :       attrVal->GetEnumString(aResult, true);
    3999           0 :     } else if (aDefaultInvalid) {
    4000           0 :       AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
    4001             :     }
    4002             :   }
    4003           0 : }
    4004             : 
    4005             : void
    4006           0 : Element::SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue,
    4007             :                                        ErrorResult& aError)
    4008             : {
    4009           0 :   if (DOMStringIsNull(aValue)) {
    4010           0 :     UnsetAttr(aName, aError);
    4011             :   } else {
    4012           0 :     SetAttr(aName, aValue, aError);
    4013             :   }
    4014           0 : }
    4015             : 
    4016             : Directionality
    4017           0 : Element::GetComputedDirectionality() const
    4018             : {
    4019           0 :   nsIFrame* frame = GetPrimaryFrame();
    4020           0 :   if (frame) {
    4021           0 :     return frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR
    4022           0 :              ? eDir_LTR : eDir_RTL;
    4023             :   }
    4024             : 
    4025           0 :   return GetDirectionality();
    4026             : }
    4027             : 
    4028             : float
    4029           0 : Element::FontSizeInflation()
    4030             : {
    4031           0 :   nsIFrame* frame = GetPrimaryFrame();
    4032           0 :   if (!frame) {
    4033           0 :     return -1.0;
    4034             :   }
    4035             : 
    4036           0 :   if (nsLayoutUtils::FontSizeInflationEnabled(frame->PresContext())) {
    4037           0 :     return nsLayoutUtils::FontSizeInflationFor(frame);
    4038             :   }
    4039             : 
    4040           0 :   return 1.0;
    4041             : }
    4042             : 
    4043             : net::ReferrerPolicy
    4044           4 : Element::GetReferrerPolicyAsEnum()
    4045             : {
    4046           4 :   if (IsHTMLElement()) {
    4047           4 :     const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrerpolicy);
    4048           4 :     return ReferrerPolicyFromAttr(referrerValue);
    4049             :   }
    4050           0 :   return net::RP_Unset;
    4051             : }
    4052             : 
    4053             : net::ReferrerPolicy
    4054           4 : Element::ReferrerPolicyFromAttr(const nsAttrValue* aValue)
    4055             : {
    4056           4 :   if (aValue && aValue->Type() == nsAttrValue::eEnum) {
    4057           0 :     return net::ReferrerPolicy(aValue->GetEnumValue());
    4058             :   }
    4059           4 :   return net::RP_Unset;
    4060             : }
    4061             : 
    4062             : already_AddRefed<nsDOMStringMap>
    4063           0 : Element::Dataset()
    4064             : {
    4065           0 :   nsDOMSlots *slots = DOMSlots();
    4066             : 
    4067           0 :   if (!slots->mDataset) {
    4068             :     // mDataset is a weak reference so assignment will not AddRef.
    4069             :     // AddRef is called before returning the pointer.
    4070           0 :     slots->mDataset = new nsDOMStringMap(this);
    4071             :   }
    4072             : 
    4073           0 :   RefPtr<nsDOMStringMap> ret = slots->mDataset;
    4074           0 :   return ret.forget();
    4075             : }
    4076             : 
    4077             : void
    4078           0 : Element::ClearDataset()
    4079             : {
    4080           0 :   nsDOMSlots *slots = GetExistingDOMSlots();
    4081             : 
    4082           0 :   MOZ_ASSERT(slots && slots->mDataset,
    4083             :              "Slots should exist and dataset should not be null.");
    4084           0 :   slots->mDataset = nullptr;
    4085           0 : }
    4086             : 
    4087             : nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>*
    4088           0 : Element::RegisteredIntersectionObservers()
    4089             : {
    4090           0 :   nsDOMSlots* slots = DOMSlots();
    4091           0 :   return &slots->mRegisteredIntersectionObservers;
    4092             : }
    4093             : 
    4094             : enum nsPreviousIntersectionThreshold {
    4095             :   eUninitialized = -2,
    4096             :   eNonIntersecting = -1
    4097             : };
    4098             : 
    4099             : void
    4100           0 : Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
    4101             : {
    4102           0 :   RegisteredIntersectionObservers()->LookupForAdd(aObserver).OrInsert([]() {
    4103             :     // Value can be:
    4104             :     //   -2:   Makes sure next calculated threshold always differs, leading to a
    4105             :     //         notification task being scheduled.
    4106             :     //   -1:   Non-intersecting.
    4107             :     //   >= 0: Intersecting, valid index of aObserver->mThresholds.
    4108             :     return eUninitialized;
    4109           0 :   });
    4110           0 : }
    4111             : 
    4112             : void
    4113           0 : Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
    4114             : {
    4115           0 :   RegisteredIntersectionObservers()->Remove(aObserver);
    4116           0 : }
    4117             : 
    4118             : bool
    4119           0 : Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
    4120             : {
    4121           0 :   bool updated = false;
    4122           0 :   if (auto entry = RegisteredIntersectionObservers()->Lookup(aObserver)) {
    4123           0 :     updated = entry.Data() != aThreshold;
    4124           0 :     entry.Data() = aThreshold;
    4125             :   }
    4126           0 :   return updated;
    4127             : }
    4128             : 
    4129             : void
    4130           0 : Element::ClearServoData() {
    4131             : #ifdef MOZ_STYLO
    4132             :   Servo_Element_ClearData(this);
    4133             : #else
    4134           0 :   MOZ_CRASH("Accessing servo node data in non-stylo build");
    4135             : #endif
    4136             : }
    4137             : 
    4138             : void
    4139           0 : Element::SetCustomElementData(CustomElementData* aData)
    4140             : {
    4141           0 :   nsDOMSlots *slots = DOMSlots();
    4142           0 :   MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
    4143           0 :   slots->mCustomElementData = aData;
    4144           0 : }

Generated by: LCOV version 1.13