LCOV - code coverage report
Current view: top level - dom/base - FragmentOrElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 381 1121 34.0 %
Date: 2017-07-14 16:53:18 Functions: 69 135 51.1 %
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/ArrayUtils.h"
      14             : #include "mozilla/Likely.h"
      15             : #include "mozilla/MemoryReporting.h"
      16             : #include "mozilla/StaticPtr.h"
      17             : 
      18             : #include "mozilla/dom/FragmentOrElement.h"
      19             : 
      20             : #include "mozilla/AsyncEventDispatcher.h"
      21             : #include "mozilla/DeclarationBlockInlines.h"
      22             : #include "mozilla/EffectSet.h"
      23             : #include "mozilla/EventDispatcher.h"
      24             : #include "mozilla/EventListenerManager.h"
      25             : #include "mozilla/EventStates.h"
      26             : #include "mozilla/ServoRestyleManager.h"
      27             : #include "mozilla/TextEditor.h"
      28             : #include "mozilla/URLExtraData.h"
      29             : #include "mozilla/dom/Attr.h"
      30             : #include "nsDOMAttributeMap.h"
      31             : #include "nsIAtom.h"
      32             : #include "mozilla/dom/NodeInfo.h"
      33             : #include "mozilla/dom/Event.h"
      34             : #include "nsIDocumentInlines.h"
      35             : #include "nsIDocumentEncoder.h"
      36             : #include "nsIDOMNodeList.h"
      37             : #include "nsIContentIterator.h"
      38             : #include "nsFocusManager.h"
      39             : #include "nsILinkHandler.h"
      40             : #include "nsIScriptGlobalObject.h"
      41             : #include "nsIURL.h"
      42             : #include "nsNetUtil.h"
      43             : #include "nsIFrame.h"
      44             : #include "nsIAnonymousContentCreator.h"
      45             : #include "nsIPresShell.h"
      46             : #include "nsPresContext.h"
      47             : #include "nsStyleConsts.h"
      48             : #include "nsString.h"
      49             : #include "nsUnicharUtils.h"
      50             : #include "nsIDOMEvent.h"
      51             : #include "nsDOMCID.h"
      52             : #include "nsIServiceManager.h"
      53             : #include "nsIDOMCSSStyleDeclaration.h"
      54             : #include "nsDOMCSSAttrDeclaration.h"
      55             : #include "nsNameSpaceManager.h"
      56             : #include "nsContentList.h"
      57             : #include "nsDOMTokenList.h"
      58             : #include "nsXBLPrototypeBinding.h"
      59             : #include "nsError.h"
      60             : #include "nsDOMString.h"
      61             : #include "nsIScriptSecurityManager.h"
      62             : #include "nsIDOMMutationEvent.h"
      63             : #include "mozilla/InternalMutationEvent.h"
      64             : #include "mozilla/MouseEvents.h"
      65             : #include "nsNodeUtils.h"
      66             : #include "nsDocument.h"
      67             : #include "nsAttrValueOrString.h"
      68             : #ifdef MOZ_XUL
      69             : #include "nsXULElement.h"
      70             : #endif /* MOZ_XUL */
      71             : #include "nsFrameSelection.h"
      72             : #ifdef DEBUG
      73             : #include "nsRange.h"
      74             : #endif
      75             : 
      76             : #include "nsBindingManager.h"
      77             : #include "nsXBLBinding.h"
      78             : #include "nsPIDOMWindow.h"
      79             : #include "nsPIBoxObject.h"
      80             : #include "nsSVGUtils.h"
      81             : #include "nsLayoutUtils.h"
      82             : #include "nsGkAtoms.h"
      83             : #include "nsContentUtils.h"
      84             : #include "nsTextFragment.h"
      85             : #include "nsContentCID.h"
      86             : 
      87             : #include "nsIDOMEventListener.h"
      88             : #include "nsIWebNavigation.h"
      89             : #include "nsIBaseWindow.h"
      90             : #include "nsIWidget.h"
      91             : 
      92             : #include "js/GCAPI.h"
      93             : 
      94             : #include "nsNodeInfoManager.h"
      95             : #include "nsICategoryManager.h"
      96             : #include "nsGenericHTMLElement.h"
      97             : #include "nsContentCreatorFunctions.h"
      98             : #include "nsIControllers.h"
      99             : #include "nsView.h"
     100             : #include "nsViewManager.h"
     101             : #include "nsIScrollableFrame.h"
     102             : #include "ChildIterator.h"
     103             : #include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
     104             : #include "nsRuleProcessorData.h"
     105             : #include "nsTextNode.h"
     106             : #include "mozilla/dom/NodeListBinding.h"
     107             : 
     108             : #ifdef MOZ_XUL
     109             : #include "nsIXULDocument.h"
     110             : #endif /* MOZ_XUL */
     111             : 
     112             : #include "nsCCUncollectableMarker.h"
     113             : 
     114             : #include "mozAutoDocUpdate.h"
     115             : 
     116             : #include "mozilla/Sprintf.h"
     117             : #include "nsDOMMutationObserver.h"
     118             : #include "nsWrapperCacheInlines.h"
     119             : #include "nsCycleCollector.h"
     120             : #include "xpcpublic.h"
     121             : #include "nsIScriptError.h"
     122             : #include "mozilla/Telemetry.h"
     123             : 
     124             : #include "mozilla/CORSMode.h"
     125             : 
     126             : #include "mozilla/dom/ShadowRoot.h"
     127             : #include "mozilla/dom/HTMLTemplateElement.h"
     128             : #include "mozilla/dom/SVGUseElement.h"
     129             : 
     130             : #include "nsStyledElement.h"
     131             : #include "nsIContentInlines.h"
     132             : #include "nsChildContentList.h"
     133             : 
     134             : using namespace mozilla;
     135             : using namespace mozilla::dom;
     136             : 
     137             : int32_t nsIContent::sTabFocusModel = eTabFocus_any;
     138             : bool nsIContent::sTabFocusModelAppliesToXUL = false;
     139             : uint64_t nsMutationGuard::sGeneration = 0;
     140             : 
     141             : nsIContent*
     142           0 : nsIContent::FindFirstNonChromeOnlyAccessContent() const
     143             : {
     144             :   // This handles also nested native anonymous content.
     145           0 :   for (const nsIContent *content = this; content;
     146           0 :        content = content->GetBindingParent()) {
     147           0 :     if (!content->ChromeOnlyAccess()) {
     148             :       // Oops, this function signature allows casting const to
     149             :       // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
     150           0 :       return const_cast<nsIContent*>(content);
     151             :     }
     152             :   }
     153           0 :   return nullptr;
     154             : }
     155             : 
     156             : nsINode*
     157        4363 : nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const
     158             : {
     159        4363 :   nsINode* parentNode = GetParentNode();
     160        4363 :   if (!parentNode || !parentNode->IsContent()) {
     161         448 :     MOZ_ASSERT(!parentNode || parentNode == OwnerDoc());
     162         448 :     return parentNode;
     163             :   }
     164        3915 :   nsIContent* parent = parentNode->AsContent();
     165             : 
     166        3915 :   if (aType == eForStyle &&
     167        3915 :       IsRootOfNativeAnonymousSubtree() &&
     168           0 :       OwnerDoc()->GetRootElement() == parent) {
     169             :     // First, check if this is generated ::before/::after content for the root.
     170             :     // If it is, we know what to do.
     171           0 :     if (IsGeneratedContentContainerForBefore() ||
     172           0 :         IsGeneratedContentContainerForAfter()) {
     173           0 :       return parent;
     174             :     }
     175             : 
     176             :     // When getting the flattened tree parent for style, we return null
     177             :     // for any "document level" native anonymous content subtree root.
     178             :     // This is NAC generated by an ancestor frame of the document element's
     179             :     // primary frame, and includes scrollbar elements created by the root
     180             :     // scroll frame, and the "custom content container" and accessible caret
     181             :     // generated by the nsCanvasFrame.  We distinguish document level NAC
     182             :     // from NAC generated by the root element's primary frame below.
     183           0 :     nsIFrame* parentFrame = parent->GetPrimaryFrame();
     184           0 :     if (!parentFrame) {
     185             :       // If the root element has no primary frame, it means it can't have
     186             :       // generated any NAC itself.  Thus any NAC we have here must have
     187             :       // been generated by an ancestor frame.
     188             :       //
     189             :       // If we are in here, then either the root element is display:none, or
     190             :       // we are in the middle of constructing the root of the frame tree and
     191             :       // we are trying to eagerly restyle document level NAC in
     192             :       // nsCSSFrameConstructor::GetAnonymousContent before the root
     193             :       // element's frame has been constructed.
     194           0 :       return nullptr;
     195             :     }
     196           0 :     nsIAnonymousContentCreator* creator = do_QueryFrame(parentFrame);
     197           0 :     if (!creator) {
     198             :       // If the root element does have a frame, but does not implement
     199             :       // nsIAnonymousContentCreator, then this must be document level NAC.
     200           0 :       return nullptr;
     201             :     }
     202           0 :     AutoTArray<nsIContent*, 8> elements;
     203           0 :     creator->AppendAnonymousContentTo(elements, 0);
     204           0 :     if (!elements.Contains(this)) {
     205             :       // If the root element does have a frame, and also does implement
     206             :       // nsIAnonymousContentCreator, but didn't create this node, then
     207             :       // it must be document level NAC.
     208           0 :       return nullptr;
     209             :     }
     210             :   }
     211             : 
     212        3915 :   if (parent && nsContentUtils::HasDistributedChildren(parent) &&
     213           0 :       nsContentUtils::IsInSameAnonymousTree(parent, this)) {
     214             :     // This node is distributed to insertion points, thus we
     215             :     // need to consult the destination insertion points list to
     216             :     // figure out where this node was inserted in the flattened tree.
     217             :     // It may be the case that |parent| distributes its children
     218             :     // but the child does not match any insertion points, thus
     219             :     // the flattened tree parent is nullptr.
     220           0 :     nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
     221           0 :     parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ?
     222           0 :       destInsertionPoints->LastElement()->GetParent() : nullptr;
     223        3915 :   } else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
     224        3915 :     nsIContent* insertionParent = GetXBLInsertionParent();
     225        3915 :     if (insertionParent) {
     226         989 :       parent = insertionParent;
     227             :     }
     228             :   }
     229             : 
     230             :   // Shadow roots never shows up in the flattened tree. Return the host
     231             :   // instead.
     232        3915 :   if (parent && parent->IsInShadowTree()) {
     233           0 :     ShadowRoot* parentShadowRoot = ShadowRoot::FromNode(parent);
     234           0 :     if (parentShadowRoot) {
     235           0 :       return parentShadowRoot->GetHost();
     236             :     }
     237             :   }
     238             : 
     239        3915 :   return parent;
     240             : }
     241             : 
     242             : nsIContent::IMEState
     243           0 : nsIContent::GetDesiredIMEState()
     244             : {
     245           0 :   if (!IsEditableInternal()) {
     246             :     // Check for the special case where we're dealing with elements which don't
     247             :     // have the editable flag set, but are readwrite (such as text controls).
     248           0 :     if (!IsElement() ||
     249           0 :         !AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
     250           0 :       return IMEState(IMEState::DISABLED);
     251             :     }
     252             :   }
     253             :   // NOTE: The content for independent editors (e.g., input[type=text],
     254             :   // textarea) must override this method, so, we don't need to worry about
     255             :   // that here.
     256           0 :   nsIContent *editableAncestor = GetEditingHost();
     257             : 
     258             :   // This is in another editable content, use the result of it.
     259           0 :   if (editableAncestor && editableAncestor != this) {
     260           0 :     return editableAncestor->GetDesiredIMEState();
     261             :   }
     262           0 :   nsIDocument* doc = GetComposedDoc();
     263           0 :   if (!doc) {
     264           0 :     return IMEState(IMEState::DISABLED);
     265             :   }
     266           0 :   nsIPresShell* ps = doc->GetShell();
     267           0 :   if (!ps) {
     268           0 :     return IMEState(IMEState::DISABLED);
     269             :   }
     270           0 :   nsPresContext* pc = ps->GetPresContext();
     271           0 :   if (!pc) {
     272           0 :     return IMEState(IMEState::DISABLED);
     273             :   }
     274           0 :   nsIEditor* editor = nsContentUtils::GetHTMLEditor(pc);
     275           0 :   if (!editor) {
     276           0 :     return IMEState(IMEState::DISABLED);
     277             :   }
     278           0 :   IMEState state;
     279           0 :   editor->GetPreferredIMEState(&state);
     280           0 :   return state;
     281             : }
     282             : 
     283             : bool
     284           0 : nsIContent::HasIndependentSelection()
     285             : {
     286           0 :   nsIFrame* frame = GetPrimaryFrame();
     287           0 :   return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
     288             : }
     289             : 
     290             : dom::Element*
     291           0 : nsIContent::GetEditingHost()
     292             : {
     293             :   // If this isn't editable, return nullptr.
     294           0 :   if (!IsEditableInternal()) {
     295           0 :     return nullptr;
     296             :   }
     297             : 
     298           0 :   nsIDocument* doc = GetComposedDoc();
     299           0 :   if (!doc) {
     300           0 :     return nullptr;
     301             :   }
     302             : 
     303             :   // If this is in designMode, we should return <body>
     304           0 :   if (doc->HasFlag(NODE_IS_EDITABLE) && !IsInShadowTree()) {
     305           0 :     return doc->GetBodyElement();
     306             :   }
     307             : 
     308           0 :   nsIContent* content = this;
     309           0 :   for (dom::Element* parent = GetParentElement();
     310           0 :        parent && parent->HasFlag(NODE_IS_EDITABLE);
     311           0 :        parent = content->GetParentElement()) {
     312           0 :     content = parent;
     313             :   }
     314           0 :   return content->AsElement();
     315             : }
     316             : 
     317             : nsresult
     318           2 : nsIContent::LookupNamespaceURIInternal(const nsAString& aNamespacePrefix,
     319             :                                        nsAString& aNamespaceURI) const
     320             : {
     321           2 :   if (aNamespacePrefix.EqualsLiteral("xml")) {
     322             :     // Special-case for xml prefix
     323           0 :     aNamespaceURI.AssignLiteral("http://www.w3.org/XML/1998/namespace");
     324           0 :     return NS_OK;
     325             :   }
     326             : 
     327           2 :   if (aNamespacePrefix.EqualsLiteral("xmlns")) {
     328             :     // Special-case for xmlns prefix
     329           0 :     aNamespaceURI.AssignLiteral("http://www.w3.org/2000/xmlns/");
     330           0 :     return NS_OK;
     331             :   }
     332             : 
     333           4 :   nsCOMPtr<nsIAtom> name;
     334           2 :   if (!aNamespacePrefix.IsEmpty()) {
     335           2 :     name = NS_Atomize(aNamespacePrefix);
     336           2 :     NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
     337             :   }
     338             :   else {
     339           0 :     name = nsGkAtoms::xmlns;
     340             :   }
     341             :   // Trace up the content parent chain looking for the namespace
     342             :   // declaration that declares aNamespacePrefix.
     343           2 :   const nsIContent* content = this;
     344           3 :   do {
     345           4 :     if (content->GetAttr(kNameSpaceID_XMLNS, name, aNamespaceURI))
     346           1 :       return NS_OK;
     347           3 :   } while ((content = content->GetParent()));
     348           1 :   return NS_ERROR_FAILURE;
     349             : }
     350             : 
     351             : nsIAtom*
     352           0 : nsIContent::GetLang() const
     353             : {
     354           0 :   for (const auto* content = this; content; content = content->GetParent()) {
     355           0 :     if (!content->GetAttrCount() || !content->IsElement()) {
     356           0 :       continue;
     357             :     }
     358             : 
     359           0 :     auto* element = content->AsElement();
     360             : 
     361             :     // xml:lang has precedence over lang on HTML elements (see
     362             :     // XHTML1 section C.7).
     363             :     const nsAttrValue* attr =
     364           0 :       element->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
     365           0 :     if (!attr && element->SupportsLangAttr()) {
     366           0 :       attr = element->GetParsedAttr(nsGkAtoms::lang);
     367             :     }
     368           0 :     if (attr) {
     369           0 :       MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom);
     370           0 :       MOZ_ASSERT(attr->GetAtomValue());
     371           0 :       return attr->GetAtomValue();
     372             :     }
     373             :   }
     374             : 
     375           0 :   return nullptr;
     376             : }
     377             : 
     378             : already_AddRefed<nsIURI>
     379         301 : nsIContent::GetBaseURI(bool aTryUseXHRDocBaseURI) const
     380             : {
     381         301 :   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     382          46 :     nsIContent* bindingParent = GetBindingParent();
     383          46 :     MOZ_ASSERT(bindingParent);
     384          46 :     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
     385             :     // XXX Ignore xml:base as we are removing it.
     386          46 :     return do_AddRef(useElement->GetContentURLData()->BaseURI());
     387             :   }
     388             : 
     389         255 :   nsIDocument* doc = OwnerDoc();
     390             :   // Start with document base
     391         510 :   nsCOMPtr<nsIURI> base = doc->GetBaseURI(aTryUseXHRDocBaseURI);
     392             : 
     393             :   // Collect array of xml:base attribute values up the parent chain. This
     394             :   // is slightly slower for the case when there are xml:base attributes, but
     395             :   // faster for the far more common case of there not being any such
     396             :   // attributes.
     397             :   // Also check for SVG elements which require special handling
     398         510 :   AutoTArray<nsString, 5> baseAttrs;
     399         510 :   nsString attr;
     400         255 :   const nsIContent *elem = this;
     401         631 :   do {
     402             :     // First check for SVG specialness (why is this SVG specific?)
     403         886 :     if (elem->IsSVGElement()) {
     404         603 :       nsIContent* bindingParent = elem->GetBindingParent();
     405         603 :       if (bindingParent) {
     406           0 :         nsXBLBinding* binding = bindingParent->GetXBLBinding();
     407           0 :         if (binding) {
     408             :           // XXX sXBL/XBL2 issue
     409             :           // If this is an anonymous XBL element use the binding
     410             :           // document for the base URI.
     411             :           // XXX Will fail with xml:base
     412           0 :           base = binding->PrototypeBinding()->DocURI();
     413           0 :           break;
     414             :         }
     415             :       }
     416             :     }
     417             : 
     418             :     // Otherwise check for xml:base attribute
     419         886 :     elem->GetAttr(kNameSpaceID_XML, nsGkAtoms::base, attr);
     420         886 :     if (!attr.IsEmpty()) {
     421           0 :       baseAttrs.AppendElement(attr);
     422             :     }
     423         886 :     elem = elem->GetParent();
     424         886 :   } while(elem);
     425             : 
     426         255 :   if (!baseAttrs.IsEmpty()) {
     427           0 :     doc->WarnOnceAbout(nsIDocument::eXMLBaseAttribute);
     428             :     // Now resolve against all xml:base attrs
     429           0 :     for (uint32_t i = baseAttrs.Length() - 1; i != uint32_t(-1); --i) {
     430           0 :       nsCOMPtr<nsIURI> newBase;
     431           0 :       nsresult rv = NS_NewURI(getter_AddRefs(newBase), baseAttrs[i],
     432           0 :                               doc->GetDocumentCharacterSet(), base);
     433             :       // Do a security check, almost the same as nsDocument::SetBaseURL()
     434             :       // Only need to do this on the final uri
     435           0 :       if (NS_SUCCEEDED(rv) && i == 0) {
     436           0 :         rv = nsContentUtils::GetSecurityManager()->
     437           0 :           CheckLoadURIWithPrincipal(NodePrincipal(), newBase,
     438           0 :                                     nsIScriptSecurityManager::STANDARD);
     439             :       }
     440           0 :       if (NS_SUCCEEDED(rv)) {
     441           0 :         base.swap(newBase);
     442             :       }
     443             :     }
     444             :   }
     445             : 
     446         255 :   return base.forget();
     447             : }
     448             : 
     449             : nsIURI*
     450           8 : nsIContent::GetBaseURIWithoutXMLBase() const
     451             : {
     452           8 :   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     453           0 :     nsIContent* bindingParent = GetBindingParent();
     454           0 :     MOZ_ASSERT(bindingParent);
     455           0 :     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
     456           0 :     return useElement->GetContentURLData()->BaseURI();
     457             :   }
     458             :   // This also ignores the case that SVG inside XBL binding.
     459             :   // But it is probably fine.
     460           8 :   return OwnerDoc()->GetDocBaseURI();
     461             : }
     462             : 
     463             : already_AddRefed<nsIURI>
     464           8 : nsIContent::GetBaseURIForStyleAttr() const
     465             : {
     466           8 :   nsIDocument* doc = OwnerDoc();
     467           8 :   nsIURI* baseWithoutXMLBase = GetBaseURIWithoutXMLBase();
     468          16 :   nsCOMPtr<nsIURI> base = GetBaseURI();
     469             :   // If eXMLBaseAttribute is not triggered in GetBaseURI() call above,
     470             :   // we don't need to count eXMLBaseAttributeForStyleAttr either.
     471           8 :   if (doc->HasWarnedAbout(nsIDocument::eXMLBaseAttribute) &&
     472           0 :       !doc->HasWarnedAbout(nsIDocument::eXMLBaseAttributeForStyleAttr)) {
     473           0 :     bool isEqual = false;
     474           0 :     base->Equals(baseWithoutXMLBase, &isEqual);
     475           0 :     if (!isEqual) {
     476           0 :       doc->WarnOnceAbout(nsIDocument::eXMLBaseAttributeForStyleAttr);
     477             :     }
     478             :   }
     479           8 :   return nsLayoutUtils::StyleAttrWithXMLBaseDisabled()
     480          16 :     ? do_AddRef(baseWithoutXMLBase) : base.forget();
     481             : }
     482             : 
     483             : URLExtraData*
     484           0 : nsIContent::GetURLDataForStyleAttr() const
     485             : {
     486           0 :   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     487           0 :     nsIContent* bindingParent = GetBindingParent();
     488           0 :     MOZ_ASSERT(bindingParent);
     489           0 :     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
     490           0 :     return useElement->GetContentURLData();
     491             :   }
     492             :   // We are not going to support xml:base for stylo, but we want to
     493             :   // ensure we unship that support before we enabling stylo.
     494           0 :   MOZ_ASSERT(nsLayoutUtils::StyleAttrWithXMLBaseDisabled());
     495             :   // This also ignores the case that SVG inside XBL binding.
     496             :   // But it is probably fine.
     497           0 :   return OwnerDoc()->DefaultStyleAttrURLData();
     498             : }
     499             : 
     500             : //----------------------------------------------------------------------
     501             : 
     502             : static inline JSObject*
     503           0 : GetJSObjectChild(nsWrapperCache* aCache)
     504             : {
     505           0 :   return aCache->PreservingWrapper() ? aCache->GetWrapperPreserveColor() : nullptr;
     506             : }
     507             : 
     508             : static bool
     509           0 : NeedsScriptTraverse(nsINode* aNode)
     510             : {
     511           0 :   return aNode->PreservingWrapper() && aNode->GetWrapperPreserveColor() &&
     512           0 :          !aNode->HasKnownLiveWrapperAndDoesNotNeedTracing(aNode);
     513             : }
     514             : 
     515             : //----------------------------------------------------------------------
     516             : 
     517          30 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
     518          12 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
     519             : 
     520             : // If nsChildContentList is changed so that any additional fields are
     521             : // traversed by the cycle collector, then CAN_SKIP must be updated to
     522             : // check that the additional fields are null.
     523          24 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsChildContentList)
     524             : 
     525             : // nsChildContentList only ever has a single child, its wrapper, so if
     526             : // the wrapper is known-live, the list can't be part of a garbage cycle.
     527           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
     528           0 :   return tmp->HasKnownLiveWrapper();
     529             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
     530             : 
     531           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
     532           0 :   return tmp->HasKnownLiveWrapperAndDoesNotNeedTracing(tmp);
     533             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
     534             : 
     535             : // CanSkipThis returns false to avoid problems with incomplete unlinking.
     536           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
     537           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
     538             : 
     539          88 : NS_INTERFACE_TABLE_HEAD(nsChildContentList)
     540          88 :   NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
     541          80 :   NS_INTERFACE_TABLE(nsChildContentList, nsINodeList, nsIDOMNodeList)
     542          80 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsChildContentList)
     543           0 : NS_INTERFACE_MAP_END
     544             : 
     545             : JSObject*
     546           8 : nsChildContentList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
     547             : {
     548           8 :   return NodeListBinding::Wrap(cx, this, aGivenProto);
     549             : }
     550             : 
     551             : NS_IMETHODIMP
     552          38 : nsChildContentList::GetLength(uint32_t* aLength)
     553             : {
     554          38 :   *aLength = mNode ? mNode->GetChildCount() : 0;
     555             : 
     556          38 :   return NS_OK;
     557             : }
     558             : 
     559             : NS_IMETHODIMP
     560           6 : nsChildContentList::Item(uint32_t aIndex, nsIDOMNode** aReturn)
     561             : {
     562           6 :   nsINode* node = Item(aIndex);
     563           6 :   if (!node) {
     564           0 :     *aReturn = nullptr;
     565             : 
     566           0 :     return NS_OK;
     567             :   }
     568             : 
     569           6 :   return CallQueryInterface(node, aReturn);
     570             : }
     571             : 
     572             : nsIContent*
     573          39 : nsChildContentList::Item(uint32_t aIndex)
     574             : {
     575          39 :   if (mNode) {
     576          39 :     return mNode->GetChildAt(aIndex);
     577             :   }
     578             : 
     579           0 :   return nullptr;
     580             : }
     581             : 
     582             : int32_t
     583           0 : nsChildContentList::IndexOf(nsIContent* aContent)
     584             : {
     585           0 :   if (mNode) {
     586           0 :     return mNode->IndexOf(aContent);
     587             :   }
     588             : 
     589           0 :   return -1;
     590             : }
     591             : 
     592             : //----------------------------------------------------------------------
     593             : 
     594             : nsIHTMLCollection*
     595           5 : FragmentOrElement::Children()
     596             : {
     597           5 :   FragmentOrElement::nsDOMSlots *slots = DOMSlots();
     598             : 
     599           5 :   if (!slots->mChildrenList) {
     600             :     slots->mChildrenList = new nsContentList(this, kNameSpaceID_Wildcard,
     601             :                                              nsGkAtoms::_asterisk, nsGkAtoms::_asterisk,
     602           5 :                                              false);
     603             :   }
     604             : 
     605           5 :   return slots->mChildrenList;
     606             : }
     607             : 
     608             : 
     609             : //----------------------------------------------------------------------
     610             : 
     611             : 
     612         581 : NS_IMPL_ISUPPORTS(nsNodeWeakReference,
     613             :                   nsIWeakReference)
     614             : 
     615          26 : nsNodeWeakReference::~nsNodeWeakReference()
     616             : {
     617          13 :   if (mNode) {
     618          13 :     NS_ASSERTION(mNode->Slots()->mWeakReference == this,
     619             :                  "Weak reference has wrong value");
     620          13 :     mNode->Slots()->mWeakReference = nullptr;
     621             :   }
     622          13 : }
     623             : 
     624             : NS_IMETHODIMP
     625         258 : nsNodeWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
     626             : {
     627         258 :   return mNode ? mNode->QueryInterface(aIID, aInstancePtr) :
     628         258 :                  NS_ERROR_NULL_POINTER;
     629             : }
     630             : 
     631             : size_t
     632           0 : nsNodeWeakReference::SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const
     633             : {
     634           0 :   return aMallocSizeOf(this);
     635             : }
     636             : 
     637             : 
     638           0 : NS_IMPL_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff, mNode)
     639             : 
     640         675 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff)
     641           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     642           0 : NS_INTERFACE_MAP_END_AGGREGATED(mNode)
     643             : 
     644         135 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSupportsWeakRefTearoff)
     645         405 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSupportsWeakRefTearoff)
     646             : 
     647             : NS_IMETHODIMP
     648         135 : nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
     649             : {
     650         135 :   nsINode::nsSlots* slots = mNode->Slots();
     651         135 :   if (!slots->mWeakReference) {
     652         222 :     slots->mWeakReference = new nsNodeWeakReference(mNode);
     653             :   }
     654             : 
     655         135 :   NS_ADDREF(*aInstancePtr = slots->mWeakReference);
     656             : 
     657         135 :   return NS_OK;
     658             : }
     659             : 
     660             : //----------------------------------------------------------------------
     661         981 : FragmentOrElement::nsDOMSlots::nsDOMSlots()
     662             :   : nsINode::nsSlots(),
     663             :     mDataset(nullptr),
     664         981 :     mBindingParent(nullptr)
     665             : {
     666         981 : }
     667             : 
     668           3 : FragmentOrElement::nsDOMSlots::~nsDOMSlots()
     669             : {
     670           1 :   if (mAttributeMap) {
     671           0 :     mAttributeMap->DropReference();
     672             :   }
     673           3 : }
     674             : 
     675             : void
     676         290 : FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL)
     677             : {
     678         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
     679         290 :   cb.NoteXPCOMChild(mStyle.get());
     680             : 
     681         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
     682         290 :   cb.NoteXPCOMChild(mSMILOverrideStyle.get());
     683             : 
     684         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
     685         290 :   cb.NoteXPCOMChild(mAttributeMap.get());
     686             : 
     687         290 :   if (aIsXUL) {
     688         287 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
     689         287 :     cb.NoteXPCOMChild(mControllers);
     690             :   }
     691             : 
     692         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLBinding");
     693         290 :   cb.NoteNativeChild(mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
     694             : 
     695         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
     696         290 :   cb.NoteXPCOMChild(mXBLInsertionParent.get());
     697             : 
     698         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mShadowRoot");
     699         290 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
     700             : 
     701         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
     702         290 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
     703             : 
     704         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
     705         290 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
     706             : 
     707         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
     708         290 :   cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
     709             : 
     710         290 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
     711         290 :   cb.NoteXPCOMChild(mClassList.get());
     712             : 
     713         290 :   if (mCustomElementData) {
     714           0 :     for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) {
     715           0 :       mCustomElementData->mCallbackQueue[i]->Traverse(cb);
     716             :     }
     717             :   }
     718             : 
     719         290 :   for (auto iter = mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     720           0 :     DOMIntersectionObserver* observer = iter.Key();
     721           0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mRegisteredIntersectionObservers[i]");
     722           0 :     cb.NoteXPCOMChild(observer);
     723             :   }
     724         290 : }
     725             : 
     726             : void
     727           0 : FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
     728             : {
     729           0 :   mStyle = nullptr;
     730           0 :   mSMILOverrideStyle = nullptr;
     731           0 :   if (mAttributeMap) {
     732           0 :     mAttributeMap->DropReference();
     733           0 :     mAttributeMap = nullptr;
     734             :   }
     735           0 :   if (aIsXUL)
     736           0 :     NS_IF_RELEASE(mControllers);
     737             : 
     738           0 :   MOZ_ASSERT(!mXBLBinding);
     739             : 
     740           0 :   mXBLInsertionParent = nullptr;
     741           0 :   mShadowRoot = nullptr;
     742           0 :   mContainingShadow = nullptr;
     743           0 :   mChildrenList = nullptr;
     744           0 :   mLabelsList = nullptr;
     745           0 :   mCustomElementData = nullptr;
     746           0 :   mClassList = nullptr;
     747           0 :   mRegisteredIntersectionObservers.Clear();
     748           0 : }
     749             : 
     750             : size_t
     751           5 : FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     752             : {
     753           5 :   size_t n = aMallocSizeOf(this);
     754             : 
     755           5 :   if (mAttributeMap) {
     756           0 :     n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf);
     757             :   }
     758             : 
     759             :   // Measurement of the following members may be added later if DMD finds it is
     760             :   // worthwhile:
     761             :   // - Superclass members (nsINode::nsSlots)
     762             :   // - mStyle
     763             :   // - mDataSet
     764             :   // - mSMILOverrideStyle
     765             :   // - mSMILOverrideStyleDeclaration
     766             :   // - mChildrenList
     767             :   // - mClassList
     768             : 
     769             :   // The following members are not measured:
     770             :   // - mBindingParent / mControllers: because they're   non-owning
     771           5 :   return n;
     772             : }
     773             : 
     774        3168 : FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     775        3168 :   : nsIContent(aNodeInfo)
     776             : {
     777        3168 : }
     778             : 
     779           4 : FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     780           4 :   : nsIContent(aNodeInfo)
     781             : {
     782           4 : }
     783             : 
     784          64 : FragmentOrElement::~FragmentOrElement()
     785             : {
     786          32 :   NS_PRECONDITION(!IsInUncomposedDoc(),
     787             :                   "Please remove this from the document properly");
     788          32 :   if (GetParent()) {
     789           0 :     NS_RELEASE(mParent);
     790             :   }
     791          32 : }
     792             : 
     793             : already_AddRefed<nsINodeList>
     794           0 : FragmentOrElement::GetChildren(uint32_t aFilter)
     795             : {
     796           0 :   RefPtr<nsSimpleContentList> list = new nsSimpleContentList(this);
     797           0 :   AllChildrenIterator iter(this, aFilter);
     798           0 :   while (nsIContent* kid = iter.GetNextChild()) {
     799           0 :     list->AppendElement(kid);
     800           0 :   }
     801             : 
     802           0 :   return list.forget();
     803             : }
     804             : 
     805             : static nsIContent*
     806           0 : FindChromeAccessOnlySubtreeOwner(nsIContent* aContent)
     807             : {
     808           0 :   if (aContent->ChromeOnlyAccess()) {
     809           0 :     bool chromeAccessOnly = false;
     810           0 :     while (aContent && !chromeAccessOnly) {
     811           0 :       chromeAccessOnly = aContent->IsRootOfChromeAccessOnlySubtree();
     812           0 :       aContent = aContent->GetParent();
     813             :     }
     814             :   }
     815           0 :   return aContent;
     816             : }
     817             : 
     818             : nsresult
     819        1404 : nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     820             : {
     821             :   //FIXME! Document how this event retargeting works, Bug 329124.
     822        1404 :   aVisitor.mCanHandle = true;
     823        1404 :   aVisitor.mMayHaveListenerManager = HasListenerManager();
     824             : 
     825             :   // Don't propagate mouseover and mouseout events when mouse is moving
     826             :   // inside chrome access only content.
     827        1404 :   bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
     828        4198 :   if ((aVisitor.mEvent->mMessage == eMouseOver ||
     829        2766 :        aVisitor.mEvent->mMessage == eMouseOut ||
     830        2738 :        aVisitor.mEvent->mMessage == ePointerOver ||
     831        2826 :        aVisitor.mEvent->mMessage == ePointerOut) &&
     832             :       // Check if we should stop event propagation when event has just been
     833             :       // dispatched or when we're about to propagate from
     834             :       // chrome access only subtree or if we are about to propagate out of
     835             :       // a shadow root to a shadow root host.
     836          60 :       ((this == aVisitor.mEvent->mOriginalTarget &&
     837          56 :         !ChromeOnlyAccess()) || isAnonForEvents || GetShadowRoot())) {
     838             :      nsCOMPtr<nsIContent> relatedTarget =
     839           8 :        do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->relatedTarget);
     840           4 :     if (relatedTarget &&
     841           4 :         relatedTarget->OwnerDoc() == OwnerDoc()) {
     842             : 
     843             :       // In the web components case, we may need to stop propagation of events
     844             :       // at shadow root host.
     845           0 :       if (GetShadowRoot()) {
     846             :         nsIContent* adjustedTarget =
     847           0 :           Event::GetShadowRelatedTarget(this, relatedTarget);
     848           0 :         if (this == adjustedTarget) {
     849           0 :           aVisitor.mParentTarget = nullptr;
     850           0 :           aVisitor.mCanHandle = false;
     851           0 :           return NS_OK;
     852             :         }
     853             :       }
     854             : 
     855             :       // If current target is anonymous for events or we know that related
     856             :       // target is descendant of an element which is anonymous for events,
     857             :       // we may want to stop event propagation.
     858             :       // If this is the original target, aVisitor.mRelatedTargetIsInAnon
     859             :       // must be updated.
     860           0 :       if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
     861           0 :           (aVisitor.mEvent->mOriginalTarget == this &&
     862           0 :            (aVisitor.mRelatedTargetIsInAnon =
     863           0 :             relatedTarget->ChromeOnlyAccess()))) {
     864           0 :         nsIContent* anonOwner = FindChromeAccessOnlySubtreeOwner(this);
     865           0 :         if (anonOwner) {
     866             :           nsIContent* anonOwnerRelated =
     867           0 :             FindChromeAccessOnlySubtreeOwner(relatedTarget);
     868           0 :           if (anonOwnerRelated) {
     869             :             // Note, anonOwnerRelated may still be inside some other
     870             :             // native anonymous subtree. The case where anonOwner is still
     871             :             // inside native anonymous subtree will be handled when event
     872             :             // propagates up in the DOM tree.
     873           0 :             while (anonOwner != anonOwnerRelated &&
     874           0 :                    anonOwnerRelated->ChromeOnlyAccess()) {
     875           0 :               anonOwnerRelated = FindChromeAccessOnlySubtreeOwner(anonOwnerRelated);
     876             :             }
     877           0 :             if (anonOwner == anonOwnerRelated) {
     878             : #ifdef DEBUG_smaug
     879             :               nsCOMPtr<nsIContent> originalTarget =
     880             :                 do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
     881             :               nsAutoString ot, ct, rt;
     882             :               if (originalTarget) {
     883             :                 originalTarget->NodeInfo()->NameAtom()->ToString(ot);
     884             :               }
     885             :               NodeInfo()->NameAtom()->ToString(ct);
     886             :               relatedTarget->NodeInfo()->NameAtom()->ToString(rt);
     887             :               printf("Stopping %s propagation:"
     888             :                      "\n\toriginalTarget=%s \n\tcurrentTarget=%s %s"
     889             :                      "\n\trelatedTarget=%s %s \n%s",
     890             :                      (aVisitor.mEvent->mMessage == eMouseOver)
     891             :                        ? "mouseover" : "mouseout",
     892             :                      NS_ConvertUTF16toUTF8(ot).get(),
     893             :                      NS_ConvertUTF16toUTF8(ct).get(),
     894             :                      isAnonForEvents
     895             :                        ? "(is native anonymous)"
     896             :                        : (ChromeOnlyAccess()
     897             :                            ? "(is in native anonymous subtree)" : ""),
     898             :                      NS_ConvertUTF16toUTF8(rt).get(),
     899             :                      relatedTarget->ChromeOnlyAccess()
     900             :                        ? "(is in native anonymous subtree)" : "",
     901             :                      (originalTarget &&
     902             :                       relatedTarget->FindFirstNonChromeOnlyAccessContent() ==
     903             :                         originalTarget->FindFirstNonChromeOnlyAccessContent())
     904             :                        ? "" : "Wrong event propagation!?!\n");
     905             : #endif
     906           0 :               aVisitor.mParentTarget = nullptr;
     907             :               // Event should not propagate to non-anon content.
     908           0 :               aVisitor.mCanHandle = isAnonForEvents;
     909           0 :               return NS_OK;
     910             :             }
     911             :           }
     912             :         }
     913             :       }
     914             :     }
     915             :   }
     916             : 
     917        1404 :   nsIContent* parent = GetParent();
     918             : 
     919             :   // Web components have a special event chain that need to account
     920             :   // for destination insertion points where nodes have been distributed.
     921        1404 :   nsTArray<nsIContent*>* destPoints = GetExistingDestInsertionPoints();
     922        1404 :   if (destPoints && !destPoints->IsEmpty()) {
     923             :     // Push destination insertion points to aVisitor.mDestInsertionPoints
     924             :     // excluding shadow insertion points.
     925           0 :     bool didPushNonShadowInsertionPoint = false;
     926           0 :     for (uint32_t i = 0; i < destPoints->Length(); i++) {
     927           0 :       nsIContent* point = destPoints->ElementAt(i);
     928           0 :       if (!ShadowRoot::IsShadowInsertionPoint(point)) {
     929           0 :         aVisitor.mDestInsertionPoints.AppendElement(point);
     930           0 :         didPushNonShadowInsertionPoint = true;
     931             :       }
     932             :     }
     933             : 
     934             :     // Next node in the event path is the final destination
     935             :     // (non-shadow) insertion point that was pushed.
     936           0 :     if (didPushNonShadowInsertionPoint) {
     937           0 :       parent = aVisitor.mDestInsertionPoints.LastElement();
     938           0 :       aVisitor.mDestInsertionPoints.SetLength(
     939           0 :         aVisitor.mDestInsertionPoints.Length() - 1);
     940             :     }
     941             :   }
     942             : 
     943        1404 :   ShadowRoot* thisShadowRoot = ShadowRoot::FromNode(this);
     944        1404 :   if (thisShadowRoot) {
     945           0 :     if (!aVisitor.mEvent->mFlags.mComposed) {
     946             :       // If we do stop propagation, we still want to propagate
     947             :       // the event to chrome (nsPIDOMWindow::GetParentTarget()).
     948             :       // The load event is special in that we don't ever propagate it
     949             :       // to chrome.
     950           0 :       nsCOMPtr<nsPIDOMWindowOuter> win = OwnerDoc()->GetWindow();
     951           0 :       EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad
     952           0 :         ? win->GetParentTarget() : nullptr;
     953             : 
     954           0 :       aVisitor.mParentTarget = parentTarget;
     955           0 :       return NS_OK;
     956             :     }
     957             : 
     958           0 :     if (!aVisitor.mDestInsertionPoints.IsEmpty()) {
     959           0 :       parent = aVisitor.mDestInsertionPoints.LastElement();
     960           0 :       aVisitor.mDestInsertionPoints.SetLength(
     961           0 :         aVisitor.mDestInsertionPoints.Length() - 1);
     962             :     } else {
     963             :       // The pool host for the youngest shadow root is shadow DOM host,
     964             :       // for older shadow roots, it is the shadow insertion point
     965             :       // where the shadow root is projected, nullptr if none exists.
     966           0 :       parent = thisShadowRoot->GetPoolHost();
     967             :     }
     968             :   }
     969             : 
     970             :   // Event may need to be retargeted if this is the root of a native
     971             :   // anonymous content subtree or event is dispatched somewhere inside XBL.
     972        1404 :   if (isAnonForEvents) {
     973             : #ifdef DEBUG
     974             :     // If a DOM event is explicitly dispatched using node.dispatchEvent(), then
     975             :     // all the events are allowed even in the native anonymous content..
     976             :     nsCOMPtr<nsIContent> t =
     977           2 :       do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
     978           1 :     NS_ASSERTION(!t || !t->ChromeOnlyAccess() ||
     979             :                  aVisitor.mEvent->mClass != eMutationEventClass ||
     980             :                  aVisitor.mDOMEvent,
     981             :                  "Mutation event dispatched in native anonymous content!?!");
     982             : #endif
     983           1 :     aVisitor.mEventTargetAtParent = parent;
     984        1403 :   } else if (parent && aVisitor.mOriginalTargetIsInAnon) {
     985        1470 :     nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget));
     986         735 :     if (content && content->GetBindingParent() == parent) {
     987          90 :       aVisitor.mEventTargetAtParent = parent;
     988             :     }
     989             :   }
     990             : 
     991             :   // check for an anonymous parent
     992             :   // XXX XBL2/sXBL issue
     993        1404 :   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
     994         780 :     nsIContent* insertionParent = GetXBLInsertionParent();
     995         780 :     NS_ASSERTION(!(aVisitor.mEventTargetAtParent && insertionParent &&
     996             :                    aVisitor.mEventTargetAtParent != insertionParent),
     997             :                  "Retargeting and having insertion parent!");
     998         780 :     if (insertionParent) {
     999          68 :       parent = insertionParent;
    1000             :     }
    1001             :   }
    1002             : 
    1003        3476 :   if (!aVisitor.mEvent->mFlags.mComposedInNativeAnonymousContent &&
    1004        1404 :       IsRootOfNativeAnonymousSubtree() && OwnerDoc() &&
    1005           0 :       OwnerDoc()->GetWindow()) {
    1006           0 :     aVisitor.mParentTarget = OwnerDoc()->GetWindow()->GetParentTarget();
    1007        1404 :   } else if (parent) {
    1008        1225 :     aVisitor.mParentTarget = parent;
    1009             :   } else {
    1010         179 :     aVisitor.mParentTarget = GetComposedDoc();
    1011             :   }
    1012        1404 :   return NS_OK;
    1013             : }
    1014             : 
    1015             : bool
    1016       12142 : nsIContent::GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
    1017             :                     nsAString& aResult) const
    1018             : {
    1019       12142 :   if (IsElement()) {
    1020       12136 :     return AsElement()->GetAttr(aNameSpaceID, aName, aResult);
    1021             :   }
    1022           6 :   aResult.Truncate();
    1023           6 :   return false;
    1024             : }
    1025             : 
    1026             : bool
    1027        5473 : nsIContent::HasAttr(int32_t aNameSpaceID, nsIAtom* aName) const
    1028             : {
    1029        5473 :   return IsElement() && AsElement()->HasAttr(aNameSpaceID, aName);
    1030             : }
    1031             : 
    1032             : bool
    1033         231 : nsIContent::AttrValueIs(int32_t aNameSpaceID,
    1034             :                         nsIAtom* aName,
    1035             :                         const nsAString& aValue,
    1036             :                         nsCaseTreatment aCaseSensitive) const
    1037             : {
    1038         453 :   return IsElement() &&
    1039         453 :     AsElement()->AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
    1040             : }
    1041             : 
    1042             : bool
    1043        1188 : nsIContent::AttrValueIs(int32_t aNameSpaceID,
    1044             :                         nsIAtom* aName,
    1045             :                         nsIAtom* aValue,
    1046             :                         nsCaseTreatment aCaseSensitive) const
    1047             : {
    1048        2376 :   return IsElement() &&
    1049        2376 :     AsElement()->AttrValueIs(aNameSpaceID, aName, aValue, aCaseSensitive);
    1050             : }
    1051             : 
    1052             : bool
    1053           3 : nsIContent::IsFocusable(int32_t* aTabIndex, bool aWithMouse)
    1054             : {
    1055           3 :   bool focusable = IsFocusableInternal(aTabIndex, aWithMouse);
    1056             :   // Ensure that the return value and aTabIndex are consistent in the case
    1057             :   // we're in userfocusignored context.
    1058           3 :   if (focusable || (aTabIndex && *aTabIndex != -1)) {
    1059           3 :     if (nsContentUtils::IsUserFocusIgnored(this)) {
    1060           0 :       if (aTabIndex) {
    1061           0 :         *aTabIndex = -1;
    1062             :       }
    1063           0 :       return false;
    1064             :     }
    1065           3 :     return focusable;
    1066             :   }
    1067           0 :   return false;
    1068             : }
    1069             : 
    1070             : bool
    1071           0 : nsIContent::IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse)
    1072             : {
    1073           0 :   if (aTabIndex) {
    1074           0 :     *aTabIndex = -1; // Default, not tabbable
    1075             :   }
    1076           0 :   return false;
    1077             : }
    1078             : 
    1079             : NS_IMETHODIMP
    1080           0 : FragmentOrElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
    1081             : {
    1082           0 :   return NS_OK;
    1083             : }
    1084             : 
    1085             : bool
    1086           0 : FragmentOrElement::IsLink(nsIURI** aURI) const
    1087             : {
    1088           0 :   *aURI = nullptr;
    1089           0 :   return false;
    1090             : }
    1091             : 
    1092             : nsIContent*
    1093       15726 : FragmentOrElement::GetBindingParent() const
    1094             : {
    1095       15726 :   nsDOMSlots *slots = GetExistingDOMSlots();
    1096             : 
    1097       15726 :   if (slots) {
    1098        3090 :     return slots->mBindingParent;
    1099             :   }
    1100       12636 :   return nullptr;
    1101             : }
    1102             : 
    1103             : nsXBLBinding*
    1104       11149 : FragmentOrElement::GetXBLBinding() const
    1105             : {
    1106       11149 :   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
    1107        6580 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1108        6580 :     if (slots) {
    1109        6580 :       return slots->mXBLBinding;
    1110             :     }
    1111             :   }
    1112             : 
    1113        4569 :   return nullptr;
    1114             : }
    1115             : 
    1116             : void
    1117         284 : FragmentOrElement::SetXBLBinding(nsXBLBinding* aBinding,
    1118             :                                  nsBindingManager* aOldBindingManager)
    1119             : {
    1120             :   nsBindingManager* bindingManager;
    1121         284 :   if (aOldBindingManager) {
    1122           7 :     MOZ_ASSERT(!aBinding, "aOldBindingManager should only be provided "
    1123             :                           "when removing a binding.");
    1124           7 :     bindingManager = aOldBindingManager;
    1125             :   } else {
    1126         277 :     bindingManager = OwnerDoc()->BindingManager();
    1127             :   }
    1128             : 
    1129             :   // After this point, aBinding will be the most-derived binding for aContent.
    1130             :   // If we already have a binding for aContent, make sure to
    1131             :   // remove it from the attached stack.  Otherwise we might end up firing its
    1132             :   // constructor twice (if aBinding inherits from it) or firing its constructor
    1133             :   // after aContent has been deleted (if aBinding is null and the content node
    1134             :   // dies before we process mAttachedStack).
    1135         568 :   RefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
    1136         284 :   if (oldBinding) {
    1137          12 :     bindingManager->RemoveFromAttachedQueue(oldBinding);
    1138             :   }
    1139             : 
    1140         284 :   if (aBinding) {
    1141         272 :     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
    1142         272 :     nsDOMSlots *slots = DOMSlots();
    1143         272 :     slots->mXBLBinding = aBinding;
    1144         272 :     bindingManager->AddBoundContent(this);
    1145             :   } else {
    1146          12 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1147          12 :     if (slots) {
    1148          12 :       slots->mXBLBinding = nullptr;
    1149             :     }
    1150          12 :     bindingManager->RemoveBoundContent(this);
    1151          12 :     if (oldBinding) {
    1152          12 :       oldBinding->SetBoundElement(nullptr);
    1153             :     }
    1154             :   }
    1155         284 : }
    1156             : 
    1157             : nsIContent*
    1158        4786 : FragmentOrElement::GetXBLInsertionParent() const
    1159             : {
    1160        4786 :   if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
    1161        4693 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1162        4693 :     if (slots) {
    1163        4693 :       return slots->mXBLInsertionParent;
    1164             :     }
    1165             :   }
    1166             : 
    1167          93 :   return nullptr;
    1168             : }
    1169             : 
    1170             : ShadowRoot*
    1171        7177 : FragmentOrElement::GetContainingShadow() const
    1172             : {
    1173        7177 :   nsDOMSlots *slots = GetExistingDOMSlots();
    1174        7177 :   if (slots) {
    1175         553 :     return slots->mContainingShadow;
    1176             :   }
    1177        6624 :   return nullptr;
    1178             : }
    1179             : 
    1180             : void
    1181           0 : FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot)
    1182             : {
    1183           0 :   nsDOMSlots *slots = DOMSlots();
    1184           0 :   slots->mShadowRoot = aShadowRoot;
    1185           0 : }
    1186             : 
    1187             : nsTArray<nsIContent*>&
    1188           0 : FragmentOrElement::DestInsertionPoints()
    1189             : {
    1190           0 :   nsDOMSlots *slots = DOMSlots();
    1191           0 :   return slots->mDestInsertionPoints;
    1192             : }
    1193             : 
    1194             : nsTArray<nsIContent*>*
    1195        1398 : FragmentOrElement::GetExistingDestInsertionPoints() const
    1196             : {
    1197        1398 :   nsDOMSlots *slots = GetExistingDOMSlots();
    1198        1398 :   if (slots) {
    1199         852 :     return &slots->mDestInsertionPoints;
    1200             :   }
    1201         546 :   return nullptr;
    1202             : }
    1203             : 
    1204             : void
    1205         496 : FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
    1206             : {
    1207         496 :   if (aContent) {
    1208         429 :     nsDOMSlots *slots = DOMSlots();
    1209         429 :     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
    1210         429 :     slots->mXBLInsertionParent = aContent;
    1211             :   } else {
    1212          67 :     nsDOMSlots *slots = GetExistingDOMSlots();
    1213          67 :     if (slots) {
    1214          30 :       slots->mXBLInsertionParent = nullptr;
    1215             :     }
    1216             :   }
    1217             : 
    1218             :   // We just changed the flattened tree, so any Servo style data is now invalid.
    1219             :   // We rely on nsXBLService::LoadBindings to re-traverse the subtree afterwards.
    1220         496 :   if (IsStyledByServo() && IsElement() && AsElement()->HasServoData()) {
    1221           0 :     ServoRestyleManager::ClearServoDataFromSubtree(AsElement());
    1222             :   }
    1223         496 : }
    1224             : 
    1225             : nsresult
    1226        3330 : FragmentOrElement::InsertChildAt(nsIContent* aKid,
    1227             :                                 uint32_t aIndex,
    1228             :                                 bool aNotify)
    1229             : {
    1230        3330 :   NS_PRECONDITION(aKid, "null ptr");
    1231             : 
    1232        3330 :   return doInsertChildAt(aKid, aIndex, aNotify, mAttrsAndChildren);
    1233             : }
    1234             : 
    1235             : void
    1236         109 : FragmentOrElement::RemoveChildAt(uint32_t aIndex, bool aNotify)
    1237             : {
    1238         218 :   nsCOMPtr<nsIContent> oldKid = mAttrsAndChildren.GetSafeChildAt(aIndex);
    1239         109 :   NS_ASSERTION(oldKid == GetChildAt(aIndex), "Unexpected child in RemoveChildAt");
    1240             : 
    1241         109 :   if (oldKid) {
    1242         109 :     doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
    1243             :   }
    1244         109 : }
    1245             : 
    1246             : void
    1247           2 : FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
    1248             :                                           OOMReporter& aError)
    1249             : {
    1250           2 :   if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
    1251           0 :     aError.ReportOOM();
    1252             :   }
    1253           2 : }
    1254             : 
    1255             : void
    1256           2 : FragmentOrElement::SetTextContentInternal(const nsAString& aTextContent,
    1257             :                                           ErrorResult& aError)
    1258             : {
    1259           2 :   aError = nsContentUtils::SetNodeTextContent(this, aTextContent, false);
    1260           2 : }
    1261             : 
    1262             : void
    1263          12 : FragmentOrElement::DestroyContent()
    1264             : {
    1265             :   // Drop any servo data. We do this before the RemovedFromDocument call below
    1266             :   // so that it doesn't need to try to keep the style state sane when shuffling
    1267             :   // around the flattened tree.
    1268          12 :   if (IsElement() && AsElement()->HasServoData()) {
    1269           0 :     AsElement()->ClearServoData();
    1270             :   }
    1271             : 
    1272          12 :   nsIDocument *document = OwnerDoc();
    1273          12 :   document->BindingManager()->RemovedFromDocument(this, document,
    1274          12 :                                                   nsBindingManager::eRunDtor);
    1275          12 :   document->ClearBoxObjectFor(this);
    1276             : 
    1277          12 :   uint32_t i, count = mAttrsAndChildren.ChildCount();
    1278          20 :   for (i = 0; i < count; ++i) {
    1279             :     // The child can remove itself from the parent in BindToTree.
    1280           8 :     mAttrsAndChildren.ChildAt(i)->DestroyContent();
    1281             :   }
    1282          12 :   ShadowRoot* shadowRoot = GetShadowRoot();
    1283          12 :   if (shadowRoot) {
    1284           0 :     shadowRoot->DestroyContent();
    1285             :   }
    1286          12 : }
    1287             : 
    1288             : void
    1289          12 : FragmentOrElement::SaveSubtreeState()
    1290             : {
    1291          12 :   uint32_t i, count = mAttrsAndChildren.ChildCount();
    1292          20 :   for (i = 0; i < count; ++i) {
    1293           8 :     mAttrsAndChildren.ChildAt(i)->SaveSubtreeState();
    1294             :   }
    1295          12 : }
    1296             : 
    1297             : //----------------------------------------------------------------------
    1298             : 
    1299             : // Generic DOMNode implementations
    1300             : 
    1301             : void
    1302           0 : FragmentOrElement::FireNodeInserted(nsIDocument* aDoc,
    1303             :                                    nsINode* aParent,
    1304             :                                    nsTArray<nsCOMPtr<nsIContent> >& aNodes)
    1305             : {
    1306           0 :   uint32_t count = aNodes.Length();
    1307           0 :   for (uint32_t i = 0; i < count; ++i) {
    1308           0 :     nsIContent* childContent = aNodes[i];
    1309             : 
    1310           0 :     if (nsContentUtils::HasMutationListeners(childContent,
    1311             :           NS_EVENT_BITS_MUTATION_NODEINSERTED, aParent)) {
    1312           0 :       InternalMutationEvent mutation(true, eLegacyNodeInserted);
    1313           0 :       mutation.mRelatedNode = do_QueryInterface(aParent);
    1314             : 
    1315           0 :       mozAutoSubtreeModified subtree(aDoc, aParent);
    1316           0 :       (new AsyncEventDispatcher(childContent, mutation))->RunDOMEventWhenSafe();
    1317             :     }
    1318             :   }
    1319           0 : }
    1320             : 
    1321             : //----------------------------------------------------------------------
    1322             : 
    1323             : // nsISupports implementation
    1324             : 
    1325             : #define SUBTREE_UNBINDINGS_PER_RUNNABLE 500
    1326             : 
    1327             : class ContentUnbinder : public Runnable
    1328             : {
    1329             : public:
    1330           0 :   ContentUnbinder()
    1331           0 :     : Runnable("ContentUnbinder")
    1332             :   {
    1333           0 :     mLast = this;
    1334           0 :   }
    1335             : 
    1336           0 :   ~ContentUnbinder()
    1337           0 :   {
    1338           0 :     Run();
    1339           0 :   }
    1340             : 
    1341           0 :   void UnbindSubtree(nsIContent* aNode)
    1342             :   {
    1343           0 :     if (aNode->NodeType() != nsIDOMNode::ELEMENT_NODE &&
    1344           0 :         aNode->NodeType() != nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
    1345           0 :       return;
    1346             :     }
    1347           0 :     FragmentOrElement* container = static_cast<FragmentOrElement*>(aNode);
    1348           0 :     uint32_t childCount = container->mAttrsAndChildren.ChildCount();
    1349           0 :     if (childCount) {
    1350           0 :       while (childCount-- > 0) {
    1351             :         // Hold a strong ref to the node when we remove it, because we may be
    1352             :         // the last reference to it.  We need to call TakeChildAt() and
    1353             :         // update mFirstChild before calling UnbindFromTree, since this last
    1354             :         // can notify various observers and they should really see consistent
    1355             :         // tree state.
    1356             :         // If this code changes, change the corresponding code in
    1357             :         // FragmentOrElement's and nsDocument's unlink impls.
    1358             :         nsCOMPtr<nsIContent> child =
    1359           0 :           container->mAttrsAndChildren.TakeChildAt(childCount);
    1360           0 :         if (childCount == 0) {
    1361           0 :           container->mFirstChild = nullptr;
    1362             :         }
    1363           0 :         UnbindSubtree(child);
    1364           0 :         child->UnbindFromTree();
    1365             :       }
    1366             :     }
    1367             :   }
    1368             : 
    1369           0 :   NS_IMETHOD Run() override
    1370             :   {
    1371           0 :     nsAutoScriptBlocker scriptBlocker;
    1372           0 :     uint32_t len = mSubtreeRoots.Length();
    1373           0 :     if (len) {
    1374           0 :       for (uint32_t i = 0; i < len; ++i) {
    1375           0 :         UnbindSubtree(mSubtreeRoots[i]);
    1376             :       }
    1377           0 :       mSubtreeRoots.Clear();
    1378             :     }
    1379           0 :     nsCycleCollector_dispatchDeferredDeletion();
    1380           0 :     if (this == sContentUnbinder) {
    1381           0 :       sContentUnbinder = nullptr;
    1382           0 :       if (mNext) {
    1383           0 :         RefPtr<ContentUnbinder> next;
    1384           0 :         next.swap(mNext);
    1385           0 :         sContentUnbinder = next;
    1386           0 :         next->mLast = mLast;
    1387           0 :         mLast = nullptr;
    1388           0 :         NS_IdleDispatchToCurrentThread(next.forget());
    1389             :       }
    1390             :     }
    1391           0 :     return NS_OK;
    1392             :   }
    1393             : 
    1394           0 :   static void UnbindAll()
    1395             :   {
    1396           0 :     RefPtr<ContentUnbinder> ub = sContentUnbinder;
    1397           0 :     sContentUnbinder = nullptr;
    1398           0 :     while (ub) {
    1399           0 :       ub->Run();
    1400           0 :       ub = ub->mNext;
    1401             :     }
    1402           0 :   }
    1403             : 
    1404           0 :   static void Append(nsIContent* aSubtreeRoot)
    1405             :   {
    1406           0 :     if (!sContentUnbinder) {
    1407           0 :       sContentUnbinder = new ContentUnbinder();
    1408           0 :       nsCOMPtr<nsIRunnable> e = sContentUnbinder;
    1409           0 :       NS_IdleDispatchToCurrentThread(e.forget());
    1410             :     }
    1411             : 
    1412           0 :     if (sContentUnbinder->mLast->mSubtreeRoots.Length() >=
    1413             :         SUBTREE_UNBINDINGS_PER_RUNNABLE) {
    1414           0 :       sContentUnbinder->mLast->mNext = new ContentUnbinder();
    1415           0 :       sContentUnbinder->mLast = sContentUnbinder->mLast->mNext;
    1416             :     }
    1417           0 :     sContentUnbinder->mLast->mSubtreeRoots.AppendElement(aSubtreeRoot);
    1418           0 :   }
    1419             : 
    1420             : private:
    1421             :   AutoTArray<nsCOMPtr<nsIContent>,
    1422             :                SUBTREE_UNBINDINGS_PER_RUNNABLE> mSubtreeRoots;
    1423             :   RefPtr<ContentUnbinder>                     mNext;
    1424             :   ContentUnbinder*                              mLast;
    1425             :   static ContentUnbinder*                       sContentUnbinder;
    1426             : };
    1427             : 
    1428             : ContentUnbinder* ContentUnbinder::sContentUnbinder = nullptr;
    1429             : 
    1430             : void
    1431           0 : FragmentOrElement::ClearContentUnbinder()
    1432             : {
    1433           0 :   ContentUnbinder::UnbindAll();
    1434           0 : }
    1435             : 
    1436             : NS_IMPL_CYCLE_COLLECTION_CLASS(FragmentOrElement)
    1437             : 
    1438           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
    1439           0 :   nsINode::Unlink(tmp);
    1440             : 
    1441             :   // The XBL binding is removed by RemoveFromBindingManagerRunnable
    1442             :   // which is dispatched in UnbindFromTree.
    1443             : 
    1444           0 :   if (tmp->HasProperties()) {
    1445           0 :     if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
    1446           0 :       nsIAtom*** props = Element::HTMLSVGPropertiesToTraverseAndUnlink();
    1447           0 :       for (uint32_t i = 0; props[i]; ++i) {
    1448           0 :         tmp->DeleteProperty(*props[i]);
    1449             :       }
    1450           0 :       if (tmp->MayHaveAnimations()) {
    1451           0 :         nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms();
    1452           0 :         for (uint32_t i = 0; effectProps[i]; ++i) {
    1453           0 :           tmp->DeleteProperty(effectProps[i]);
    1454             :         }
    1455             :       }
    1456             :     }
    1457             :   }
    1458             : 
    1459             :   // Unlink child content (and unbind our subtree).
    1460           0 :   if (tmp->UnoptimizableCCNode() || !nsCCUncollectableMarker::sGeneration) {
    1461           0 :     uint32_t childCount = tmp->mAttrsAndChildren.ChildCount();
    1462           0 :     if (childCount) {
    1463             :       // Don't allow script to run while we're unbinding everything.
    1464           0 :       nsAutoScriptBlocker scriptBlocker;
    1465           0 :       while (childCount-- > 0) {
    1466             :         // Hold a strong ref to the node when we remove it, because we may be
    1467             :         // the last reference to it.  We need to call TakeChildAt() and
    1468             :         // update mFirstChild before calling UnbindFromTree, since this last
    1469             :         // can notify various observers and they should really see consistent
    1470             :         // tree state.
    1471             :         // If this code changes, change the corresponding code in nsDocument's
    1472             :         // unlink impl and ContentUnbinder::UnbindSubtree.
    1473           0 :         nsCOMPtr<nsIContent> child = tmp->mAttrsAndChildren.TakeChildAt(childCount);
    1474           0 :         if (childCount == 0) {
    1475           0 :           tmp->mFirstChild = nullptr;
    1476             :         }
    1477           0 :         child->UnbindFromTree();
    1478             :       }
    1479             :     }
    1480           0 :   } else if (!tmp->GetParent() && tmp->mAttrsAndChildren.ChildCount()) {
    1481           0 :     ContentUnbinder::Append(tmp);
    1482             :   } /* else {
    1483             :     The subtree root will end up to a ContentUnbinder, and that will
    1484             :     unbind the child nodes.
    1485             :   } */
    1486             : 
    1487             :   // Clear flag here because unlinking slots will clear the
    1488             :   // containing shadow root pointer.
    1489           0 :   tmp->UnsetFlags(NODE_IS_IN_SHADOW_TREE);
    1490             : 
    1491           0 :   nsIDocument* doc = tmp->OwnerDoc();
    1492           0 :   doc->BindingManager()->RemovedFromDocument(tmp, doc,
    1493           0 :                                              nsBindingManager::eDoNotRunDtor);
    1494             : 
    1495             :   // Unlink any DOM slots of interest.
    1496             :   {
    1497           0 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
    1498           0 :     if (slots) {
    1499           0 :       if (tmp->IsElement()) {
    1500           0 :         Element* elem = tmp->AsElement();
    1501           0 :         for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
    1502           0 :           DOMIntersectionObserver* observer = iter.Key();
    1503           0 :           observer->UnlinkTarget(*elem);
    1504             :         }
    1505             :       }
    1506           0 :       slots->Unlink(tmp->IsXULElement());
    1507             :     }
    1508             :   }
    1509             : 
    1510           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1511             : 
    1512        1140 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FragmentOrElement)
    1513             : 
    1514             : void
    1515           0 : FragmentOrElement::MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
    1516             :                                void* aData)
    1517             : {
    1518           0 :   uint32_t* gen = static_cast<uint32_t*>(aData);
    1519           0 :   xpc_MarkInCCGeneration(static_cast<nsISupports*>(aChild), *gen);
    1520           0 : }
    1521             : 
    1522             : void
    1523           0 : FragmentOrElement::MarkNodeChildren(nsINode* aNode)
    1524             : {
    1525           0 :   JSObject* o = GetJSObjectChild(aNode);
    1526           0 :   if (o) {
    1527           0 :     JS::ExposeObjectToActiveJS(o);
    1528             :   }
    1529             : 
    1530           0 :   EventListenerManager* elm = aNode->GetExistingListenerManager();
    1531           0 :   if (elm) {
    1532           0 :     elm->MarkForCC();
    1533             :   }
    1534             : 
    1535           0 :   if (aNode->HasProperties()) {
    1536           0 :     nsIDocument* ownerDoc = aNode->OwnerDoc();
    1537             :     ownerDoc->PropertyTable(DOM_USER_DATA)->
    1538           0 :       Enumerate(aNode, FragmentOrElement::MarkUserData,
    1539           0 :                 &nsCCUncollectableMarker::sGeneration);
    1540             :   }
    1541           0 : }
    1542             : 
    1543             : nsINode*
    1544           0 : FindOptimizableSubtreeRoot(nsINode* aNode)
    1545             : {
    1546             :   nsINode* p;
    1547           0 :   while ((p = aNode->GetParentNode())) {
    1548           0 :     if (aNode->UnoptimizableCCNode()) {
    1549           0 :       return nullptr;
    1550             :     }
    1551           0 :     aNode = p;
    1552             :   }
    1553             : 
    1554           0 :   if (aNode->UnoptimizableCCNode()) {
    1555           0 :     return nullptr;
    1556             :   }
    1557           0 :   return aNode;
    1558             : }
    1559             : 
    1560           3 : StaticAutoPtr<nsTHashtable<nsPtrHashKey<nsINode>>> gCCBlackMarkedNodes;
    1561             : 
    1562             : static void
    1563           0 : ClearBlackMarkedNodes()
    1564             : {
    1565           0 :   if (!gCCBlackMarkedNodes) {
    1566           0 :     return;
    1567             :   }
    1568           0 :   for (auto iter = gCCBlackMarkedNodes->ConstIter(); !iter.Done();
    1569           0 :        iter.Next()) {
    1570           0 :     nsINode* n = iter.Get()->GetKey();
    1571           0 :     n->SetCCMarkedRoot(false);
    1572           0 :     n->SetInCCBlackTree(false);
    1573             :   }
    1574           0 :   gCCBlackMarkedNodes = nullptr;
    1575             : }
    1576             : 
    1577             : // static
    1578             : void
    1579          47 : FragmentOrElement::RemoveBlackMarkedNode(nsINode* aNode)
    1580             : {
    1581          47 :   if (!gCCBlackMarkedNodes) {
    1582          47 :     return;
    1583             :   }
    1584           0 :   gCCBlackMarkedNodes->RemoveEntry(aNode);
    1585             : }
    1586             : 
    1587             : static bool
    1588           0 : IsCertainlyAliveNode(nsINode* aNode, nsIDocument* aDoc)
    1589             : {
    1590           0 :   MOZ_ASSERT(aNode->GetUncomposedDoc() == aDoc);
    1591             : 
    1592             :   // Marked to be in-CC-generation or if the document is an svg image that's
    1593             :   // being kept alive by the image cache. (Note that an svg image's internal
    1594             :   // SVG document will receive an OnPageHide() call when it gets purged from
    1595             :   // the image cache; hence, we use IsVisible() as a hint that the document is
    1596             :   // actively being kept alive by the cache.)
    1597           0 :   return nsCCUncollectableMarker::InGeneration(aDoc->GetMarkedCCGeneration()) ||
    1598           0 :          (nsCCUncollectableMarker::sGeneration &&
    1599           0 :           aDoc->IsBeingUsedAsImage() &&
    1600           0 :           aDoc->IsVisible());
    1601             : }
    1602             : 
    1603             : // static
    1604             : bool
    1605           0 : FragmentOrElement::CanSkipInCC(nsINode* aNode)
    1606             : {
    1607             :   // Don't try to optimize anything during shutdown.
    1608           0 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    1609           0 :     return false;
    1610             :   }
    1611             : 
    1612             :   //XXXsmaug Need to figure out in which cases Shadow DOM can be optimized out
    1613             :   //         from the CC graph.
    1614           0 :   nsIDocument* currentDoc = aNode->GetUncomposedDoc();
    1615           0 :   if (currentDoc && IsCertainlyAliveNode(aNode, currentDoc)) {
    1616           0 :     return !NeedsScriptTraverse(aNode);
    1617             :   }
    1618             : 
    1619             :   // Bail out early if aNode is somewhere in anonymous content,
    1620             :   // or otherwise unusual.
    1621           0 :   if (aNode->UnoptimizableCCNode()) {
    1622           0 :     return false;
    1623             :   }
    1624             : 
    1625             :   nsINode* root =
    1626           0 :     currentDoc ? static_cast<nsINode*>(currentDoc) :
    1627           0 :                  FindOptimizableSubtreeRoot(aNode);
    1628           0 :   if (!root) {
    1629           0 :     return false;
    1630             :   }
    1631             : 
    1632             :   // Subtree has been traversed already.
    1633           0 :   if (root->CCMarkedRoot()) {
    1634           0 :     return root->InCCBlackTree() && !NeedsScriptTraverse(aNode);
    1635             :   }
    1636             : 
    1637           0 :   if (!gCCBlackMarkedNodes) {
    1638           0 :     gCCBlackMarkedNodes = new nsTHashtable<nsPtrHashKey<nsINode> >(1020);
    1639             :   }
    1640             : 
    1641             :   // nodesToUnpurple contains nodes which will be removed
    1642             :   // from the purple buffer if the DOM tree is known-live.
    1643           0 :   AutoTArray<nsIContent*, 1020> nodesToUnpurple;
    1644             :   // grayNodes need script traverse, so they aren't removed from
    1645             :   // the purple buffer, but are marked to be in known-live subtree so that
    1646             :   // traverse is faster.
    1647           0 :   AutoTArray<nsINode*, 1020> grayNodes;
    1648             : 
    1649           0 :   bool foundLiveWrapper = root->HasKnownLiveWrapper();
    1650           0 :   if (root != currentDoc) {
    1651           0 :     currentDoc = nullptr;
    1652           0 :     if (NeedsScriptTraverse(root)) {
    1653           0 :       grayNodes.AppendElement(root);
    1654           0 :     } else if (static_cast<nsIContent*>(root)->IsPurple()) {
    1655           0 :       nodesToUnpurple.AppendElement(static_cast<nsIContent*>(root));
    1656             :     }
    1657             :   }
    1658             : 
    1659             :   // Traverse the subtree and check if we could know without CC
    1660             :   // that it is known-live.
    1661             :   // Note, this traverse is non-virtual and inline, so it should be a lot faster
    1662             :   // than CC's generic traverse.
    1663           0 :   for (nsIContent* node = root->GetFirstChild(); node;
    1664           0 :        node = node->GetNextNode(root)) {
    1665           0 :     foundLiveWrapper = foundLiveWrapper || node->HasKnownLiveWrapper();
    1666           0 :     if (foundLiveWrapper && currentDoc) {
    1667             :       // If we can mark the whole document known-live, no need to optimize
    1668             :       // so much, since when the next purple node in the document will be
    1669             :       // handled, it is fast to check that currentDoc is in CCGeneration.
    1670           0 :       break;
    1671             :     }
    1672           0 :     if (NeedsScriptTraverse(node)) {
    1673             :       // Gray nodes need real CC traverse.
    1674           0 :       grayNodes.AppendElement(node);
    1675           0 :     } else if (node->IsPurple()) {
    1676           0 :       nodesToUnpurple.AppendElement(node);
    1677             :     }
    1678             :   }
    1679             : 
    1680           0 :   root->SetCCMarkedRoot(true);
    1681           0 :   root->SetInCCBlackTree(foundLiveWrapper);
    1682           0 :   gCCBlackMarkedNodes->PutEntry(root);
    1683             : 
    1684           0 :   if (!foundLiveWrapper) {
    1685           0 :     return false;
    1686             :   }
    1687             : 
    1688           0 :   if (currentDoc) {
    1689             :     // Special case documents. If we know the document is known-live,
    1690             :     // we can mark the document to be in CCGeneration.
    1691             :     currentDoc->
    1692           0 :       MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
    1693             :   } else {
    1694           0 :     for (uint32_t i = 0; i < grayNodes.Length(); ++i) {
    1695           0 :       nsINode* node = grayNodes[i];
    1696           0 :       node->SetInCCBlackTree(true);
    1697           0 :       gCCBlackMarkedNodes->PutEntry(node);
    1698             :     }
    1699             :   }
    1700             : 
    1701             :   // Subtree is known-live, we can remove non-gray purple nodes from
    1702             :   // purple buffer.
    1703           0 :   for (uint32_t i = 0; i < nodesToUnpurple.Length(); ++i) {
    1704           0 :     nsIContent* purple = nodesToUnpurple[i];
    1705             :     // Can't remove currently handled purple node.
    1706           0 :     if (purple != aNode) {
    1707           0 :       purple->RemovePurple();
    1708             :     }
    1709             :   }
    1710           0 :   return !NeedsScriptTraverse(aNode);
    1711             : }
    1712             : 
    1713             : AutoTArray<nsINode*, 1020>* gPurpleRoots = nullptr;
    1714             : AutoTArray<nsIContent*, 1020>* gNodesToUnbind = nullptr;
    1715             : 
    1716           0 : void ClearCycleCollectorCleanupData()
    1717             : {
    1718           0 :   if (gPurpleRoots) {
    1719           0 :     uint32_t len = gPurpleRoots->Length();
    1720           0 :     for (uint32_t i = 0; i < len; ++i) {
    1721           0 :       nsINode* n = gPurpleRoots->ElementAt(i);
    1722           0 :       n->SetIsPurpleRoot(false);
    1723             :     }
    1724           0 :     delete gPurpleRoots;
    1725           0 :     gPurpleRoots = nullptr;
    1726             :   }
    1727           0 :   if (gNodesToUnbind) {
    1728           0 :     uint32_t len = gNodesToUnbind->Length();
    1729           0 :     for (uint32_t i = 0; i < len; ++i) {
    1730           0 :       nsIContent* c = gNodesToUnbind->ElementAt(i);
    1731           0 :       c->SetIsPurpleRoot(false);
    1732           0 :       ContentUnbinder::Append(c);
    1733             :     }
    1734           0 :     delete gNodesToUnbind;
    1735           0 :     gNodesToUnbind = nullptr;
    1736             :   }
    1737           0 : }
    1738             : 
    1739             : static bool
    1740           0 : ShouldClearPurple(nsIContent* aContent)
    1741             : {
    1742           0 :   MOZ_ASSERT(aContent);
    1743           0 :   if (aContent->IsPurple()) {
    1744           0 :     return true;
    1745             :   }
    1746             : 
    1747           0 :   JSObject* o = GetJSObjectChild(aContent);
    1748           0 :   if (o && JS::ObjectIsMarkedGray(o)) {
    1749           0 :     return true;
    1750             :   }
    1751             : 
    1752           0 :   if (aContent->HasListenerManager()) {
    1753           0 :     return true;
    1754             :   }
    1755             : 
    1756           0 :   return aContent->HasProperties();
    1757             : }
    1758             : 
    1759             : // If aNode is not optimizable, but is an element
    1760             : // with a frame in a document which has currently active presshell,
    1761             : // we can act as if it was optimizable. When the primary frame dies, aNode
    1762             : // will end up to the purple buffer because of the refcount change.
    1763             : bool
    1764           0 : NodeHasActiveFrame(nsIDocument* aCurrentDoc, nsINode* aNode)
    1765             : {
    1766           0 :   return aCurrentDoc->GetShell() && aNode->IsElement() &&
    1767           0 :          aNode->AsElement()->GetPrimaryFrame();
    1768             : }
    1769             : 
    1770             : bool
    1771           0 : OwnedByBindingManager(nsIDocument* aCurrentDoc, nsINode* aNode)
    1772             : {
    1773           0 :   return aNode->IsElement() && aNode->AsElement()->GetXBLBinding();
    1774             : }
    1775             : 
    1776             : // CanSkip checks if aNode is known-live, and if it is, returns true. If aNode
    1777             : // is in a known-live DOM tree, CanSkip may also remove other objects from
    1778             : // purple buffer and unmark event listeners and user data.  If the root of the
    1779             : // DOM tree is a document, less optimizations are done since checking the
    1780             : // liveness of the current document is usually fast and we don't want slow down
    1781             : // such common cases.
    1782             : bool
    1783           0 : FragmentOrElement::CanSkip(nsINode* aNode, bool aRemovingAllowed)
    1784             : {
    1785             :   // Don't try to optimize anything during shutdown.
    1786           0 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    1787           0 :     return false;
    1788             :   }
    1789             : 
    1790           0 :   bool unoptimizable = aNode->UnoptimizableCCNode();
    1791           0 :   nsIDocument* currentDoc = aNode->GetUncomposedDoc();
    1792           0 :   if (currentDoc && IsCertainlyAliveNode(aNode, currentDoc) &&
    1793           0 :       (!unoptimizable || NodeHasActiveFrame(currentDoc, aNode) ||
    1794           0 :        OwnedByBindingManager(currentDoc, aNode))) {
    1795           0 :     MarkNodeChildren(aNode);
    1796           0 :     return true;
    1797             :   }
    1798             : 
    1799           0 :   if (unoptimizable) {
    1800           0 :     return false;
    1801             :   }
    1802             : 
    1803           0 :   nsINode* root = currentDoc ? static_cast<nsINode*>(currentDoc) :
    1804           0 :                                FindOptimizableSubtreeRoot(aNode);
    1805           0 :   if (!root) {
    1806           0 :     return false;
    1807             :   }
    1808             : 
    1809             :   // Subtree has been traversed already, and aNode has
    1810             :   // been handled in a way that doesn't require revisiting it.
    1811           0 :   if (root->IsPurpleRoot()) {
    1812           0 :     return false;
    1813             :   }
    1814             : 
    1815             :   // nodesToClear contains nodes which are either purple or
    1816             :   // gray.
    1817           0 :   AutoTArray<nsIContent*, 1020> nodesToClear;
    1818             : 
    1819           0 :   bool foundLiveWrapper = root->HasKnownLiveWrapper();
    1820           0 :   bool domOnlyCycle = false;
    1821           0 :   if (root != currentDoc) {
    1822           0 :     currentDoc = nullptr;
    1823           0 :     if (!foundLiveWrapper) {
    1824           0 :       domOnlyCycle = static_cast<nsIContent*>(root)->OwnedOnlyByTheDOMTree();
    1825             :     }
    1826           0 :     if (ShouldClearPurple(static_cast<nsIContent*>(root))) {
    1827           0 :       nodesToClear.AppendElement(static_cast<nsIContent*>(root));
    1828             :     }
    1829             :   }
    1830             : 
    1831             :   // Traverse the subtree and check if we could know without CC
    1832             :   // that it is known-live.
    1833             :   // Note, this traverse is non-virtual and inline, so it should be a lot faster
    1834             :   // than CC's generic traverse.
    1835           0 :   for (nsIContent* node = root->GetFirstChild(); node;
    1836           0 :        node = node->GetNextNode(root)) {
    1837           0 :     foundLiveWrapper = foundLiveWrapper || node->HasKnownLiveWrapper();
    1838           0 :     if (foundLiveWrapper) {
    1839           0 :       domOnlyCycle = false;
    1840           0 :       if (currentDoc) {
    1841             :         // If we can mark the whole document live, no need to optimize
    1842             :         // so much, since when the next purple node in the document will be
    1843             :         // handled, it is fast to check that the currentDoc is in CCGeneration.
    1844           0 :         break;
    1845             :       }
    1846             :       // No need to put stuff to the nodesToClear array, if we can clear it
    1847             :       // already here.
    1848           0 :       if (node->IsPurple() && (node != aNode || aRemovingAllowed)) {
    1849           0 :         node->RemovePurple();
    1850             :       }
    1851           0 :       MarkNodeChildren(node);
    1852             :     } else {
    1853           0 :       domOnlyCycle = domOnlyCycle && node->OwnedOnlyByTheDOMTree();
    1854           0 :       if (ShouldClearPurple(node)) {
    1855             :         // Collect interesting nodes which we can clear if we find that
    1856             :         // they are kept alive in a known-live tree or are in a DOM-only cycle.
    1857           0 :         nodesToClear.AppendElement(node);
    1858             :       }
    1859             :     }
    1860             :   }
    1861             : 
    1862           0 :   if (!currentDoc || !foundLiveWrapper) {
    1863           0 :     root->SetIsPurpleRoot(true);
    1864           0 :     if (domOnlyCycle) {
    1865           0 :       if (!gNodesToUnbind) {
    1866           0 :         gNodesToUnbind = new AutoTArray<nsIContent*, 1020>();
    1867             :       }
    1868           0 :       gNodesToUnbind->AppendElement(static_cast<nsIContent*>(root));
    1869           0 :       for (uint32_t i = 0; i < nodesToClear.Length(); ++i) {
    1870           0 :         nsIContent* n = nodesToClear[i];
    1871           0 :         if ((n != aNode || aRemovingAllowed) && n->IsPurple()) {
    1872           0 :           n->RemovePurple();
    1873             :         }
    1874             :       }
    1875           0 :       return true;
    1876             :     } else {
    1877           0 :       if (!gPurpleRoots) {
    1878           0 :         gPurpleRoots = new AutoTArray<nsINode*, 1020>();
    1879             :       }
    1880           0 :       gPurpleRoots->AppendElement(root);
    1881             :     }
    1882             :   }
    1883             : 
    1884           0 :   if (!foundLiveWrapper) {
    1885           0 :     return false;
    1886             :   }
    1887             : 
    1888           0 :   if (currentDoc) {
    1889             :     // Special case documents. If we know the document is known-live,
    1890             :     // we can mark the document to be in CCGeneration.
    1891             :     currentDoc->
    1892           0 :       MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
    1893           0 :     MarkNodeChildren(currentDoc);
    1894             :   }
    1895             : 
    1896             :   // Subtree is known-live, so we can remove purple nodes from
    1897             :   // purple buffer and mark stuff that to be certainly alive.
    1898           0 :   for (uint32_t i = 0; i < nodesToClear.Length(); ++i) {
    1899           0 :     nsIContent* n = nodesToClear[i];
    1900           0 :     MarkNodeChildren(n);
    1901             :     // Can't remove currently handled purple node,
    1902             :     // unless aRemovingAllowed is true.
    1903           0 :     if ((n != aNode || aRemovingAllowed) && n->IsPurple()) {
    1904           0 :       n->RemovePurple();
    1905             :     }
    1906             :   }
    1907           0 :   return true;
    1908             : }
    1909             : 
    1910             : bool
    1911           0 : FragmentOrElement::CanSkipThis(nsINode* aNode)
    1912             : {
    1913           0 :   if (nsCCUncollectableMarker::sGeneration == 0) {
    1914           0 :     return false;
    1915             :   }
    1916           0 :   if (aNode->HasKnownLiveWrapper()) {
    1917           0 :     return true;
    1918             :   }
    1919           0 :   nsIDocument* c = aNode->GetUncomposedDoc();
    1920             :   return
    1921           0 :     ((c && IsCertainlyAliveNode(aNode, c)) || aNode->InCCBlackTree()) &&
    1922           0 :     !NeedsScriptTraverse(aNode);
    1923             : }
    1924             : 
    1925             : void
    1926           3 : FragmentOrElement::InitCCCallbacks()
    1927             : {
    1928           3 :   nsCycleCollector_setForgetSkippableCallback(ClearCycleCollectorCleanupData);
    1929           3 :   nsCycleCollector_setBeforeUnlinkCallback(ClearBlackMarkedNodes);
    1930           3 : }
    1931             : 
    1932           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(FragmentOrElement)
    1933           0 :   return FragmentOrElement::CanSkip(tmp, aRemovingAllowed);
    1934             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    1935             : 
    1936           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(FragmentOrElement)
    1937           0 :   return FragmentOrElement::CanSkipInCC(tmp);
    1938             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    1939             : 
    1940           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(FragmentOrElement)
    1941           0 :   return FragmentOrElement::CanSkipThis(tmp);
    1942             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    1943             : 
    1944             : static const char* kNSURIs[] = {
    1945             :   " ([none])",
    1946             :   " (xmlns)",
    1947             :   " (xml)",
    1948             :   " (xhtml)",
    1949             :   " (XLink)",
    1950             :   " (XSLT)",
    1951             :   " (XBL)",
    1952             :   " (MathML)",
    1953             :   " (RDF)",
    1954             :   " (XUL)",
    1955             :   " (SVG)",
    1956             :   " (XML Events)"
    1957             : };
    1958             : 
    1959         432 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
    1960         432 :   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
    1961             :     char name[512];
    1962           0 :     uint32_t nsid = tmp->GetNameSpaceID();
    1963           0 :     nsAtomCString localName(tmp->NodeInfo()->NameAtom());
    1964           0 :     nsAutoCString uri;
    1965           0 :     if (tmp->OwnerDoc()->GetDocumentURI()) {
    1966           0 :       uri = tmp->OwnerDoc()->GetDocumentURI()->GetSpecOrDefault();
    1967             :     }
    1968             : 
    1969           0 :     nsAutoString id;
    1970           0 :     nsIAtom* idAtom = tmp->GetID();
    1971           0 :     if (idAtom) {
    1972           0 :       id.AppendLiteral(" id='");
    1973           0 :       id.Append(nsDependentAtomString(idAtom));
    1974           0 :       id.Append('\'');
    1975             :     }
    1976             : 
    1977           0 :     nsAutoString classes;
    1978           0 :     const nsAttrValue* classAttrValue = tmp->IsElement() ?
    1979           0 :       tmp->AsElement()->GetClasses() : nullptr;
    1980           0 :     if (classAttrValue) {
    1981           0 :       classes.AppendLiteral(" class='");
    1982           0 :       nsAutoString classString;
    1983           0 :       classAttrValue->ToString(classString);
    1984           0 :       classString.ReplaceChar(char16_t('\n'), char16_t(' '));
    1985           0 :       classes.Append(classString);
    1986           0 :       classes.Append('\'');
    1987             :     }
    1988             : 
    1989           0 :     nsAutoCString orphan;
    1990           0 :     if (!tmp->IsInUncomposedDoc() &&
    1991             :         // Ignore xbl:content, which is never in the document and hence always
    1992             :         // appears to be orphaned.
    1993           0 :         !tmp->NodeInfo()->Equals(nsGkAtoms::content, kNameSpaceID_XBL)) {
    1994           0 :       orphan.AppendLiteral(" (orphan)");
    1995             :     }
    1996             : 
    1997           0 :     const char* nsuri = nsid < ArrayLength(kNSURIs) ? kNSURIs[nsid] : "";
    1998           0 :     SprintfLiteral(name, "FragmentOrElement%s %s%s%s%s %s",
    1999             :                    nsuri,
    2000             :                    localName.get(),
    2001           0 :                    NS_ConvertUTF16toUTF8(id).get(),
    2002           0 :                    NS_ConvertUTF16toUTF8(classes).get(),
    2003             :                    orphan.get(),
    2004           0 :                    uri.get());
    2005           0 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
    2006             :   }
    2007             :   else {
    2008         432 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(FragmentOrElement, tmp->mRefCnt.get())
    2009             :   }
    2010             : 
    2011         432 :   if (!nsINode::Traverse(tmp, cb)) {
    2012           0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
    2013             :   }
    2014             : 
    2015         432 :   tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
    2016             : 
    2017             :   // Check that whenever we have effect properties, MayHaveAnimations is set.
    2018             : #ifdef DEBUG
    2019         432 :   nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms();
    2020        1728 :   for (uint32_t i = 0; effectProps[i]; ++i) {
    2021        1296 :     MOZ_ASSERT_IF(tmp->GetProperty(effectProps[i]), tmp->MayHaveAnimations());
    2022             :   }
    2023             : #endif
    2024             : 
    2025         432 :   if (tmp->HasProperties()) {
    2026           1 :     if (tmp->IsHTMLElement() || tmp->IsSVGElement()) {
    2027           0 :       nsIAtom*** props = Element::HTMLSVGPropertiesToTraverseAndUnlink();
    2028           0 :       for (uint32_t i = 0; props[i]; ++i) {
    2029             :         nsISupports* property =
    2030           0 :           static_cast<nsISupports*>(tmp->GetProperty(*props[i]));
    2031           0 :         cb.NoteXPCOMChild(property);
    2032             :       }
    2033           0 :       if (tmp->MayHaveAnimations()) {
    2034           0 :         nsIAtom** effectProps = EffectSet::GetEffectSetPropertyAtoms();
    2035           0 :         for (uint32_t i = 0; effectProps[i]; ++i) {
    2036             :           EffectSet* effectSet =
    2037           0 :             static_cast<EffectSet*>(tmp->GetProperty(effectProps[i]));
    2038           0 :           if (effectSet) {
    2039           0 :             effectSet->Traverse(cb);
    2040             :           }
    2041             :         }
    2042             :       }
    2043             :     }
    2044             :   }
    2045             : 
    2046             :   // Traverse attribute names and child content.
    2047             :   {
    2048             :     uint32_t i;
    2049         432 :     uint32_t attrs = tmp->mAttrsAndChildren.AttrCount();
    2050        1990 :     for (i = 0; i < attrs; i++) {
    2051        1558 :       const nsAttrName* name = tmp->mAttrsAndChildren.AttrNameAt(i);
    2052        1558 :       if (!name->IsAtom()) {
    2053             :         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
    2054          63 :                                            "mAttrsAndChildren[i]->NodeInfo()");
    2055          63 :         cb.NoteNativeChild(name->NodeInfo(),
    2056         126 :                            NS_CYCLE_COLLECTION_PARTICIPANT(NodeInfo));
    2057             :       }
    2058             :     }
    2059             : 
    2060         432 :     uint32_t kids = tmp->mAttrsAndChildren.ChildCount();
    2061        1235 :     for (i = 0; i < kids; i++) {
    2062         803 :       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAttrsAndChildren[i]");
    2063         803 :       cb.NoteXPCOMChild(tmp->mAttrsAndChildren.GetSafeChildAt(i));
    2064             :     }
    2065             :   }
    2066             : 
    2067             :   // Traverse any DOM slots of interest.
    2068             :   {
    2069         432 :     nsDOMSlots *slots = tmp->GetExistingDOMSlots();
    2070         432 :     if (slots) {
    2071         290 :       slots->Traverse(cb, tmp->IsXULElement());
    2072             :     }
    2073             :   }
    2074         432 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2075             : 
    2076             : 
    2077       20883 : NS_INTERFACE_MAP_BEGIN(FragmentOrElement)
    2078       20883 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    2079       20099 :   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(FragmentOrElement)
    2080       16785 :   NS_INTERFACE_MAP_ENTRY(Element)
    2081       14994 :   NS_INTERFACE_MAP_ENTRY(nsIContent)
    2082        7380 :   NS_INTERFACE_MAP_ENTRY(nsINode)
    2083        4259 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    2084        4244 :   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
    2085        1613 :   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
    2086             :                                  new nsNodeSupportsWeakRefTearoff(this))
    2087             :   // DOM bindings depend on the identity pointer being the
    2088             :   // same as nsINode (which nsIContent inherits).
    2089        1359 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
    2090         514 : NS_INTERFACE_MAP_END
    2091             : 
    2092       40755 : NS_IMPL_CYCLE_COLLECTING_ADDREF(FragmentOrElement)
    2093       31949 : NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(FragmentOrElement,
    2094             :                                                    nsNodeUtils::LastRelease(this))
    2095             : 
    2096             : //----------------------------------------------------------------------
    2097             : 
    2098             : nsresult
    2099         337 : FragmentOrElement::CopyInnerTo(FragmentOrElement* aDst,
    2100             :                                bool aPreallocateChildren)
    2101             : {
    2102         337 :   nsresult rv = aDst->mAttrsAndChildren.EnsureCapacityToClone(mAttrsAndChildren,
    2103         337 :                                                               aPreallocateChildren);
    2104         337 :   NS_ENSURE_SUCCESS(rv, rv);
    2105             : 
    2106         337 :   uint32_t i, count = mAttrsAndChildren.AttrCount();
    2107         568 :   for (i = 0; i < count; ++i) {
    2108         231 :     const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
    2109         231 :     const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
    2110         462 :     nsAutoString valStr;
    2111         231 :     value->ToString(valStr);
    2112         462 :     rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
    2113         462 :                                 name->GetPrefix(), valStr, false);
    2114         231 :     NS_ENSURE_SUCCESS(rv, rv);
    2115             :   }
    2116             : 
    2117         337 :   return NS_OK;
    2118             : }
    2119             : 
    2120             : const nsTextFragment*
    2121           0 : FragmentOrElement::GetText()
    2122             : {
    2123           0 :   return nullptr;
    2124             : }
    2125             : 
    2126             : uint32_t
    2127           0 : FragmentOrElement::TextLength() const
    2128             : {
    2129             :   // We can remove this assertion if it turns out to be useful to be able
    2130             :   // to depend on this returning 0
    2131           0 :   NS_NOTREACHED("called FragmentOrElement::TextLength");
    2132             : 
    2133           0 :   return 0;
    2134             : }
    2135             : 
    2136             : nsresult
    2137           0 : FragmentOrElement::SetText(const char16_t* aBuffer, uint32_t aLength,
    2138             :                           bool aNotify)
    2139             : {
    2140           0 :   NS_ERROR("called FragmentOrElement::SetText");
    2141             : 
    2142           0 :   return NS_ERROR_FAILURE;
    2143             : }
    2144             : 
    2145             : nsresult
    2146           0 : FragmentOrElement::AppendText(const char16_t* aBuffer, uint32_t aLength,
    2147             :                              bool aNotify)
    2148             : {
    2149           0 :   NS_ERROR("called FragmentOrElement::AppendText");
    2150             : 
    2151           0 :   return NS_ERROR_FAILURE;
    2152             : }
    2153             : 
    2154             : bool
    2155           0 : FragmentOrElement::TextIsOnlyWhitespace()
    2156             : {
    2157           0 :   return false;
    2158             : }
    2159             : 
    2160             : bool
    2161           0 : FragmentOrElement::ThreadSafeTextIsOnlyWhitespace() const
    2162             : {
    2163           0 :   return false;
    2164             : }
    2165             : 
    2166             : bool
    2167           0 : FragmentOrElement::HasTextForTranslation()
    2168             : {
    2169           0 :   return false;
    2170             : }
    2171             : 
    2172             : void
    2173           0 : FragmentOrElement::AppendTextTo(nsAString& aResult)
    2174             : {
    2175             :   // We can remove this assertion if it turns out to be useful to be able
    2176             :   // to depend on this appending nothing.
    2177           0 :   NS_NOTREACHED("called FragmentOrElement::TextLength");
    2178           0 : }
    2179             : 
    2180             : bool
    2181           0 : FragmentOrElement::AppendTextTo(nsAString& aResult, const mozilla::fallible_t&)
    2182             : {
    2183             :   // We can remove this assertion if it turns out to be useful to be able
    2184             :   // to depend on this appending nothing.
    2185           0 :   NS_NOTREACHED("called FragmentOrElement::TextLength");
    2186             : 
    2187           0 :   return false;
    2188             : }
    2189             : 
    2190             : uint32_t
    2191        3780 : FragmentOrElement::GetChildCount() const
    2192             : {
    2193        3780 :   return mAttrsAndChildren.ChildCount();
    2194             : }
    2195             : 
    2196             : nsIContent *
    2197        1087 : FragmentOrElement::GetChildAt(uint32_t aIndex) const
    2198             : {
    2199        1087 :   return mAttrsAndChildren.GetSafeChildAt(aIndex);
    2200             : }
    2201             : 
    2202             : nsIContent * const *
    2203        1023 : FragmentOrElement::GetChildArray(uint32_t* aChildCount) const
    2204             : {
    2205        1023 :   return mAttrsAndChildren.GetChildArray(aChildCount);
    2206             : }
    2207             : 
    2208             : int32_t
    2209         729 : FragmentOrElement::IndexOf(const nsINode* aPossibleChild) const
    2210             : {
    2211         729 :   return mAttrsAndChildren.IndexOfChild(aPossibleChild);
    2212             : }
    2213             : 
    2214             : static inline bool
    2215           0 : IsVoidTag(nsIAtom* aTag)
    2216             : {
    2217             :   static const nsIAtom* voidElements[] = {
    2218             :     nsGkAtoms::area, nsGkAtoms::base, nsGkAtoms::basefont,
    2219             :     nsGkAtoms::bgsound, nsGkAtoms::br, nsGkAtoms::col,
    2220             :     nsGkAtoms::embed, nsGkAtoms::frame,
    2221             :     nsGkAtoms::hr, nsGkAtoms::img, nsGkAtoms::input,
    2222             :     nsGkAtoms::keygen, nsGkAtoms::link, nsGkAtoms::meta,
    2223             :     nsGkAtoms::param, nsGkAtoms::source, nsGkAtoms::track,
    2224             :     nsGkAtoms::wbr
    2225           0 :   };
    2226             : 
    2227           0 :   static mozilla::BloomFilter<12, nsIAtom> sFilter;
    2228             :   static bool sInitialized = false;
    2229           0 :   if (!sInitialized) {
    2230           0 :     sInitialized = true;
    2231           0 :     for (uint32_t i = 0; i < ArrayLength(voidElements); ++i) {
    2232           0 :       sFilter.add(voidElements[i]);
    2233             :     }
    2234             :   }
    2235             : 
    2236           0 :   if (sFilter.mightContain(aTag)) {
    2237           0 :     for (uint32_t i = 0; i < ArrayLength(voidElements); ++i) {
    2238           0 :       if (aTag == voidElements[i]) {
    2239           0 :         return true;
    2240             :       }
    2241             :     }
    2242             :   }
    2243           0 :   return false;
    2244             : }
    2245             : 
    2246             : /* static */
    2247             : bool
    2248           0 : FragmentOrElement::IsHTMLVoid(nsIAtom* aLocalName)
    2249             : {
    2250           0 :   return aLocalName && IsVoidTag(aLocalName);
    2251             : }
    2252             : 
    2253             : void
    2254           0 : FragmentOrElement::GetMarkup(bool aIncludeSelf, nsAString& aMarkup)
    2255             : {
    2256           0 :   aMarkup.Truncate();
    2257             : 
    2258           0 :   nsIDocument* doc = OwnerDoc();
    2259           0 :   if (IsInHTMLDocument()) {
    2260           0 :     nsContentUtils::SerializeNodeToMarkup(this, !aIncludeSelf, aMarkup);
    2261           0 :     return;
    2262             :   }
    2263             : 
    2264           0 :   nsAutoString contentType;
    2265           0 :   doc->GetContentType(contentType);
    2266           0 :   bool tryToCacheEncoder = !aIncludeSelf;
    2267             : 
    2268           0 :   nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
    2269           0 :   if (!docEncoder) {
    2270             :     docEncoder =
    2271           0 :       do_CreateInstance(PromiseFlatCString(
    2272           0 :         nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) +
    2273           0 :         NS_ConvertUTF16toUTF8(contentType)
    2274           0 :       ).get());
    2275             :   }
    2276           0 :   if (!docEncoder) {
    2277             :     // This could be some type for which we create a synthetic document.  Try
    2278             :     // again as XML
    2279           0 :     contentType.AssignLiteral("application/xml");
    2280           0 :     docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "application/xml");
    2281             :     // Don't try to cache the encoder since it would point to a different
    2282             :     // contentType once it has been reinitialized.
    2283           0 :     tryToCacheEncoder = false;
    2284             :   }
    2285             : 
    2286           0 :   NS_ENSURE_TRUE_VOID(docEncoder);
    2287             : 
    2288             :   uint32_t flags = nsIDocumentEncoder::OutputEncodeBasicEntities |
    2289             :                    // Output DOM-standard newlines
    2290             :                    nsIDocumentEncoder::OutputLFLineBreak |
    2291             :                    // Don't do linebreaking that's not present in
    2292             :                    // the source
    2293             :                    nsIDocumentEncoder::OutputRaw |
    2294             :                    // Only check for mozdirty when necessary (bug 599983)
    2295           0 :                    nsIDocumentEncoder::OutputIgnoreMozDirty;
    2296             : 
    2297           0 :   if (IsEditable()) {
    2298           0 :     nsCOMPtr<Element> elem = do_QueryInterface(this);
    2299           0 :     TextEditor* textEditor = elem ? elem->GetTextEditorInternal() : nullptr;
    2300           0 :     if (textEditor && textEditor->OutputsMozDirty()) {
    2301           0 :       flags &= ~nsIDocumentEncoder::OutputIgnoreMozDirty;
    2302             :     }
    2303             :   }
    2304             : 
    2305           0 :   DebugOnly<nsresult> rv = docEncoder->NativeInit(doc, contentType, flags);
    2306           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    2307             : 
    2308           0 :   if (aIncludeSelf) {
    2309           0 :     docEncoder->SetNativeNode(this);
    2310             :   } else {
    2311           0 :     docEncoder->SetNativeContainerNode(this);
    2312             :   }
    2313           0 :   rv = docEncoder->EncodeToString(aMarkup);
    2314           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
    2315           0 :   if (tryToCacheEncoder) {
    2316           0 :     doc->SetCachedEncoder(docEncoder.forget());
    2317             :   }
    2318             : }
    2319             : 
    2320             : static bool
    2321           0 : ContainsMarkup(const nsAString& aStr)
    2322             : {
    2323             :   // Note: we can't use FindCharInSet because null is one of the characters we
    2324             :   // want to search for.
    2325           0 :   const char16_t* start = aStr.BeginReading();
    2326           0 :   const char16_t* end = aStr.EndReading();
    2327             : 
    2328           0 :   while (start != end) {
    2329           0 :     char16_t c = *start;
    2330           0 :     if (c == char16_t('<') ||
    2331           0 :         c == char16_t('&') ||
    2332           0 :         c == char16_t('\r') ||
    2333             :         c == char16_t('\0')) {
    2334           0 :       return true;
    2335             :     }
    2336           0 :     ++start;
    2337             :   }
    2338             : 
    2339           0 :   return false;
    2340             : }
    2341             : 
    2342             : void
    2343           0 : FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError)
    2344             : {
    2345           0 :   FragmentOrElement* target = this;
    2346             :   // Handle template case.
    2347           0 :   if (nsNodeUtils::IsTemplateElement(target)) {
    2348             :     DocumentFragment* frag =
    2349           0 :       static_cast<HTMLTemplateElement*>(target)->Content();
    2350           0 :     MOZ_ASSERT(frag);
    2351           0 :     target = frag;
    2352             :   }
    2353             : 
    2354             :   // Fast-path for strings with no markup. Limit this to short strings, to
    2355             :   // avoid ContainsMarkup taking too long. The choice for 100 is based on
    2356             :   // gut feeling.
    2357             :   //
    2358             :   // Don't do this for elements with a weird parser insertion mode, for
    2359             :   // instance setting innerHTML = "" on a <html> element should add the
    2360             :   // optional <head> and <body> elements.
    2361           0 :   if (!target->HasWeirdParserInsertionMode() &&
    2362           0 :       aInnerHTML.Length() < 100 && !ContainsMarkup(aInnerHTML)) {
    2363           0 :     aError = nsContentUtils::SetNodeTextContent(target, aInnerHTML, false);
    2364           0 :     return;
    2365             :   }
    2366             : 
    2367           0 :   nsIDocument* doc = target->OwnerDoc();
    2368             : 
    2369             :   // Batch possible DOMSubtreeModified events.
    2370           0 :   mozAutoSubtreeModified subtree(doc, nullptr);
    2371             : 
    2372           0 :   target->FireNodeRemovedForChildren();
    2373             : 
    2374             :   // Needed when innerHTML is used in combination with contenteditable
    2375           0 :   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
    2376             : 
    2377             :   // Remove childnodes.
    2378           0 :   uint32_t childCount = target->GetChildCount();
    2379           0 :   nsAutoMutationBatch mb(target, true, false);
    2380           0 :   for (uint32_t i = 0; i < childCount; ++i) {
    2381           0 :     target->RemoveChildAt(0, true);
    2382             :   }
    2383           0 :   mb.RemovalDone();
    2384             : 
    2385           0 :   nsAutoScriptLoaderDisabler sld(doc);
    2386             : 
    2387           0 :   nsIAtom* contextLocalName = NodeInfo()->NameAtom();
    2388           0 :   int32_t contextNameSpaceID = GetNameSpaceID();
    2389             : 
    2390           0 :   ShadowRoot* shadowRoot = ShadowRoot::FromNode(this);
    2391           0 :   if (shadowRoot) {
    2392             :     // Fix up the context to be the host of the ShadowRoot.
    2393           0 :     contextLocalName = shadowRoot->GetHost()->NodeInfo()->NameAtom();
    2394           0 :     contextNameSpaceID = shadowRoot->GetHost()->GetNameSpaceID();
    2395             :   }
    2396             : 
    2397           0 :   if (doc->IsHTMLDocument()) {
    2398           0 :     int32_t oldChildCount = target->GetChildCount();
    2399           0 :     aError = nsContentUtils::ParseFragmentHTML(aInnerHTML,
    2400             :                                                target,
    2401             :                                                contextLocalName,
    2402             :                                                contextNameSpaceID,
    2403           0 :                                                doc->GetCompatibilityMode() ==
    2404             :                                                  eCompatibility_NavQuirks,
    2405           0 :                                                true);
    2406           0 :     mb.NodesAdded();
    2407             :     // HTML5 parser has notified, but not fired mutation events.
    2408             :     nsContentUtils::FireMutationEventsForDirectParsing(doc, target,
    2409           0 :                                                        oldChildCount);
    2410             :   } else {
    2411             :     RefPtr<DocumentFragment> df =
    2412           0 :       nsContentUtils::CreateContextualFragment(target, aInnerHTML, true, aError);
    2413           0 :     if (!aError.Failed()) {
    2414             :       // Suppress assertion about node removal mutation events that can't have
    2415             :       // listeners anyway, because no one has had the chance to register mutation
    2416             :       // listeners on the fragment that comes from the parser.
    2417           0 :       nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
    2418             : 
    2419           0 :       static_cast<nsINode*>(target)->AppendChild(*df, aError);
    2420           0 :       mb.NodesAdded();
    2421             :     }
    2422             :   }
    2423             : }
    2424             : 
    2425             : nsINode::nsSlots*
    2426         275 : FragmentOrElement::CreateSlots()
    2427             : {
    2428         275 :   return new nsDOMSlots();
    2429             : }
    2430             : 
    2431             : void
    2432           4 : FragmentOrElement::FireNodeRemovedForChildren()
    2433             : {
    2434           4 :   nsIDocument* doc = OwnerDoc();
    2435             :   // Optimize the common case
    2436           4 :   if (!nsContentUtils::
    2437           4 :         HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
    2438           4 :     return;
    2439             :   }
    2440             : 
    2441           0 :   nsCOMPtr<nsIDocument> owningDoc = doc;
    2442             : 
    2443           0 :   nsCOMPtr<nsINode> child;
    2444           0 :   for (child = GetFirstChild();
    2445           0 :        child && child->GetParentNode() == this;
    2446           0 :        child = child->GetNextSibling()) {
    2447           0 :     nsContentUtils::MaybeFireNodeRemoved(child, this, doc);
    2448             :   }
    2449             : }
    2450             : 
    2451             : size_t
    2452         130 : FragmentOrElement::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
    2453             : {
    2454         130 :   size_t n = 0;
    2455         130 :   n += nsIContent::SizeOfExcludingThis(aMallocSizeOf);
    2456         130 :   n += mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
    2457             : 
    2458         130 :   nsDOMSlots* slots = GetExistingDOMSlots();
    2459         130 :   if (slots) {
    2460           5 :     n += slots->SizeOfIncludingThis(aMallocSizeOf);
    2461             :   }
    2462             : 
    2463         130 :   return n;
    2464             : }
    2465             : 
    2466             : void
    2467           0 : FragmentOrElement::SetIsElementInStyleScopeFlagOnSubtree(bool aInStyleScope)
    2468             : {
    2469           0 :   if (aInStyleScope && IsElementInStyleScope()) {
    2470           0 :     return;
    2471             :   }
    2472             : 
    2473           0 :   if (IsElement()) {
    2474           0 :     SetIsElementInStyleScope(aInStyleScope);
    2475           0 :     SetIsElementInStyleScopeFlagOnShadowTree(aInStyleScope);
    2476             :   }
    2477             : 
    2478           0 :   nsIContent* n = GetNextNode(this);
    2479           0 :   while (n) {
    2480           0 :     if (n->IsElementInStyleScope()) {
    2481           0 :       n = n->GetNextNonChildNode(this);
    2482             :     } else {
    2483           0 :       if (n->IsElement()) {
    2484           0 :         n->SetIsElementInStyleScope(aInStyleScope);
    2485           0 :         n->AsElement()->SetIsElementInStyleScopeFlagOnShadowTree(aInStyleScope);
    2486             :       }
    2487           0 :       n = n->GetNextNode(this);
    2488             :     }
    2489             :   }
    2490             : }
    2491             : 
    2492             : void
    2493        4709 : FragmentOrElement::SetIsElementInStyleScopeFlagOnShadowTree(bool aInStyleScope)
    2494             : {
    2495        4709 :   NS_ASSERTION(IsElement(), "calling SetIsElementInStyleScopeFlagOnShadowTree "
    2496             :                             "on a non-Element is useless");
    2497        4709 :   ShadowRoot* shadowRoot = GetShadowRoot();
    2498        4709 :   while (shadowRoot) {
    2499           0 :     shadowRoot->SetIsElementInStyleScopeFlagOnSubtree(aInStyleScope);
    2500           0 :     shadowRoot = shadowRoot->GetOlderShadowRoot();
    2501             :   }
    2502        4709 : }

Generated by: LCOV version 1.13