LCOV - code coverage report
Current view: top level - layout/style - nsStyleSet.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 752 1249 60.2 %
Date: 2017-07-14 16:53:18 Functions: 71 115 61.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  * the container for the style sheets that apply to a presentation, and
       8             :  * the internal API that the style system exposes for creating (and
       9             :  * potentially re-creating) style contexts
      10             :  */
      11             : 
      12             : #include "nsStyleSet.h"
      13             : 
      14             : #include "mozilla/ArrayUtils.h"
      15             : #include "mozilla/StyleSheetInlines.h"
      16             : #include "mozilla/EffectCompositor.h"
      17             : #include "mozilla/EnumeratedRange.h"
      18             : #include "mozilla/EventStates.h"
      19             : #include "mozilla/MemoryReporting.h"
      20             : #include "mozilla/RuleProcessorCache.h"
      21             : #include "mozilla/StyleSheetInlines.h"
      22             : #include "nsIDocumentInlines.h"
      23             : #include "nsRuleWalker.h"
      24             : #include "nsStyleContext.h"
      25             : #include "mozilla/css/StyleRule.h"
      26             : #include "nsCSSAnonBoxes.h"
      27             : #include "nsCSSPseudoElements.h"
      28             : #include "nsCSSRuleProcessor.h"
      29             : #include "nsDataHashtable.h"
      30             : #include "nsIContent.h"
      31             : #include "nsRuleData.h"
      32             : #include "nsRuleProcessorData.h"
      33             : #include "nsAnimationManager.h"
      34             : #include "nsStyleSheetService.h"
      35             : #include "mozilla/dom/Element.h"
      36             : #include "mozilla/dom/ShadowRoot.h"
      37             : #include "GeckoProfiler.h"
      38             : #include "nsHTMLCSSStyleSheet.h"
      39             : #include "nsHTMLStyleSheet.h"
      40             : #include "nsCSSRules.h"
      41             : #include "nsPrintfCString.h"
      42             : #include "nsIFrame.h"
      43             : #include "mozilla/RestyleManager.h"
      44             : #include "mozilla/RestyleManagerInlines.h"
      45             : #include "nsQueryObject.h"
      46             : #include "nsStyleContextInlines.h"
      47             : 
      48             : #include <inttypes.h>
      49             : 
      50             : using namespace mozilla;
      51             : using namespace mozilla::dom;
      52             : 
      53         430 : NS_IMPL_ISUPPORTS(nsEmptyStyleRule, nsIStyleRule)
      54             : 
      55             : /* virtual */ void
      56          46 : nsEmptyStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
      57             : {
      58          46 : }
      59             : 
      60             : /* virtual */ bool
      61           0 : nsEmptyStyleRule::MightMapInheritedStyleData()
      62             : {
      63           0 :   return false;
      64             : }
      65             : 
      66             : /* virtual */ bool
      67           0 : nsEmptyStyleRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
      68             :                                                 nsCSSValue* aValue)
      69             : {
      70           0 :   MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
      71             :   return false;
      72             : }
      73             : 
      74             : #ifdef DEBUG
      75             : /* virtual */ void
      76           0 : nsEmptyStyleRule::List(FILE* out, int32_t aIndent) const
      77             : {
      78           0 :   nsAutoCString indentStr;
      79           0 :   for (int32_t index = aIndent; --index >= 0; ) {
      80           0 :     indentStr.AppendLiteral("  ");
      81             :   }
      82           0 :   fprintf_stderr(out, "%s[empty style rule] {}\n", indentStr.get());
      83           0 : }
      84             : #endif
      85             : 
      86           0 : NS_IMPL_ISUPPORTS(nsInitialStyleRule, nsIStyleRule)
      87             : 
      88             : /* virtual */ void
      89           0 : nsInitialStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
      90             : {
      91             :   // Iterate over the property groups
      92           0 :   for (nsStyleStructID sid = nsStyleStructID(0);
      93           0 :        sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
      94           0 :     if (aRuleData->mSIDs & (1 << sid)) {
      95             :       // Iterate over nsCSSValues within the property group
      96             :       nsCSSValue * const value_start =
      97           0 :         aRuleData->mValueStorage + aRuleData->mValueOffsets[sid];
      98           0 :       for (nsCSSValue *value = value_start,
      99           0 :            *value_end = value + nsCSSProps::PropertyCountInStruct(sid);
     100           0 :            value != value_end; ++value) {
     101             :         // If MathML is disabled take care not to set MathML properties (or we
     102             :         // will trigger assertions in nsRuleNode)
     103           0 :         if (sid == eStyleStruct_Font &&
     104           0 :             !aRuleData->mPresContext->Document()->GetMathMLEnabled()) {
     105           0 :           size_t index = value - value_start;
     106           0 :           if (index == nsCSSProps::PropertyIndexInStruct(
     107           0 :                           eCSSProperty__moz_script_level) ||
     108           0 :               index == nsCSSProps::PropertyIndexInStruct(
     109           0 :                           eCSSProperty__moz_script_size_multiplier) ||
     110           0 :               index == nsCSSProps::PropertyIndexInStruct(
     111           0 :                           eCSSProperty__moz_script_min_size) ||
     112           0 :               index == nsCSSProps::PropertyIndexInStruct(
     113           0 :                           eCSSProperty__moz_math_variant) ||
     114           0 :               index == nsCSSProps::PropertyIndexInStruct(
     115             :                           eCSSProperty__moz_math_display)) {
     116           0 :             continue;
     117             :           }
     118             :         }
     119           0 :         if (value->GetUnit() == eCSSUnit_Null) {
     120           0 :           value->SetInitialValue();
     121             :         }
     122             :       }
     123             :     }
     124             :   }
     125           0 : }
     126             : 
     127             : /* virtual */ bool
     128           0 : nsInitialStyleRule::MightMapInheritedStyleData()
     129             : {
     130           0 :   return true;
     131             : }
     132             : 
     133             : /* virtual */ bool
     134           0 : nsInitialStyleRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
     135             :                                                   nsCSSValue* aValue)
     136             : {
     137           0 :   MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
     138             :   return false;
     139             : }
     140             : 
     141             : #ifdef DEBUG
     142             : /* virtual */ void
     143           0 : nsInitialStyleRule::List(FILE* out, int32_t aIndent) const
     144             : {
     145           0 :   nsAutoCString indentStr;
     146           0 :   for (int32_t index = aIndent; --index >= 0; ) {
     147           0 :     indentStr.AppendLiteral("  ");
     148             :   }
     149           0 :   fprintf_stderr(out, "%s[initial style rule] {}\n", indentStr.get());
     150           0 : }
     151             : #endif
     152             : 
     153          36 : NS_IMPL_ISUPPORTS(nsDisableTextZoomStyleRule, nsIStyleRule)
     154             : 
     155             : /* virtual */ void
     156           0 : nsDisableTextZoomStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
     157             : {
     158           0 :   if (!(aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Font)))
     159           0 :     return;
     160             : 
     161           0 :   nsCSSValue* value = aRuleData->ValueForTextZoom();
     162           0 :   if (value->GetUnit() == eCSSUnit_Null)
     163           0 :     value->SetNoneValue();
     164             : }
     165             : 
     166             : /* virtual */ bool
     167           0 : nsDisableTextZoomStyleRule::MightMapInheritedStyleData()
     168             : {
     169           0 :   return true;
     170             : }
     171             : 
     172             : /* virtual */ bool
     173           0 : nsDisableTextZoomStyleRule::
     174             : GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty, nsCSSValue* aValue)
     175             : {
     176           0 :   MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
     177             :   return false;
     178             : }
     179             : 
     180             : #ifdef DEBUG
     181             : /* virtual */ void
     182           0 : nsDisableTextZoomStyleRule::List(FILE* out, int32_t aIndent) const
     183             : {
     184           0 :   nsAutoCString indentStr;
     185           0 :   for (int32_t index = aIndent; --index >= 0; ) {
     186           0 :     indentStr.AppendLiteral("  ");
     187             :   }
     188           0 :   fprintf_stderr(out, "%s[disable text zoom style rule] {}\n", indentStr.get());
     189           0 : }
     190             : #endif
     191             : 
     192             : static const SheetType gCSSSheetTypes[] = {
     193             :   // From lowest to highest in cascading order.
     194             :   SheetType::Agent,
     195             :   SheetType::User,
     196             :   SheetType::Doc,
     197             :   SheetType::ScopedDoc,
     198             :   SheetType::Override
     199             : };
     200             : 
     201             : /* static */ bool
     202         320 : nsStyleSet::IsCSSSheetType(SheetType aSheetType)
     203             : {
     204         945 :   for (SheetType type : gCSSSheetTypes) {
     205         833 :     if (type == aSheetType) {
     206         208 :       return true;
     207             :     }
     208             :   }
     209         112 :   return false;
     210             : }
     211             : 
     212          28 : nsStyleSet::nsStyleSet()
     213             :   : mRuleTree(nullptr),
     214             :     mBatching(0),
     215             :     mStylesHaveChanged(0),
     216             :     mInShutdown(false),
     217             :     mInGC(false),
     218             :     mAuthorStyleDisabled(false),
     219             :     mInReconstruct(false),
     220             :     mInitFontFeatureValuesLookup(true),
     221             :     mNeedsRestyleAfterEnsureUniqueInner(false),
     222             :     mDirty(0),
     223             :     mRootStyleContextCount(0),
     224             : #ifdef DEBUG
     225             :     mOldRootNode(nullptr),
     226             : #endif
     227          28 :     mUnusedRuleNodeCount(0)
     228             : {
     229          28 : }
     230             : 
     231           8 : nsStyleSet::~nsStyleSet()
     232             : {
     233          24 :   for (SheetType type : gCSSSheetTypes) {
     234          62 :     for (CSSStyleSheet* sheet : mSheets[type]) {
     235          42 :       sheet->DropStyleSet(this);
     236             :     }
     237             :   }
     238             : 
     239             :   // drop reference to cached rule processors
     240             :   nsCSSRuleProcessor* rp;
     241           4 :   rp = static_cast<nsCSSRuleProcessor*>(mRuleProcessors[SheetType::Agent].get());
     242           4 :   if (rp) {
     243           4 :     MOZ_ASSERT(rp->IsShared());
     244           4 :     rp->ReleaseStyleSetRef();
     245             :   }
     246           4 :   rp = static_cast<nsCSSRuleProcessor*>(mRuleProcessors[SheetType::User].get());
     247           4 :   if (rp) {
     248           0 :     MOZ_ASSERT(rp->IsShared());
     249           0 :     rp->ReleaseStyleSetRef();
     250             :   }
     251           4 : }
     252             : 
     253             : size_t
     254          21 : nsStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     255             : {
     256          21 :   size_t n = aMallocSizeOf(this);
     257             : 
     258         210 :   for (SheetType type : MakeEnumeratedRange(SheetType::Count)) {
     259         189 :     if (mRuleProcessors[type]) {
     260         110 :       bool shared = false;
     261         110 :       if (type == SheetType::Agent || type == SheetType::User) {
     262             :         // The only two origins we consider caching rule processors for.
     263             :         nsCSSRuleProcessor* rp =
     264          21 :           static_cast<nsCSSRuleProcessor*>(mRuleProcessors[type].get());
     265          21 :         shared = rp->IsShared();
     266             :       }
     267         110 :       if (!shared) {
     268          89 :         n += mRuleProcessors[type]->SizeOfIncludingThis(aMallocSizeOf);
     269             :       }
     270             :     }
     271             :     // We don't own the sheets (either the nsLayoutStyleSheetCache singleton
     272             :     // or our document owns them).
     273         189 :     n += mSheets[type].ShallowSizeOfExcludingThis(aMallocSizeOf);
     274             :   }
     275             : 
     276          21 :   for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
     277           0 :     n += mScopedDocSheetRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
     278             :   }
     279          21 :   n += mScopedDocSheetRuleProcessors.ShallowSizeOfExcludingThis(aMallocSizeOf);
     280             : 
     281          21 :   return n;
     282             : }
     283             : 
     284             : void
     285          28 : nsStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
     286             : {
     287          28 :   mFirstLineRule = new nsEmptyStyleRule;
     288          28 :   mFirstLetterRule = new nsEmptyStyleRule;
     289          28 :   mPlaceholderRule = new nsEmptyStyleRule;
     290          28 :   mDisableTextZoomStyleRule = new nsDisableTextZoomStyleRule;
     291             : 
     292          28 :   mRuleTree = nsRuleNode::CreateRootNode(aPresContext);
     293          28 :   mBindingManager = aBindingManager;
     294             : 
     295             :   // Make an explicit GatherRuleProcessors call for the levels that
     296             :   // don't have style sheets.  The other levels will have their calls
     297             :   // triggered by DirtyRuleProcessors.
     298          28 :   GatherRuleProcessors(SheetType::PresHint);
     299          28 :   GatherRuleProcessors(SheetType::StyleAttr);
     300          28 :   GatherRuleProcessors(SheetType::Animation);
     301          28 :   GatherRuleProcessors(SheetType::Transition);
     302          28 : }
     303             : 
     304             : nsresult
     305           2 : nsStyleSet::BeginReconstruct()
     306             : {
     307           2 :   NS_ASSERTION(!mInReconstruct, "Unmatched begin/end?");
     308           2 :   NS_ASSERTION(mRuleTree, "Reconstructing before first construction?");
     309           2 :   mInReconstruct = true;
     310             : 
     311             :   // Clear any ArenaRefPtr-managed style contexts, as we don't want them
     312             :   // held on to after the rule tree has been reconstructed.
     313           2 :   PresContext()->PresShell()->ClearArenaRefPtrs(eArenaObjectID_GeckoStyleContext);
     314             : 
     315             :   // Clear our cached style contexts for non-inheriting anonymous boxes.
     316           2 :   ClearNonInheritingStyleContexts();
     317             : 
     318             : #ifdef DEBUG
     319           2 :   MOZ_ASSERT(!mOldRootNode);
     320           2 :   mOldRootNode = mRuleTree;
     321             : #endif
     322             : 
     323             :   // Create a new rule tree root, dropping the reference to our old rule tree.
     324             :   // After reconstruction, we will re-enable GC, and allow everything to be
     325             :   // collected.
     326           2 :   mRuleTree = nsRuleNode::CreateRootNode(mRuleTree->PresContext());
     327             : 
     328           2 :   return NS_OK;
     329             : }
     330             : 
     331             : void
     332           2 : nsStyleSet::EndReconstruct()
     333             : {
     334           2 :   NS_ASSERTION(mInReconstruct, "Unmatched begin/end?");
     335           2 :   mInReconstruct = false;
     336           2 :   GCRuleTrees();
     337           2 : }
     338             : 
     339             : typedef nsDataHashtable<nsPtrHashKey<nsINode>, uint32_t> ScopeDepthCache;
     340             : 
     341             : // Returns the depth of a style scope element, with 1 being the depth of
     342             : // a style scope element that has no ancestor style scope elements.  The
     343             : // depth does not count intervening non-scope elements.
     344             : static uint32_t
     345           0 : GetScopeDepth(nsINode* aScopeElement, ScopeDepthCache& aCache)
     346             : {
     347           0 :   nsINode* parent = aScopeElement->GetParent();
     348           0 :   if (!parent || !parent->IsElementInStyleScope()) {
     349           0 :     return 1;
     350             :   }
     351             : 
     352           0 :   uint32_t depth = aCache.Get(aScopeElement);
     353           0 :   if (!depth) {
     354           0 :     for (nsINode* n = parent; n; n = n->GetParent()) {
     355           0 :       if (n->IsScopedStyleRoot()) {
     356           0 :         depth = GetScopeDepth(n, aCache) + 1;
     357           0 :         aCache.Put(aScopeElement, depth);
     358           0 :         break;
     359             :       }
     360             :     }
     361             :   }
     362           0 :   return depth;
     363             : }
     364             : 
     365             : struct ScopedSheetOrder
     366             : {
     367             :   CSSStyleSheet* mSheet;
     368             :   uint32_t mDepth;
     369             :   uint32_t mOrder;
     370             : 
     371           0 :   bool operator==(const ScopedSheetOrder& aRHS) const
     372             :   {
     373           0 :     return mDepth == aRHS.mDepth &&
     374           0 :            mOrder == aRHS.mOrder;
     375             :   }
     376             : 
     377           0 :   bool operator<(const ScopedSheetOrder& aRHS) const
     378             :   {
     379           0 :     if (mDepth != aRHS.mDepth) {
     380           0 :       return mDepth < aRHS.mDepth;
     381             :     }
     382           0 :     return mOrder < aRHS.mOrder;
     383             :   }
     384             : };
     385             : 
     386             : // Sorts aSheets such that style sheets for ancestor scopes come
     387             : // before those for descendant scopes, and with sheets for a single
     388             : // scope in document order.
     389             : static void
     390           0 : SortStyleSheetsByScope(nsTArray<CSSStyleSheet*>& aSheets)
     391             : {
     392           0 :   uint32_t n = aSheets.Length();
     393           0 :   if (n == 1) {
     394           0 :     return;
     395             :   }
     396             : 
     397           0 :   ScopeDepthCache cache;
     398             : 
     399           0 :   nsTArray<ScopedSheetOrder> sheets;
     400           0 :   sheets.SetLength(n);
     401             : 
     402             :   // For each sheet, record the depth of its scope element and its original
     403             :   // document order.
     404           0 :   for (uint32_t i = 0; i < n; i++) {
     405           0 :     sheets[i].mSheet = aSheets[i];
     406           0 :     sheets[i].mDepth = GetScopeDepth(aSheets[i]->GetScopeElement(), cache);
     407           0 :     sheets[i].mOrder = i;
     408             :   }
     409             : 
     410             :   // Sort by depth first, then document order.
     411           0 :   sheets.Sort();
     412             : 
     413           0 :   for (uint32_t i = 0; i < n; i++) {
     414           0 :     aSheets[i] = sheets[i].mSheet;
     415             :   }
     416             : }
     417             : 
     418             : nsresult
     419         160 : nsStyleSet::GatherRuleProcessors(SheetType aType)
     420             : {
     421         160 :   NS_ENSURE_FALSE(mInShutdown, NS_ERROR_FAILURE);
     422             : 
     423             :   // We might be in GatherRuleProcessors because we are dropping a sheet,
     424             :   // resulting in an nsCSSSelector being destroyed.  Tell the
     425             :   // RestyleManager for each document we're used in so that they can
     426             :   // drop any nsCSSSelector pointers (used for eRestyle_SomeDescendants)
     427             :   // in their mPendingRestyles.
     428         160 :   if (IsCSSSheetType(aType)) {
     429          48 :     ClearSelectors();
     430             :   }
     431         320 :   nsCOMPtr<nsIStyleRuleProcessor> oldRuleProcessor(mRuleProcessors[aType]);
     432         320 :   nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> oldScopedDocRuleProcessors;
     433         160 :   if (aType == SheetType::Agent || aType == SheetType::User) {
     434             :     // drop reference to cached rule processor
     435             :     nsCSSRuleProcessor* rp =
     436          36 :       static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aType].get());
     437          36 :     if (rp) {
     438           5 :       MOZ_ASSERT(rp->IsShared());
     439           5 :       rp->ReleaseStyleSetRef();
     440             :     }
     441             :   }
     442         160 :   mRuleProcessors[aType] = nullptr;
     443         160 :   if (aType == SheetType::ScopedDoc) {
     444           0 :     for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
     445           0 :       nsIStyleRuleProcessor* processor = mScopedDocSheetRuleProcessors[i].get();
     446             :       Element* scope =
     447           0 :         static_cast<nsCSSRuleProcessor*>(processor)->GetScopeElement();
     448           0 :       scope->ClearIsScopedStyleRoot();
     449             :     }
     450             : 
     451             :     // Clear mScopedDocSheetRuleProcessors, but save it.
     452           0 :     oldScopedDocRuleProcessors.SwapElements(mScopedDocSheetRuleProcessors);
     453             :   }
     454         160 :   if (mAuthorStyleDisabled && (aType == SheetType::Doc ||
     455           0 :                                aType == SheetType::ScopedDoc ||
     456         160 :                                aType == SheetType::StyleAttr)) {
     457             :     // Don't regather if this level is disabled.  Note that we gather
     458             :     // preshint sheets no matter what, but then skip them for some
     459             :     // elements later if mAuthorStyleDisabled.
     460           0 :     return NS_OK;
     461             :   }
     462         160 :   switch (aType) {
     463             :     // levels that do not contain CSS style sheets
     464             :     case SheetType::Animation:
     465          28 :       MOZ_ASSERT(mSheets[aType].IsEmpty());
     466          28 :       mRuleProcessors[aType] = PresContext()->EffectCompositor()->
     467          56 :         RuleProcessor(EffectCompositor::CascadeLevel::Animations);
     468          28 :       return NS_OK;
     469             :     case SheetType::Transition:
     470          28 :       MOZ_ASSERT(mSheets[aType].IsEmpty());
     471          28 :       mRuleProcessors[aType] = PresContext()->EffectCompositor()->
     472          56 :         RuleProcessor(EffectCompositor::CascadeLevel::Transitions);
     473          28 :       return NS_OK;
     474             :     case SheetType::StyleAttr:
     475          28 :       MOZ_ASSERT(mSheets[aType].IsEmpty());
     476          28 :       mRuleProcessors[aType] = PresContext()->Document()->GetInlineStyleSheet();
     477          28 :       return NS_OK;
     478             :     case SheetType::PresHint:
     479          28 :       MOZ_ASSERT(mSheets[aType].IsEmpty());
     480          28 :       mRuleProcessors[aType] =
     481          56 :         PresContext()->Document()->GetAttributeStyleSheet();
     482          28 :       return NS_OK;
     483             :     default:
     484             :       // keep going
     485          48 :       break;
     486             :   }
     487          48 :   MOZ_ASSERT(IsCSSSheetType(aType));
     488          48 :   if (aType == SheetType::ScopedDoc) {
     489             :     // Create a rule processor for each scope.
     490           0 :     uint32_t count = mSheets[SheetType::ScopedDoc].Length();
     491           0 :     if (count) {
     492             :       // Gather the scoped style sheets into an array as
     493             :       // CSSStyleSheets, and mark all of their scope elements
     494             :       // as scoped style roots.
     495           0 :       nsTArray<CSSStyleSheet*> sheets(count);
     496           0 :       for (CSSStyleSheet* sheet : mSheets[SheetType::ScopedDoc]) {
     497           0 :         sheets.AppendElement(sheet);
     498             : 
     499           0 :         Element* scope = sheet->GetScopeElement();
     500           0 :         scope->SetIsScopedStyleRoot();
     501             :       }
     502             : 
     503             :       // Sort the scoped style sheets so that those for the same scope are
     504             :       // adjacent and that ancestor scopes come before descendent scopes.
     505           0 :       SortStyleSheetsByScope(sheets);
     506             : 
     507             :       // Put the old scoped rule processors in a hashtable so that we
     508             :       // can retrieve them efficiently, even in edge cases like the
     509             :       // simultaneous removal and addition of a large number of elements
     510             :       // with scoped sheets.
     511             :       nsDataHashtable<nsPtrHashKey<Element>,
     512           0 :                       nsCSSRuleProcessor*> oldScopedRuleProcessorHash;
     513           0 :       for (size_t i = oldScopedDocRuleProcessors.Length(); i-- != 0; ) {
     514             :         nsCSSRuleProcessor* oldRP =
     515           0 :           static_cast<nsCSSRuleProcessor*>(oldScopedDocRuleProcessors[i].get());
     516           0 :         Element* scope = oldRP->GetScopeElement();
     517           0 :         MOZ_ASSERT(!oldScopedRuleProcessorHash.Get(scope),
     518             :                    "duplicate rule processors for same scope element?");
     519           0 :         oldScopedRuleProcessorHash.Put(scope, oldRP);
     520             :       }
     521             : 
     522           0 :       uint32_t start = 0, end;
     523           0 :       do {
     524             :         // Find the range of style sheets with the same scope.
     525           0 :         Element* scope = sheets[start]->GetScopeElement();
     526           0 :         end = start + 1;
     527           0 :         while (end < count && sheets[end]->GetScopeElement() == scope) {
     528           0 :           end++;
     529             :         }
     530             : 
     531           0 :         scope->SetIsScopedStyleRoot();
     532             : 
     533             :         // Create a rule processor for the scope.
     534           0 :         nsTArray<RefPtr<CSSStyleSheet>> sheetsForScope;
     535           0 :         sheetsForScope.AppendElements(sheets.Elements() + start, end - start);
     536           0 :         nsCSSRuleProcessor* oldRP = oldScopedRuleProcessorHash.Get(scope);
     537             :         mScopedDocSheetRuleProcessors.AppendElement
     538           0 :           (new nsCSSRuleProcessor(Move(sheetsForScope), aType, scope, oldRP));
     539             : 
     540           0 :         start = end;
     541           0 :       } while (start < count);
     542             :     }
     543           0 :     return NS_OK;
     544             :   }
     545          48 :   if (!mSheets[aType].IsEmpty()) {
     546          46 :     switch (aType) {
     547             :       case SheetType::Agent:
     548             :       case SheetType::User: {
     549             :         // levels containing non-scoped CSS style sheets whose rule processors
     550             :         // we want to re-use
     551          68 :         nsTArray<CSSStyleSheet*> sheets(mSheets[aType].Length());
     552         155 :         for (CSSStyleSheet* sheet : mSheets[aType]) {
     553         121 :           sheets.AppendElement(sheet);
     554             :         }
     555             :         nsCSSRuleProcessor* rp =
     556          34 :           RuleProcessorCache::GetRuleProcessor(sheets, PresContext());
     557          34 :         if (!rp) {
     558          20 :           rp = new nsCSSRuleProcessor(mSheets[aType], aType, nullptr,
     559          10 :                                       static_cast<nsCSSRuleProcessor*>(
     560             :                                        oldRuleProcessor.get()),
     561          20 :                                       true /* aIsShared */);
     562          20 :           nsTArray<css::DocumentRule*> documentRules;
     563          20 :           nsDocumentRuleResultCacheKey cacheKey;
     564          10 :           rp->TakeDocumentRulesAndCacheKey(PresContext(),
     565          10 :                                            documentRules, cacheKey);
     566             :           RuleProcessorCache::PutRuleProcessor(sheets,
     567          10 :                                                Move(documentRules),
     568          10 :                                                cacheKey, rp);
     569             :         }
     570          34 :         mRuleProcessors[aType] = rp;
     571          34 :         rp->AddStyleSetRef();
     572          34 :         break;
     573             :       }
     574             :       case SheetType::Doc:
     575             :       case SheetType::Override: {
     576             :         // levels containing non-scoped CSS stylesheets whose rule processors
     577             :         // we don't want to re-use
     578          12 :         mRuleProcessors[aType] =
     579          12 :           new nsCSSRuleProcessor(mSheets[aType], aType, nullptr,
     580          12 :                                  static_cast<nsCSSRuleProcessor*>(
     581          36 :                                    oldRuleProcessor.get()));
     582          12 :       } break;
     583             : 
     584             :       default:
     585           0 :         MOZ_ASSERT_UNREACHABLE("non-CSS sheet types should be handled above");
     586             :         break;
     587             :     }
     588             :   }
     589             : 
     590          48 :   return NS_OK;
     591             : }
     592             : 
     593             : nsresult
     594          17 : nsStyleSet::AppendStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
     595             : {
     596          17 :   NS_PRECONDITION(aSheet, "null arg");
     597          17 :   NS_ASSERTION(aSheet->IsApplicable(),
     598             :                "Inapplicable sheet being placed in style set");
     599          17 :   bool present = mSheets[aType].RemoveElement(aSheet);
     600          17 :   mSheets[aType].AppendElement(aSheet);
     601             : 
     602          17 :   if (!present && IsCSSSheetType(aType)) {
     603          17 :     aSheet->AddStyleSet(StyleSetHandle(this));
     604             :   }
     605             : 
     606          17 :   return DirtyRuleProcessors(aType);
     607             : }
     608             : 
     609             : nsresult
     610          93 : nsStyleSet::PrependStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
     611             : {
     612          93 :   NS_PRECONDITION(aSheet, "null arg");
     613          93 :   NS_ASSERTION(aSheet->IsApplicable(),
     614             :                "Inapplicable sheet being placed in style set");
     615          93 :   bool present = mSheets[aType].RemoveElement(aSheet);
     616          93 :   mSheets[aType].InsertElementAt(0, aSheet);
     617             : 
     618          93 :   if (!present && IsCSSSheetType(aType)) {
     619          93 :     aSheet->AddStyleSet(StyleSetHandle(this));
     620             :   }
     621             : 
     622          93 :   return DirtyRuleProcessors(aType);
     623             : }
     624             : 
     625             : nsresult
     626           2 : nsStyleSet::RemoveStyleSheet(SheetType aType, CSSStyleSheet* aSheet)
     627             : {
     628           2 :   NS_PRECONDITION(aSheet, "null arg");
     629           2 :   NS_ASSERTION(aSheet->IsComplete(),
     630             :                "Incomplete sheet being removed from style set");
     631           2 :   if (mSheets[aType].RemoveElement(aSheet)) {
     632           2 :     if (IsCSSSheetType(aType)) {
     633           2 :       aSheet->DropStyleSet(StyleSetHandle(this));
     634             :     }
     635             :   }
     636             : 
     637           2 :   return DirtyRuleProcessors(aType);
     638             : }
     639             : 
     640             : nsresult
     641           0 : nsStyleSet::ReplaceSheets(SheetType aType,
     642             :                           const nsTArray<RefPtr<CSSStyleSheet>>& aNewSheets)
     643             : {
     644           0 :   bool cssSheetType = IsCSSSheetType(aType);
     645           0 :   if (cssSheetType) {
     646           0 :     for (CSSStyleSheet* sheet : mSheets[aType]) {
     647           0 :       sheet->DropStyleSet(StyleSetHandle(this));
     648             :     }
     649             :   }
     650             : 
     651           0 :   mSheets[aType].Clear();
     652           0 :   mSheets[aType].AppendElements(aNewSheets);
     653             : 
     654           0 :   if (cssSheetType) {
     655           0 :     for (CSSStyleSheet* sheet : mSheets[aType]) {
     656           0 :       sheet->AddStyleSet(StyleSetHandle(this));
     657             :     }
     658             :   }
     659             : 
     660           0 :   return DirtyRuleProcessors(aType);
     661             : }
     662             : 
     663             : nsresult
     664           0 : nsStyleSet::InsertStyleSheetBefore(SheetType aType, CSSStyleSheet* aNewSheet,
     665             :                                    CSSStyleSheet* aReferenceSheet)
     666             : {
     667           0 :   NS_PRECONDITION(aNewSheet && aReferenceSheet, "null arg");
     668           0 :   NS_ASSERTION(aNewSheet->IsApplicable(),
     669             :                "Inapplicable sheet being placed in style set");
     670             : 
     671           0 :   bool present = mSheets[aType].RemoveElement(aNewSheet);
     672           0 :   int32_t idx = mSheets[aType].IndexOf(aReferenceSheet);
     673           0 :   if (idx < 0)
     674           0 :     return NS_ERROR_INVALID_ARG;
     675             : 
     676           0 :   mSheets[aType].InsertElementAt(idx, aNewSheet);
     677             : 
     678           0 :   if (!present && IsCSSSheetType(aType)) {
     679           0 :     aNewSheet->AddStyleSet(StyleSetHandle(this));
     680             :   }
     681             : 
     682           0 :   return DirtyRuleProcessors(aType);
     683             : }
     684             : 
     685             : static inline uint32_t
     686         823 : DirtyBit(SheetType aType)
     687             : {
     688         823 :   return 1 << uint32_t(aType);
     689             : }
     690             : 
     691             : nsresult
     692         123 : nsStyleSet::DirtyRuleProcessors(SheetType aType)
     693             : {
     694         123 :   if (!mBatching)
     695           2 :     return GatherRuleProcessors(aType);
     696             : 
     697         121 :   mDirty |= DirtyBit(aType);
     698         121 :   return NS_OK;
     699             : }
     700             : 
     701             : bool
     702          10 : nsStyleSet::GetAuthorStyleDisabled() const
     703             : {
     704          10 :   return mAuthorStyleDisabled;
     705             : }
     706             : 
     707             : nsresult
     708           0 : nsStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled)
     709             : {
     710           0 :   if (aStyleDisabled == !mAuthorStyleDisabled) {
     711           0 :     mAuthorStyleDisabled = aStyleDisabled;
     712           0 :     BeginUpdate();
     713           0 :     mDirty |= DirtyBit(SheetType::Doc) |
     714           0 :               DirtyBit(SheetType::ScopedDoc) |
     715           0 :               DirtyBit(SheetType::StyleAttr);
     716           0 :     return EndUpdate();
     717             :   }
     718           0 :   return NS_OK;
     719             : }
     720             : 
     721             : // -------- Doc Sheets
     722             : 
     723             : nsresult
     724          11 : nsStyleSet::AddDocStyleSheet(CSSStyleSheet* aSheet, nsIDocument* aDocument)
     725             : {
     726          11 :   NS_PRECONDITION(aSheet && aDocument, "null arg");
     727          11 :   NS_ASSERTION(aSheet->IsApplicable(),
     728             :                "Inapplicable sheet being placed in style set");
     729             : 
     730          11 :   SheetType type = aSheet->GetScopeElement() ?
     731             :                      SheetType::ScopedDoc :
     732          11 :                      SheetType::Doc;
     733          11 :   nsTArray<RefPtr<CSSStyleSheet>>& sheets = mSheets[type];
     734             : 
     735          11 :   bool present = sheets.RemoveElement(aSheet);
     736             : 
     737          11 :   size_t index = aDocument->FindDocStyleSheetInsertionPoint(sheets, aSheet);
     738          11 :   sheets.InsertElementAt(index, aSheet);
     739             : 
     740          11 :   if (!present) {
     741          11 :     aSheet->AddStyleSet(StyleSetHandle(this));
     742             :   }
     743             : 
     744          11 :   return DirtyRuleProcessors(type);
     745             : }
     746             : 
     747             : void
     748           0 : nsStyleSet::AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const
     749             : {
     750           0 :   if (mBindingManager) {
     751           0 :     mBindingManager->AppendAllSheets(aArray);
     752             :   }
     753           0 : }
     754             : 
     755             : nsresult
     756           0 : nsStyleSet::RemoveDocStyleSheet(CSSStyleSheet* aSheet)
     757             : {
     758           0 :   bool isScoped = aSheet->GetScopeElement();
     759           0 :   return RemoveStyleSheet(isScoped ? SheetType::ScopedDoc : SheetType::Doc,
     760           0 :                           aSheet);
     761             : }
     762             : 
     763             : // Batching
     764             : void
     765          93 : nsStyleSet::BeginUpdate()
     766             : {
     767          93 :   ++mBatching;
     768          93 : }
     769             : 
     770             : nsresult
     771          93 : nsStyleSet::EndUpdate()
     772             : {
     773          93 :   NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate");
     774          93 :   if (--mBatching) {
     775             :     // We're not completely done yet.
     776          15 :     return NS_OK;
     777             :   }
     778             : 
     779         780 :   for (SheetType type : MakeEnumeratedRange(SheetType::Count)) {
     780         702 :     if (mDirty & DirtyBit(type)) {
     781          46 :       nsresult rv = GatherRuleProcessors(type);
     782          46 :       NS_ENSURE_SUCCESS(rv, rv);
     783             :     }
     784             :   }
     785             : 
     786          78 :   mDirty = 0;
     787          78 :   return NS_OK;
     788             : }
     789             : 
     790             : template<class T>
     791             : static bool
     792       26482 : EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
     793             : {
     794       26482 :   T* data = static_cast<T*>(aData);
     795       26482 :   aProcessor->RulesMatching(data);
     796       26482 :   return true;
     797             : }
     798             : 
     799             : static inline bool
     800        3201 : IsMoreSpecificThanAnimation(nsRuleNode *aRuleNode)
     801             : {
     802        6759 :   return !aRuleNode->IsRoot() &&
     803        6380 :          (aRuleNode->GetLevel() == SheetType::Transition ||
     804        6388 :           aRuleNode->IsImportantRule());
     805             : }
     806             : 
     807             : static nsIStyleRule*
     808        2836 : GetAnimationRule(nsRuleNode *aRuleNode)
     809             : {
     810        2836 :   nsRuleNode *n = aRuleNode;
     811        3566 :   while (IsMoreSpecificThanAnimation(n)) {
     812         365 :     n = n->GetParent();
     813             :   }
     814             : 
     815        2836 :   if (n->IsRoot() || n->GetLevel() != SheetType::Animation) {
     816        2836 :     return nullptr;
     817             :   }
     818             : 
     819           0 :   return n->GetRule();
     820             : }
     821             : 
     822             : static nsRuleNode*
     823           0 : ReplaceAnimationRule(nsRuleNode *aOldRuleNode,
     824             :                      nsIStyleRule *aOldAnimRule,
     825             :                      nsIStyleRule *aNewAnimRule)
     826             : {
     827           0 :   nsTArray<nsRuleNode*> moreSpecificNodes;
     828             : 
     829           0 :   nsRuleNode *n = aOldRuleNode;
     830           0 :   while (IsMoreSpecificThanAnimation(n)) {
     831           0 :     moreSpecificNodes.AppendElement(n);
     832           0 :     n = n->GetParent();
     833             :   }
     834             : 
     835           0 :   if (aOldAnimRule) {
     836           0 :     MOZ_ASSERT(n->GetRule() == aOldAnimRule, "wrong rule");
     837           0 :     MOZ_ASSERT(n->GetLevel() == SheetType::Animation,
     838             :                "wrong level");
     839           0 :     n = n->GetParent();
     840             :   }
     841             : 
     842           0 :   MOZ_ASSERT(!IsMoreSpecificThanAnimation(n) &&
     843             :              (n->IsRoot() || n->GetLevel() != SheetType::Animation),
     844             :              "wrong level");
     845             : 
     846           0 :   if (aNewAnimRule) {
     847           0 :     n = n->Transition(aNewAnimRule, SheetType::Animation, false);
     848           0 :     n->SetIsAnimationRule();
     849             :   }
     850             : 
     851           0 :   for (uint32_t i = moreSpecificNodes.Length(); i-- != 0; ) {
     852           0 :     nsRuleNode *oldNode = moreSpecificNodes[i];
     853           0 :     n = n->Transition(oldNode->GetRule(), oldNode->GetLevel(),
     854           0 :                       oldNode->IsImportantRule());
     855             :   }
     856             : 
     857           0 :   return n;
     858             : }
     859             : 
     860             : /**
     861             :  * |GetContext| implements sharing of style contexts (not just the data
     862             :  * on the rule nodes) between siblings and cousins of the same
     863             :  * generation.  (It works for cousins of the same generation since
     864             :  * |aParentContext| could itself be a shared context.)
     865             :  */
     866             : already_AddRefed<nsStyleContext>
     867        3340 : nsStyleSet::GetContext(nsStyleContext* aParentContext,
     868             :                        nsRuleNode* aRuleNode,
     869             :                        // aVisitedRuleNode may be null; if it is null
     870             :                        // it means that we don't need to force creation
     871             :                        // of a StyleIfVisited.  (But if we make one
     872             :                        // because aParentContext has one, then aRuleNode
     873             :                        // should be used.)
     874             :                        nsRuleNode* aVisitedRuleNode,
     875             :                        nsIAtom* aPseudoTag,
     876             :                        CSSPseudoElementType aPseudoType,
     877             :                        Element* aElementForAnimation,
     878             :                        uint32_t aFlags)
     879             : {
     880        3340 :   NS_PRECONDITION((!aPseudoTag &&
     881             :                    aPseudoType ==
     882             :                      CSSPseudoElementType::NotPseudo) ||
     883             :                   (aPseudoTag &&
     884             :                    nsCSSPseudoElements::GetPseudoType(
     885             :                      aPseudoTag, CSSEnabledState::eIgnoreEnabledState) ==
     886             :                    aPseudoType),
     887             :                   "Pseudo mismatch");
     888             : 
     889        3340 :   if (aVisitedRuleNode == aRuleNode) {
     890             :     // No need to force creation of a visited style in this case.
     891           0 :     aVisitedRuleNode = nullptr;
     892             :   }
     893             : 
     894             :   // Ensure |aVisitedRuleNode != nullptr| corresponds to the need to
     895             :   // create an if-visited style context, and that in that case, we have
     896             :   // parentIfVisited set correctly.
     897             :   nsStyleContext *parentIfVisited =
     898        3340 :     aParentContext ? aParentContext->GetStyleIfVisited() : nullptr;
     899        3340 :   if (parentIfVisited) {
     900           0 :     if (!aVisitedRuleNode) {
     901           0 :       aVisitedRuleNode = aRuleNode;
     902             :     }
     903             :   } else {
     904        3340 :     if (aVisitedRuleNode) {
     905           0 :       parentIfVisited = aParentContext;
     906             :     }
     907             :   }
     908             : 
     909        3340 :   if (aFlags & eIsLink) {
     910             :     // If this node is a link, we want its visited's style context's
     911             :     // parent to be the regular style context of its parent, because
     912             :     // only the visitedness of the relevant link should influence style.
     913           0 :     parentIfVisited = aParentContext;
     914             :   }
     915             : 
     916        3340 :   bool relevantLinkVisited = (aFlags & eIsLink) ?
     917           0 :     (aFlags & eIsVisitedLink) :
     918        3340 :     (aParentContext && aParentContext->RelevantLinkVisited());
     919             : 
     920        6680 :   RefPtr<nsStyleContext> result;
     921        3340 :   if (aParentContext)
     922        6306 :     result = aParentContext->AsGecko()->FindChildWithRules(aPseudoTag, aRuleNode,
     923             :                                                 aVisitedRuleNode,
     924        3153 :                                                 relevantLinkVisited);
     925             : 
     926        3340 :   if (!result) {
     927             :     // |aVisitedRuleNode| may have a ref-count of zero since we are yet
     928             :     // to create the style context that will hold an owning reference to it.
     929             :     // As a result, we need to make sure it stays alive until that point
     930             :     // in case something in the first call to NS_NewStyleContext triggers a
     931             :     // GC sweep of rule nodes.
     932        4406 :     RefPtr<nsRuleNode> kungFuDeathGrip{aVisitedRuleNode};
     933             : 
     934        4406 :     result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType,
     935             :                                 aRuleNode,
     936        4406 :                                 aFlags & eSkipParentDisplayBasedStyleFixup);
     937        2203 :     if (aVisitedRuleNode) {
     938             :       RefPtr<nsStyleContext> resultIfVisited =
     939           0 :         NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType,
     940             :                            aVisitedRuleNode,
     941           0 :                            aFlags & eSkipParentDisplayBasedStyleFixup);
     942           0 :       resultIfVisited->SetIsStyleIfVisited();
     943           0 :       result->SetStyleIfVisited(resultIfVisited.forget());
     944             : 
     945           0 :       if (relevantLinkVisited) {
     946           0 :         result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
     947             :       }
     948             :     }
     949             :   }
     950             :   else {
     951        1137 :     NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type");
     952        1137 :     NS_ASSERTION(result->GetPseudo() == aPseudoTag, "Unexpected pseudo");
     953             :   }
     954             : 
     955        3340 :   if (aFlags & eDoAnimation) {
     956             : 
     957        2836 :     nsIStyleRule *oldAnimRule = GetAnimationRule(aRuleNode);
     958        2836 :     nsIStyleRule *animRule = nullptr;
     959             : 
     960             :     // Ignore animations for print or print preview, and for elements
     961             :     // that are not attached to the document tree.
     962        5672 :     if (PresContext()->IsDynamic() &&
     963        2836 :         aElementForAnimation->IsInComposedDoc()) {
     964             :       // Update CSS animations in case the animation-name has just changed.
     965        2834 :       PresContext()->AnimationManager()->UpdateAnimations(result,
     966        2834 :                                                           aElementForAnimation);
     967        2834 :       PresContext()->EffectCompositor()->UpdateEffectProperties(
     968        2834 :         result.get(), aElementForAnimation, result->GetPseudoType());
     969             : 
     970             :       animRule = PresContext()->EffectCompositor()->
     971        2834 :                    GetAnimationRule(aElementForAnimation,
     972             :                                     result->GetPseudoType(),
     973             :                                     EffectCompositor::CascadeLevel::Animations,
     974        2834 :                                     result);
     975             :     }
     976             : 
     977        2836 :     MOZ_ASSERT(result->RuleNode() == aRuleNode,
     978             :                "unexpected rule node");
     979        2836 :     MOZ_ASSERT(!result->GetStyleIfVisited() == !aVisitedRuleNode,
     980             :                "unexpected visited rule node");
     981        2836 :     MOZ_ASSERT(!aVisitedRuleNode ||
     982             :                result->GetStyleIfVisited()->RuleNode() == aVisitedRuleNode,
     983             :                "unexpected visited rule node");
     984        2836 :     MOZ_ASSERT(!aVisitedRuleNode ||
     985             :                oldAnimRule == GetAnimationRule(aVisitedRuleNode),
     986             :                "animation rule mismatch between rule nodes");
     987        2836 :     if (oldAnimRule != animRule) {
     988             :       // FIXME: This should use ResolveStyleWithReplacement instead (and
     989             :       // we can remove ReplaceAnimationRule), since
     990             :       // ResolveStyleWithReplacement should now be equally efficient
     991             :       // (except for the extra code complexity to be more general).
     992             :       nsRuleNode *ruleNode =
     993           0 :         ReplaceAnimationRule(aRuleNode, oldAnimRule, animRule);
     994             :       nsRuleNode *visitedRuleNode = aVisitedRuleNode
     995           0 :         ? ReplaceAnimationRule(aVisitedRuleNode, oldAnimRule, animRule)
     996           0 :         : nullptr;
     997           0 :       MOZ_ASSERT(!visitedRuleNode ||
     998             :                  GetAnimationRule(ruleNode) ==
     999             :                    GetAnimationRule(visitedRuleNode),
    1000             :                  "animation rule mismatch between rule nodes");
    1001           0 :       result = GetContext(aParentContext, ruleNode, visitedRuleNode,
    1002             :                           aPseudoTag, aPseudoType, nullptr,
    1003           0 :                           aFlags & ~eDoAnimation);
    1004             :     }
    1005             :   }
    1006             : 
    1007        6200 :   if (aElementForAnimation &&
    1008        2867 :       aElementForAnimation->IsHTMLElement(nsGkAtoms::body) &&
    1009        3347 :       aPseudoType == CSSPseudoElementType::NotPseudo &&
    1010           7 :       PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
    1011           7 :     nsIDocument* doc = aElementForAnimation->GetUncomposedDoc();
    1012           7 :     if (doc && doc->GetBodyElement() == aElementForAnimation) {
    1013             :       // Update the prescontext's body color
    1014           7 :       PresContext()->SetBodyTextColor(result->StyleColor()->mColor);
    1015             :     }
    1016             :   }
    1017             : 
    1018        6680 :   return result.forget();
    1019             : }
    1020             : 
    1021             : void
    1022         479 : nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
    1023             :                               nsRuleNode* aLastPrevLevelNode,
    1024             :                               nsRuleWalker* aRuleWalker)
    1025             : {
    1026         479 :   NS_ASSERTION(aCurrLevelNode &&
    1027             :                aCurrLevelNode != aLastPrevLevelNode, "How did we get here?");
    1028             : 
    1029         958 :   AutoTArray<nsIStyleRule*, 16> importantRules;
    1030        1660 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
    1031             :        node = node->GetParent()) {
    1032             :     // We guarantee that we never walk the root node here, so no need
    1033             :     // to null-check GetRule().  Furthermore, it must be a CSS rule.
    1034        1181 :     NS_ASSERTION(RefPtr<css::Declaration>(do_QueryObject(node->GetRule())),
    1035             :                  "Unexpected non-CSS rule");
    1036             : 
    1037             :     nsIStyleRule* impRule =
    1038        1181 :       static_cast<css::Declaration*>(node->GetRule())->GetImportantStyleData();
    1039        1181 :     if (impRule)
    1040         524 :       importantRules.AppendElement(impRule);
    1041             :   }
    1042             : 
    1043         479 :   NS_ASSERTION(importantRules.Length() != 0,
    1044             :                "Why did we think there were important rules?");
    1045             : 
    1046        1003 :   for (uint32_t i = importantRules.Length(); i-- != 0; ) {
    1047         524 :     aRuleWalker->Forward(importantRules[i]);
    1048             :   }
    1049         479 : }
    1050             : 
    1051             : #ifdef DEBUG
    1052             : void
    1053       23515 : nsStyleSet::AssertNoImportantRules(nsRuleNode* aCurrLevelNode,
    1054             :                                    nsRuleNode* aLastPrevLevelNode)
    1055             : {
    1056       23515 :   if (!aCurrLevelNode)
    1057           0 :     return;
    1058             : 
    1059       33025 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
    1060             :        node = node->GetParent()) {
    1061       19020 :     RefPtr<css::Declaration> declaration(do_QueryObject(node->GetRule()));
    1062        9510 :     NS_ASSERTION(declaration, "Unexpected non-CSS rule");
    1063             : 
    1064        9510 :     NS_ASSERTION(!declaration->GetImportantStyleData(),
    1065             :                  "Unexpected important style source");
    1066             :   }
    1067             : }
    1068             : 
    1069             : void
    1070       11997 : nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
    1071             :                              nsRuleNode* aLastPrevLevelNode)
    1072             : {
    1073       11997 :   if (!aCurrLevelNode)
    1074           0 :     return;
    1075             : 
    1076       12286 :   for (nsRuleNode *node = aCurrLevelNode; node != aLastPrevLevelNode;
    1077             :        node = node->GetParent()) {
    1078         289 :     nsIStyleRule *rule = node->GetRule();
    1079         578 :     RefPtr<css::Declaration> declaration(do_QueryObject(rule));
    1080         289 :     if (declaration) {
    1081             :       RefPtr<css::StyleRule> cssRule =
    1082         300 :         do_QueryObject(declaration->GetOwningRule());
    1083         150 :       NS_ASSERTION(!cssRule || !cssRule->Selector(),
    1084             :                    "Unexpected CSS rule");
    1085             :     }
    1086             :   }
    1087             : }
    1088             : #endif
    1089             : 
    1090             : // Enumerate the rules in a way that cares about the order of the rules.
    1091             : void
    1092        3999 : nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
    1093             :                       RuleProcessorData* aData, Element* aElement,
    1094             :                       nsRuleWalker* aRuleWalker)
    1095             : {
    1096        7998 :   AUTO_PROFILER_LABEL("nsStyleSet::FileRules", CSS);
    1097             : 
    1098        3999 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    1099             : 
    1100             :   // Cascading order:
    1101             :   // [least important]
    1102             :   //  - UA normal rules                    = Agent        normal
    1103             :   //  - User normal rules                  = User         normal
    1104             :   //  - Presentation hints                 = PresHint     normal
    1105             :   //  - Author normal rules                = Document     normal
    1106             :   //  - Override normal rules              = Override     normal
    1107             :   //  - animation rules                    = Animation    normal
    1108             :   //  - Author !important rules            = Document     !important
    1109             :   //  - Override !important rules          = Override     !important
    1110             :   //  - User !important rules              = User         !important
    1111             :   //  - UA !important rules                = Agent        !important
    1112             :   //  - transition rules                   = Transition   normal
    1113             :   // [most important]
    1114             : 
    1115             :   // Save off the last rule before we start walking our agent sheets;
    1116             :   // this will be either the root or one of the restriction rules.
    1117        3999 :   nsRuleNode* lastRestrictionRN = aRuleWalker->CurrentNode();
    1118             : 
    1119        3999 :   aRuleWalker->SetLevel(SheetType::Agent, false, true);
    1120        3999 :   if (mRuleProcessors[SheetType::Agent])
    1121        3999 :     (*aCollectorFunc)(mRuleProcessors[SheetType::Agent], aData);
    1122        3999 :   nsRuleNode* lastAgentRN = aRuleWalker->CurrentNode();
    1123        3999 :   bool haveImportantUARules = !aRuleWalker->GetCheckForImportantRules();
    1124             : 
    1125        3999 :   aRuleWalker->SetLevel(SheetType::User, false, true);
    1126             :   bool skipUserStyles =
    1127        3999 :     aElement && aElement->IsInNativeAnonymousSubtree();
    1128        3999 :   if (!skipUserStyles && mRuleProcessors[SheetType::User]) // NOTE: different
    1129          27 :     (*aCollectorFunc)(mRuleProcessors[SheetType::User], aData);
    1130        3999 :   nsRuleNode* lastUserRN = aRuleWalker->CurrentNode();
    1131        3999 :   bool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
    1132             : 
    1133        3999 :   aRuleWalker->SetLevel(SheetType::PresHint, false, false);
    1134        3999 :   if (mRuleProcessors[SheetType::PresHint])
    1135        3999 :     (*aCollectorFunc)(mRuleProcessors[SheetType::PresHint], aData);
    1136        3999 :   nsRuleNode* lastPresHintRN = aRuleWalker->CurrentNode();
    1137             : 
    1138        3999 :   aRuleWalker->SetLevel(SheetType::Doc, false, true);
    1139        3999 :   bool cutOffInheritance = false;
    1140        3999 :   if (mBindingManager && aElement) {
    1141             :     // We can supply additional document-level sheets that should be walked.
    1142        3789 :     mBindingManager->WalkRules(aCollectorFunc,
    1143             :                                static_cast<ElementDependentRuleProcessorData*>(aData),
    1144        3789 :                                &cutOffInheritance);
    1145             :   }
    1146        7811 :   if (!skipUserStyles && !cutOffInheritance && // NOTE: different
    1147        3812 :       mRuleProcessors[SheetType::Doc])
    1148        3474 :     (*aCollectorFunc)(mRuleProcessors[SheetType::Doc], aData);
    1149        3999 :   nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
    1150        3999 :   bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
    1151        7998 :   nsTArray<nsRuleNode*> lastScopedRNs;
    1152        7998 :   nsTArray<bool> haveImportantScopedRules;
    1153        3999 :   bool haveAnyImportantScopedRules = false;
    1154       11810 :   if (!skipUserStyles && !cutOffInheritance &&
    1155        7601 :       aElement && aElement->IsElementInStyleScope()) {
    1156           0 :     lastScopedRNs.SetLength(mScopedDocSheetRuleProcessors.Length());
    1157           0 :     haveImportantScopedRules.SetLength(mScopedDocSheetRuleProcessors.Length());
    1158           0 :     for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++) {
    1159           0 :       aRuleWalker->SetLevel(SheetType::ScopedDoc, false, true);
    1160             :       nsCSSRuleProcessor* processor =
    1161           0 :         static_cast<nsCSSRuleProcessor*>(mScopedDocSheetRuleProcessors[i].get());
    1162           0 :       aData->mScope = processor->GetScopeElement();
    1163           0 :       (*aCollectorFunc)(mScopedDocSheetRuleProcessors[i], aData);
    1164           0 :       lastScopedRNs[i] = aRuleWalker->CurrentNode();
    1165           0 :       haveImportantScopedRules[i] = !aRuleWalker->GetCheckForImportantRules();
    1166           0 :       haveAnyImportantScopedRules = haveAnyImportantScopedRules || haveImportantScopedRules[i];
    1167             :     }
    1168           0 :     aData->mScope = nullptr;
    1169             :   }
    1170        3999 :   nsRuleNode* lastScopedRN = aRuleWalker->CurrentNode();
    1171        3999 :   aRuleWalker->SetLevel(SheetType::StyleAttr, false, true);
    1172        3999 :   if (mRuleProcessors[SheetType::StyleAttr])
    1173        3999 :     (*aCollectorFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
    1174        3999 :   nsRuleNode* lastStyleAttrRN = aRuleWalker->CurrentNode();
    1175        3999 :   bool haveImportantStyleAttrRules = !aRuleWalker->GetCheckForImportantRules();
    1176             : 
    1177        3999 :   aRuleWalker->SetLevel(SheetType::Override, false, true);
    1178        3999 :   if (mRuleProcessors[SheetType::Override])
    1179           0 :     (*aCollectorFunc)(mRuleProcessors[SheetType::Override], aData);
    1180        3999 :   nsRuleNode* lastOvrRN = aRuleWalker->CurrentNode();
    1181        3999 :   bool haveImportantOverrideRules = !aRuleWalker->GetCheckForImportantRules();
    1182             : 
    1183             :   // This needs to match IsMoreSpecificThanAnimation() above.
    1184        3999 :   aRuleWalker->SetLevel(SheetType::Animation, false, false);
    1185        3999 :   (*aCollectorFunc)(mRuleProcessors[SheetType::Animation], aData);
    1186             : 
    1187        3999 :   if (haveAnyImportantScopedRules) {
    1188           0 :     for (uint32_t i = lastScopedRNs.Length(); i-- != 0; ) {
    1189           0 :       aRuleWalker->SetLevel(SheetType::ScopedDoc, true, false);
    1190           0 :       nsRuleNode* startRN = lastScopedRNs[i];
    1191           0 :       nsRuleNode* endRN = i == 0 ? lastDocRN : lastScopedRNs[i - 1];
    1192           0 :       if (haveImportantScopedRules[i]) {
    1193           0 :         AddImportantRules(startRN, endRN, aRuleWalker);  // scoped
    1194             :       }
    1195             : #ifdef DEBUG
    1196             :       else {
    1197           0 :         AssertNoImportantRules(startRN, endRN);
    1198             :       }
    1199             : #endif
    1200             :     }
    1201             :   }
    1202             : #ifdef DEBUG
    1203             :   else {
    1204        3999 :     AssertNoImportantRules(lastScopedRN, lastDocRN);
    1205             :   }
    1206             : #endif
    1207             : 
    1208        3999 :   if (haveImportantDocRules) {
    1209         238 :     aRuleWalker->SetLevel(SheetType::Doc, true, false);
    1210         238 :     AddImportantRules(lastDocRN, lastPresHintRN, aRuleWalker);  // doc
    1211             :   }
    1212             : #ifdef DEBUG
    1213             :   else {
    1214        3761 :     AssertNoImportantRules(lastDocRN, lastPresHintRN);
    1215             :   }
    1216             : #endif
    1217             : 
    1218        3999 :   if (haveImportantStyleAttrRules) {
    1219           0 :     aRuleWalker->SetLevel(SheetType::StyleAttr, true, false);
    1220           0 :     AddImportantRules(lastStyleAttrRN, lastScopedRN, aRuleWalker);  // style attr
    1221             :   }
    1222             : #ifdef DEBUG
    1223             :   else {
    1224        3999 :     AssertNoImportantRules(lastStyleAttrRN, lastScopedRN);
    1225             :   }
    1226             : #endif
    1227             : 
    1228        3999 :   if (haveImportantOverrideRules) {
    1229           0 :     aRuleWalker->SetLevel(SheetType::Override, true, false);
    1230           0 :     AddImportantRules(lastOvrRN, lastStyleAttrRN, aRuleWalker);  // override
    1231             :   }
    1232             : #ifdef DEBUG
    1233             :   else {
    1234        3999 :     AssertNoImportantRules(lastOvrRN, lastStyleAttrRN);
    1235             :   }
    1236             : #endif
    1237             : 
    1238             : #ifdef DEBUG
    1239        3999 :   AssertNoCSSRules(lastPresHintRN, lastUserRN);
    1240             : #endif
    1241             : 
    1242        3999 :   if (haveImportantUserRules) {
    1243           0 :     aRuleWalker->SetLevel(SheetType::User, true, false);
    1244           0 :     AddImportantRules(lastUserRN, lastAgentRN, aRuleWalker); //user
    1245             :   }
    1246             : #ifdef DEBUG
    1247             :   else {
    1248        3999 :     AssertNoImportantRules(lastUserRN, lastAgentRN);
    1249             :   }
    1250             : #endif
    1251             : 
    1252        3999 :   if (haveImportantUARules) {
    1253         241 :     aRuleWalker->SetLevel(SheetType::Agent, true, false);
    1254         241 :     AddImportantRules(lastAgentRN, lastRestrictionRN, aRuleWalker); //agent
    1255             :   }
    1256             : #ifdef DEBUG
    1257             :   else {
    1258        3758 :     AssertNoImportantRules(lastAgentRN, lastRestrictionRN);
    1259             :   }
    1260             : #endif
    1261             : 
    1262             : #ifdef DEBUG
    1263        3999 :   AssertNoCSSRules(lastRestrictionRN, mRuleTree);
    1264             : #endif
    1265             : 
    1266             : #ifdef DEBUG
    1267        3999 :   nsRuleNode *lastImportantRN = aRuleWalker->CurrentNode();
    1268             : #endif
    1269        3999 :   aRuleWalker->SetLevel(SheetType::Transition, false, false);
    1270        3999 :   (*aCollectorFunc)(mRuleProcessors[SheetType::Transition], aData);
    1271             : #ifdef DEBUG
    1272        3999 :   AssertNoCSSRules(aRuleWalker->CurrentNode(), lastImportantRN);
    1273             : #endif
    1274             : 
    1275        3999 : }
    1276             : 
    1277             : // Enumerate all the rules in a way that doesn't care about the order
    1278             : // of the rules and doesn't walk !important-rules.
    1279             : void
    1280         701 : nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
    1281             :                                ElementDependentRuleProcessorData* aData,
    1282             :                                bool aWalkAllXBLStylesheets)
    1283             : {
    1284         701 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    1285             : 
    1286         701 :   if (mRuleProcessors[SheetType::Agent])
    1287         701 :     (*aFunc)(mRuleProcessors[SheetType::Agent], aData);
    1288             : 
    1289         701 :   bool skipUserStyles = aData->mElement->IsInNativeAnonymousSubtree();
    1290         701 :   if (!skipUserStyles && mRuleProcessors[SheetType::User]) // NOTE: different
    1291           1 :     (*aFunc)(mRuleProcessors[SheetType::User], aData);
    1292             : 
    1293         701 :   if (mRuleProcessors[SheetType::PresHint])
    1294         701 :     (*aFunc)(mRuleProcessors[SheetType::PresHint], aData);
    1295             : 
    1296         701 :   bool cutOffInheritance = false;
    1297         701 :   if (mBindingManager) {
    1298             :     // We can supply additional document-level sheets that should be walked.
    1299         701 :     if (aWalkAllXBLStylesheets) {
    1300           2 :       mBindingManager->WalkAllRules(aFunc, aData);
    1301             :     } else {
    1302         699 :       mBindingManager->WalkRules(aFunc, aData, &cutOffInheritance);
    1303             :     }
    1304             :   }
    1305         701 :   if (!skipUserStyles && !cutOffInheritance) {
    1306         517 :     if (mRuleProcessors[SheetType::Doc]) // NOTE: different
    1307         514 :       (*aFunc)(mRuleProcessors[SheetType::Doc], aData);
    1308         517 :     if (aData->mElement->IsElementInStyleScope()) {
    1309           0 :       for (uint32_t i = 0; i < mScopedDocSheetRuleProcessors.Length(); i++)
    1310           0 :         (*aFunc)(mScopedDocSheetRuleProcessors[i], aData);
    1311             :     }
    1312             :   }
    1313         701 :   if (mRuleProcessors[SheetType::StyleAttr])
    1314         701 :     (*aFunc)(mRuleProcessors[SheetType::StyleAttr], aData);
    1315         701 :   if (mRuleProcessors[SheetType::Override])
    1316           0 :     (*aFunc)(mRuleProcessors[SheetType::Override], aData);
    1317         701 :   (*aFunc)(mRuleProcessors[SheetType::Animation], aData);
    1318         701 :   (*aFunc)(mRuleProcessors[SheetType::Transition], aData);
    1319         701 : }
    1320             : 
    1321             : static void
    1322        1855 : InitStyleScopes(TreeMatchContext& aTreeContext, Element* aElement)
    1323             : {
    1324        1855 :   if (aElement->IsElementInStyleScope()) {
    1325           0 :     aTreeContext.InitStyleScopes(aElement->GetParentElementCrossingShadowRoot());
    1326             :   }
    1327        1855 : }
    1328             : 
    1329             : already_AddRefed<nsStyleContext>
    1330         349 : nsStyleSet::ResolveStyleFor(Element* aElement,
    1331             :                             nsStyleContext* aParentContext)
    1332             : {
    1333             :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1334         698 :                                aElement->OwnerDoc());
    1335         349 :   InitStyleScopes(treeContext, aElement);
    1336         698 :   return ResolveStyleFor(aElement, aParentContext, treeContext);
    1337             : }
    1338             : 
    1339             : already_AddRefed<nsStyleContext>
    1340        2501 : nsStyleSet::ResolveStyleForInternal(Element* aElement,
    1341             :                                     nsStyleContext* aParentContext,
    1342             :                                     TreeMatchContext& aTreeMatchContext,
    1343             :                                     AnimationFlag aAnimationFlag)
    1344             : {
    1345        2501 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    1346        2501 :   NS_ASSERTION(aElement, "aElement must not be null");
    1347             : 
    1348        5002 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    1349        2501 :   aTreeMatchContext.ResetForUnvisitedMatching();
    1350             :   ElementRuleProcessorData data(PresContext(), aElement, &ruleWalker,
    1351        2501 :                                 aTreeMatchContext);
    1352        2501 :   WalkDisableTextZoomRule(aElement, &ruleWalker);
    1353             :   FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
    1354        2501 :             &ruleWalker);
    1355             : 
    1356        2501 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1357        2501 :   nsRuleNode *visitedRuleNode = nullptr;
    1358             : 
    1359        2501 :   if (aTreeMatchContext.HaveRelevantLink()) {
    1360           0 :     aTreeMatchContext.ResetForVisitedMatching();
    1361           0 :     ruleWalker.Reset();
    1362             :     FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aElement,
    1363           0 :               &ruleWalker);
    1364           0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1365             :   }
    1366             : 
    1367        2501 :   uint32_t flags = (aAnimationFlag == eWithAnimation) ? eDoAnimation : eNoFlags;
    1368        2501 :   if (nsCSSRuleProcessor::IsLink(aElement)) {
    1369           0 :     flags |= eIsLink;
    1370             :   }
    1371        5002 :   if (nsCSSRuleProcessor::GetContentState(aElement, aTreeMatchContext).
    1372        5002 :                             HasState(NS_EVENT_STATE_VISITED)) {
    1373           0 :     flags |= eIsVisitedLink;
    1374             :   }
    1375        2501 :   if (aTreeMatchContext.mSkippingParentDisplayBasedStyleFixup) {
    1376         807 :     flags |= eSkipParentDisplayBasedStyleFixup;
    1377             :   }
    1378             : 
    1379             :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
    1380             :                     nullptr, CSSPseudoElementType::NotPseudo,
    1381        2501 :                     aElement, flags);
    1382             : }
    1383             : 
    1384             : already_AddRefed<nsStyleContext>
    1385        2501 : nsStyleSet::ResolveStyleFor(Element* aElement,
    1386             :                             nsStyleContext* aParentContext,
    1387             :                             TreeMatchContext& aTreeMatchContext)
    1388             : {
    1389             :   return ResolveStyleForInternal(aElement,
    1390             :                                  aParentContext,
    1391             :                                  aTreeMatchContext,
    1392        2501 :                                  eWithAnimation);
    1393             : }
    1394             : 
    1395             : already_AddRefed<nsStyleContext>
    1396           0 : nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
    1397             :                                  const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules)
    1398             : {
    1399           0 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    1400             : 
    1401           0 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    1402             :   // FIXME: Perhaps this should be passed in, but it probably doesn't
    1403             :   // matter.
    1404           0 :   ruleWalker.SetLevel(SheetType::Doc, false, false);
    1405           0 :   for (uint32_t i = 0; i < aRules.Length(); i++) {
    1406           0 :     ruleWalker.ForwardOnPossiblyCSSRule(aRules.ElementAt(i));
    1407             :   }
    1408             : 
    1409             :   return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
    1410             :                     nullptr, CSSPseudoElementType::NotPseudo,
    1411           0 :                     nullptr, eNoFlags);
    1412             : }
    1413             : 
    1414             : already_AddRefed<nsStyleContext>
    1415          20 : nsStyleSet::ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
    1416             :                                       const nsCOMArray<nsIStyleRule> &aRules)
    1417             : {
    1418          20 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    1419             : 
    1420          40 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    1421          20 :   ruleWalker.SetCurrentNode(aBaseContext->RuleNode());
    1422             :   // This needs to be the transition sheet because that is the highest
    1423             :   // level of the cascade, and thus the only thing that makes sense if
    1424             :   // we are ever going to call ResolveStyleWithReplacement on the
    1425             :   // resulting context.  It's also the right thing for the one case (the
    1426             :   // transition manager's cover rule) where we put the result of this
    1427             :   // function in the style context tree.
    1428          20 :   ruleWalker.SetLevel(SheetType::Transition, false, false);
    1429          40 :   for (int32_t i = 0; i < aRules.Count(); i++) {
    1430          20 :     ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
    1431             :   }
    1432             : 
    1433          20 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1434          20 :   nsRuleNode *visitedRuleNode = nullptr;
    1435             : 
    1436          20 :   if (aBaseContext->GetStyleIfVisited()) {
    1437           0 :     ruleWalker.SetCurrentNode(aBaseContext->GetStyleIfVisited()->RuleNode());
    1438           0 :     for (int32_t i = 0; i < aRules.Count(); i++) {
    1439           0 :       ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
    1440             :     }
    1441           0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1442             :   }
    1443             : 
    1444          20 :   uint32_t flags = eNoFlags;
    1445          20 :   if (aBaseContext->IsLinkContext()) {
    1446           0 :     flags |= eIsLink;
    1447             : 
    1448             :     // GetContext handles propagating RelevantLinkVisited state from the
    1449             :     // parent in non-link cases; all we need to pass in is if this link
    1450             :     // is visited.
    1451           0 :     if (aBaseContext->RelevantLinkVisited()) {
    1452           0 :       flags |= eIsVisitedLink;
    1453             :     }
    1454             :   }
    1455          20 :   return GetContext(aBaseContext->GetParent(), ruleNode, visitedRuleNode,
    1456             :                     aBaseContext->GetPseudo(),
    1457             :                     aBaseContext->GetPseudoType(),
    1458          40 :                     nullptr, flags);
    1459             : }
    1460             : 
    1461             : struct RuleNodeInfo {
    1462             :   nsIStyleRule* mRule;
    1463             :   SheetType mLevel;
    1464             :   bool mIsImportant;
    1465             :   bool mIsAnimationRule;
    1466             : };
    1467             : 
    1468             : struct CascadeLevel {
    1469             :   SheetType mLevel;
    1470             :   bool mIsImportant;
    1471             :   bool mCheckForImportantRules;
    1472             :   nsRestyleHint mLevelReplacementHint;
    1473             : };
    1474             : 
    1475             : static const CascadeLevel gCascadeLevels[] = {
    1476             :   { SheetType::Agent,            false, false, nsRestyleHint(0) },
    1477             :   { SheetType::User,             false, false, nsRestyleHint(0) },
    1478             :   { SheetType::PresHint,         false, false, nsRestyleHint(0) },
    1479             :   { SheetType::Doc,              false, false, nsRestyleHint(0) },
    1480             :   { SheetType::ScopedDoc,        false, false, nsRestyleHint(0) },
    1481             :   { SheetType::StyleAttr,        false, true,  eRestyle_StyleAttribute |
    1482             :                                                eRestyle_StyleAttribute_Animations },
    1483             :   { SheetType::Override,         false, false, nsRestyleHint(0) },
    1484             :   { SheetType::Animation,        false, false, eRestyle_CSSAnimations },
    1485             :   { SheetType::ScopedDoc,        true,  false, nsRestyleHint(0) },
    1486             :   { SheetType::Doc,              true,  false, nsRestyleHint(0) },
    1487             :   { SheetType::StyleAttr,        true,  false, eRestyle_StyleAttribute |
    1488             :                                                eRestyle_StyleAttribute_Animations },
    1489             :   { SheetType::Override,         true,  false, nsRestyleHint(0) },
    1490             :   { SheetType::User,             true,  false, nsRestyleHint(0) },
    1491             :   { SheetType::Agent,            true,  false, nsRestyleHint(0) },
    1492             :   { SheetType::Transition,       false, false, eRestyle_CSSTransitions },
    1493             : };
    1494             : 
    1495             : nsRuleNode*
    1496          49 : nsStyleSet::RuleNodeWithReplacement(Element* aElement,
    1497             :                                     Element* aPseudoElement,
    1498             :                                     nsRuleNode* aOldRuleNode,
    1499             :                                     CSSPseudoElementType aPseudoType,
    1500             :                                     nsRestyleHint aReplacements)
    1501             : {
    1502          49 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    1503             : 
    1504          49 :   MOZ_ASSERT(!aPseudoElement ==
    1505             :              (aPseudoType >= CSSPseudoElementType::Count ||
    1506             :               !(nsCSSPseudoElements::PseudoElementSupportsStyleAttribute(aPseudoType) ||
    1507             :                 nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudoType))),
    1508             :              "should have aPseudoElement only for certain pseudo elements");
    1509             : 
    1510             :   // Remove the Force bits, which we don't need and which could confuse
    1511             :   // the remainingReplacements code below.
    1512          49 :   aReplacements &= ~(eRestyle_Force | eRestyle_ForceDescendants);
    1513             : 
    1514          49 :   MOZ_ASSERT(!(aReplacements & ~(eRestyle_CSSTransitions |
    1515             :                                  eRestyle_CSSAnimations |
    1516             :                                  eRestyle_StyleAttribute |
    1517             :                                  eRestyle_StyleAttribute_Animations)),
    1518             :              "unexpected replacement bits");
    1519             : 
    1520             :   // This array can be hot and often grows to ~20 elements, so inline storage
    1521             :   // is best.
    1522          98 :   AutoTArray<RuleNodeInfo, 30> rules;
    1523             : 
    1524          49 :   const CascadeLevel* startingLevel = gCascadeLevels;
    1525          49 :   nsRuleNode* startingNode = mRuleTree;
    1526          49 :   if (mInReconstruct) {
    1527             :     // Replace the entire path in the rule tree, since the rule tree has
    1528             :     // a new root.
    1529             : 
    1530         144 :     for (nsRuleNode* ruleNode = aOldRuleNode; !ruleNode->IsRoot();
    1531             :          ruleNode = ruleNode->GetParent()) {
    1532         118 :       RuleNodeInfo* curRule = rules.AppendElement();
    1533         118 :       curRule->mRule = ruleNode->GetRule();
    1534         118 :       curRule->mLevel = ruleNode->GetLevel();
    1535         118 :       curRule->mIsImportant = ruleNode->IsImportantRule();
    1536         118 :       curRule->mIsAnimationRule = ruleNode->IsAnimationRule();
    1537             :     }
    1538             :   } else {
    1539          23 :     if (aReplacements == nsRestyleHint(0)) {
    1540             :       // Nothing to do.
    1541           0 :       return aOldRuleNode;
    1542             :     }
    1543             : 
    1544             :     // Walk up the rule tree from aOldNode to figure out the *part* of
    1545             :     // the path in the rule tree that we need to replace.
    1546             : 
    1547          23 :     nsRestyleHint remainingReplacements = aReplacements;
    1548          23 :     nsRuleNode* ruleNode = aOldRuleNode;
    1549         100 :     for (const CascadeLevel *level = ArrayEnd(gCascadeLevels);
    1550          50 :          level-- != gCascadeLevels; ) {
    1551             :       SheetType nodeLevel;
    1552             :       bool nodeIsImportant;
    1553         240 :       while (!ruleNode->IsRoot() &&
    1554         138 :              (nodeLevel = ruleNode->GetLevel()) == level->mLevel &&
    1555             :              (nodeIsImportant = ruleNode->IsImportantRule()) ==
    1556          11 :                level->mIsImportant) {
    1557           8 :         if (!(level->mLevelReplacementHint & aReplacements)) {
    1558           0 :           RuleNodeInfo* curRule = rules.AppendElement();
    1559           0 :           curRule->mRule = ruleNode->GetRule();
    1560           0 :           curRule->mLevel = nodeLevel;
    1561           0 :           curRule->mIsImportant = nodeIsImportant;
    1562           0 :           curRule->mIsAnimationRule = ruleNode->IsAnimationRule();
    1563             :         }
    1564             : 
    1565           8 :         ruleNode = ruleNode->GetParent();
    1566             :       }
    1567          82 :       if (!level->mIsImportant &&
    1568          32 :           (level->mLevelReplacementHint & aReplacements)) {
    1569          23 :         remainingReplacements &= ~level->mLevelReplacementHint;
    1570          23 :         if (remainingReplacements == nsRestyleHint(0)) {
    1571             :           // We've found the part of the path in the rule tree we
    1572             :           // need to replace.
    1573          23 :           startingLevel = level;
    1574          23 :           startingNode = ruleNode;
    1575          23 :           break;
    1576             :         }
    1577             :       }
    1578             :     }
    1579          23 :     MOZ_ASSERT(remainingReplacements == nsRestyleHint(0),
    1580             :                "unexpected replacements (but we safely handle this case by "
    1581             :                "falling through to replacing the whole path");
    1582             :   }
    1583             : 
    1584          98 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    1585          49 :   ruleWalker.SetCurrentNode(startingNode);
    1586          49 :   auto rulesIndex = rules.Length();
    1587             : 
    1588             :   // We need to transfer this information between the non-!important and
    1589             :   // !important phases for the style attribute level.
    1590          49 :   nsRuleNode* lastScopedRN = nullptr;
    1591          49 :   nsRuleNode* lastStyleAttrRN = nullptr;
    1592          49 :   bool haveImportantStyleAttrRules = false;
    1593             : 
    1594         489 :   for (const CascadeLevel *level = startingLevel,
    1595          49 :                        *levelEnd = ArrayEnd(gCascadeLevels);
    1596         489 :        level != levelEnd; ++level) {
    1597             : 
    1598         440 :     bool doReplace = level->mLevelReplacementHint & aReplacements;
    1599             : 
    1600         440 :     ruleWalker.SetLevel(level->mLevel, level->mIsImportant,
    1601         880 :                         level->mCheckForImportantRules && doReplace);
    1602             : 
    1603         440 :     if (doReplace) {
    1604          30 :       switch (level->mLevel) {
    1605             :         case SheetType::Animation: {
    1606           0 :           if (aPseudoType == CSSPseudoElementType::NotPseudo ||
    1607           0 :               aPseudoType == CSSPseudoElementType::before ||
    1608             :               aPseudoType == CSSPseudoElementType::after) {
    1609             :             nsIStyleRule* rule = PresContext()->EffectCompositor()->
    1610           0 :               GetAnimationRule(aElement, aPseudoType,
    1611             :                                EffectCompositor::CascadeLevel::Animations,
    1612           0 :                                nullptr);
    1613           0 :             if (rule) {
    1614           0 :               ruleWalker.ForwardOnPossiblyCSSRule(rule);
    1615           0 :               ruleWalker.CurrentNode()->SetIsAnimationRule();
    1616             :             }
    1617             :           }
    1618           0 :           break;
    1619             :         }
    1620             :         case SheetType::Transition: {
    1621          24 :           if (aPseudoType == CSSPseudoElementType::NotPseudo ||
    1622           0 :               aPseudoType == CSSPseudoElementType::before ||
    1623             :               aPseudoType == CSSPseudoElementType::after) {
    1624             :             nsIStyleRule* rule = PresContext()->EffectCompositor()->
    1625          24 :               GetAnimationRule(aElement, aPseudoType,
    1626             :                                EffectCompositor::CascadeLevel::Transitions,
    1627          24 :                                nullptr);
    1628          24 :             if (rule) {
    1629           8 :               ruleWalker.ForwardOnPossiblyCSSRule(rule);
    1630           8 :               ruleWalker.CurrentNode()->SetIsAnimationRule();
    1631             :             }
    1632             :           }
    1633          24 :           break;
    1634             :         }
    1635             :         case SheetType::StyleAttr: {
    1636           6 :           if (!level->mIsImportant) {
    1637             :             // First time through, we handle the non-!important rule.
    1638             :             nsHTMLCSSStyleSheet* ruleProcessor =
    1639             :               static_cast<nsHTMLCSSStyleSheet*>(
    1640           3 :                 mRuleProcessors[SheetType::StyleAttr].get());
    1641           3 :             if (ruleProcessor) {
    1642           3 :               lastScopedRN = ruleWalker.CurrentNode();
    1643           3 :               if (aPseudoType ==
    1644             :                     CSSPseudoElementType::NotPseudo) {
    1645           3 :                 ruleProcessor->ElementRulesMatching(PresContext(),
    1646             :                                                     aElement,
    1647           3 :                                                     &ruleWalker);
    1648           0 :               } else if (aPseudoType <
    1649           0 :                            CSSPseudoElementType::Count &&
    1650             :                          nsCSSPseudoElements::
    1651           0 :                            PseudoElementSupportsStyleAttribute(aPseudoType)) {
    1652             :                 ruleProcessor->PseudoElementRulesMatching(aPseudoElement,
    1653             :                                                           aPseudoType,
    1654           0 :                                                           &ruleWalker);
    1655             :               }
    1656           3 :               lastStyleAttrRN = ruleWalker.CurrentNode();
    1657           3 :               haveImportantStyleAttrRules =
    1658           3 :                 !ruleWalker.GetCheckForImportantRules();
    1659             :             }
    1660             :           } else {
    1661             :             // Second time through, we handle the !important rule(s).
    1662           3 :             if (haveImportantStyleAttrRules) {
    1663           0 :               AddImportantRules(lastStyleAttrRN, lastScopedRN, &ruleWalker);
    1664             :             }
    1665             :           }
    1666           6 :           break;
    1667             :         }
    1668             :         default:
    1669           0 :           MOZ_ASSERT(false, "unexpected result from gCascadeLevels lookup");
    1670             :           break;
    1671             :       }
    1672             :     }
    1673             : 
    1674         676 :     while (rulesIndex != 0) {
    1675         234 :       --rulesIndex;
    1676         234 :       const RuleNodeInfo& ruleInfo = rules[rulesIndex];
    1677             : 
    1678         358 :       if (ruleInfo.mLevel != level->mLevel ||
    1679         124 :           ruleInfo.mIsImportant != level->mIsImportant) {
    1680         116 :         ++rulesIndex;
    1681         116 :         break;
    1682             :       }
    1683             : 
    1684             :       // When mIsReconstruct is true, we have rules we need to skip in
    1685             :       // the array, so we need to test !doReplace here.
    1686         118 :       if (!doReplace) {
    1687         116 :         ruleWalker.ForwardOnPossiblyCSSRule(ruleInfo.mRule);
    1688         116 :         if (ruleInfo.mIsAnimationRule) {
    1689           0 :           ruleWalker.CurrentNode()->SetIsAnimationRule();
    1690             :         }
    1691             :       }
    1692             :     }
    1693             :   }
    1694             : 
    1695          49 :   NS_ASSERTION(rulesIndex == 0,
    1696             :                "rules are in incorrect cascading order, "
    1697             :                "which means we replaced them incorrectly");
    1698             : 
    1699          49 :   return ruleWalker.CurrentNode();
    1700             : }
    1701             : 
    1702             : static bool
    1703         231 : SkipsParentDisplayBasedStyleFixup(nsStyleContext* aStyleContext)
    1704             : {
    1705         231 :   CSSPseudoElementType type = aStyleContext->GetPseudoType();
    1706         231 :   switch (type) {
    1707             :     case CSSPseudoElementType::InheritingAnonBox:
    1708          19 :        return nsCSSAnonBoxes::AnonBoxSkipsParentDisplayBasedStyleFixup(
    1709          19 :                 aStyleContext->GetPseudo());
    1710             :     case CSSPseudoElementType::NonInheritingAnonBox:
    1711           0 :        return true;
    1712             :     case CSSPseudoElementType::NotPseudo:
    1713         206 :        return false;
    1714             :     default:
    1715           6 :        return !nsCSSPseudoElements::PseudoElementIsFlexOrGridItem(type);
    1716             :   }
    1717             : }
    1718             : 
    1719             : already_AddRefed<nsStyleContext>
    1720          49 : nsStyleSet::ResolveStyleWithReplacement(Element* aElement,
    1721             :                                         Element* aPseudoElement,
    1722             :                                         nsStyleContext* aNewParentContext,
    1723             :                                         nsStyleContext* aOldStyleContext,
    1724             :                                         nsRestyleHint aReplacements,
    1725             :                                         uint32_t aFlags)
    1726             : {
    1727             :   nsRuleNode* ruleNode =
    1728          49 :     RuleNodeWithReplacement(aElement, aPseudoElement,
    1729             :                             aOldStyleContext->RuleNode(),
    1730          49 :                             aOldStyleContext->GetPseudoType(), aReplacements);
    1731             : 
    1732          49 :   nsRuleNode* visitedRuleNode = nullptr;
    1733          49 :   nsStyleContext* oldStyleIfVisited = aOldStyleContext->GetStyleIfVisited();
    1734          49 :   if (oldStyleIfVisited) {
    1735           0 :     if (oldStyleIfVisited->RuleNode() == aOldStyleContext->RuleNode()) {
    1736           0 :       visitedRuleNode = ruleNode;
    1737             :     } else {
    1738             :       visitedRuleNode =
    1739           0 :         RuleNodeWithReplacement(aElement, aPseudoElement,
    1740             :                                 oldStyleIfVisited->RuleNode(),
    1741             :                                 oldStyleIfVisited->GetPseudoType(),
    1742           0 :                                 aReplacements);
    1743             :     }
    1744             :   }
    1745             : 
    1746          49 :   uint32_t flags = eNoFlags;
    1747          49 :   if (aOldStyleContext->IsLinkContext()) {
    1748           0 :     flags |= eIsLink;
    1749             : 
    1750             :     // GetContext handles propagating RelevantLinkVisited state from the
    1751             :     // parent in non-link cases; all we need to pass in is if this link
    1752             :     // is visited.
    1753           0 :     if (aOldStyleContext->RelevantLinkVisited()) {
    1754           0 :       flags |= eIsVisitedLink;
    1755             :     }
    1756             :   }
    1757             : 
    1758          49 :   CSSPseudoElementType pseudoType = aOldStyleContext->GetPseudoType();
    1759          49 :   Element* elementForAnimation = nullptr;
    1760          49 :   if (!(aFlags & eSkipStartingAnimations) &&
    1761           3 :       (pseudoType == CSSPseudoElementType::NotPseudo ||
    1762           3 :        pseudoType == CSSPseudoElementType::before ||
    1763             :        pseudoType == CSSPseudoElementType::after)) {
    1764             :     // We want to compute a correct elementForAnimation to pass in
    1765             :     // because at this point the parameter is more than just the element
    1766             :     // for animation; it's also used for the SetBodyTextColor call when
    1767             :     // it's the body element.
    1768             :     // However, we only want to set the flag to call UpdateAnimations
    1769             :     // if we're dealing with a replacement (such as style attribute
    1770             :     // replacement) that could lead to the animation property changing,
    1771             :     // and we explicitly do NOT want to call UpdateAnimations when
    1772             :     // we're trying to do an animation-only update.
    1773          38 :     if (aReplacements & ~(eRestyle_CSSTransitions | eRestyle_CSSAnimations)) {
    1774          22 :       flags |= eDoAnimation;
    1775             :     }
    1776          38 :     elementForAnimation = aElement;
    1777             : #ifdef DEBUG
    1778             :     {
    1779          38 :       nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(elementForAnimation);
    1780          38 :       NS_ASSERTION(pseudoType == CSSPseudoElementType::NotPseudo ||
    1781             :                    !styleFrame ||
    1782             :                    styleFrame->StyleContext()->GetPseudoType() ==
    1783             :                      CSSPseudoElementType::NotPseudo,
    1784             :                    "aElement should be the element and not the pseudo-element");
    1785             :     }
    1786             : #endif
    1787             :   }
    1788             : 
    1789          60 :   if ((aElement && aElement->IsRootOfAnonymousSubtree()) ||
    1790          11 :       SkipsParentDisplayBasedStyleFixup(aOldStyleContext)) {
    1791             :     // For anonymous subtree roots, don't tweak "display" value based on whether
    1792             :     // or not the parent is styled as a flex/grid container. (If the parent
    1793             :     // has anonymous-subtree kids, then we know it's not actually going to get
    1794             :     // a flex/grid container frame, anyway.)  Same for certain anonymous boxes
    1795             :     // and most pseudos.
    1796          38 :     flags |= eSkipParentDisplayBasedStyleFixup;
    1797             :   }
    1798             : 
    1799             :   return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
    1800             :                     aOldStyleContext->GetPseudo(), pseudoType,
    1801          49 :                     elementForAnimation, flags);
    1802             : }
    1803             : 
    1804             : already_AddRefed<nsStyleContext>
    1805           8 : nsStyleSet::ResolveStyleByRemovingAnimation(dom::Element* aTarget,
    1806             :                                             nsStyleContext* aStyleContext,
    1807             :                                             nsRestyleHint aWhichToRemove)
    1808             : {
    1809             : #ifdef DEBUG
    1810           8 :   CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
    1811             : #endif
    1812           8 :   MOZ_ASSERT(pseudoType == CSSPseudoElementType::NotPseudo ||
    1813             :              pseudoType == CSSPseudoElementType::before ||
    1814             :              pseudoType == CSSPseudoElementType::after,
    1815             :              "unexpected type for animations");
    1816           8 :   MOZ_ASSERT(PresContext()->RestyleManager()->IsGecko(),
    1817             :              "stylo: the style set and restyle manager must have the same "
    1818             :              "StyleBackendType");
    1819             :   GeckoRestyleManager* restyleManager =
    1820           8 :     PresContext()->RestyleManager()->AsGecko();
    1821             : 
    1822           8 :   bool oldSkipAnimationRules = restyleManager->SkipAnimationRules();
    1823           8 :   restyleManager->SetSkipAnimationRules(true);
    1824             : 
    1825             :   RefPtr<nsStyleContext> result =
    1826          16 :     ResolveStyleWithReplacement(aTarget, nullptr, aStyleContext->GetParent(),
    1827             :                                 aStyleContext, aWhichToRemove,
    1828          16 :                                 eSkipStartingAnimations);
    1829             : 
    1830           8 :   restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
    1831             : 
    1832          16 :   return result.forget();
    1833             : }
    1834             : 
    1835             : already_AddRefed<nsStyleContext>
    1836           0 : nsStyleSet::ResolveStyleWithoutAnimation(Element* aTarget,
    1837             :                                          nsStyleContext* aParentContext)
    1838             : {
    1839             :   GeckoRestyleManager* restyleManager =
    1840           0 :     PresContext()->RestyleManager()->AsGecko();
    1841             : 
    1842             :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1843           0 :                                aTarget->OwnerDoc());
    1844           0 :   InitStyleScopes(treeContext, aTarget);
    1845             : 
    1846           0 :   bool oldSkipAnimationRules = restyleManager->SkipAnimationRules();
    1847           0 :   restyleManager->SetSkipAnimationRules(true);
    1848             : 
    1849             :   // Here we can call ResolveStyleForInternal() instead of
    1850             :   // ResolveStyleWithReplacement() since we don't need any animation rules
    1851             :   // (CSS Animations, Transitions and script animations). That's because
    1852             :   // EffectCompositor::GetAnimationRule() skips all of animations rules if
    1853             :   // SkipAnimationRules flag is true.
    1854           0 :   RefPtr<nsStyleContext> result = ResolveStyleForInternal(aTarget,
    1855             :                                                           aParentContext,
    1856             :                                                           treeContext,
    1857           0 :                                                           eWithoutAnimation);
    1858             : 
    1859           0 :   restyleManager->SetSkipAnimationRules(oldSkipAnimationRules);
    1860             : 
    1861           0 :   return result.forget();
    1862             : }
    1863             : 
    1864             : already_AddRefed<nsStyleContext>
    1865         221 : nsStyleSet::ResolveStyleForText(nsIContent* aTextNode,
    1866             :                                 nsStyleContext* aParentContext)
    1867             : {
    1868         221 :   MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
    1869             :   return GetContext(aParentContext, mRuleTree, nullptr,
    1870             :                     nsCSSAnonBoxes::mozText,
    1871         221 :                     CSSPseudoElementType::InheritingAnonBox, nullptr, eNoFlags);
    1872             : }
    1873             : 
    1874             : already_AddRefed<nsStyleContext>
    1875           0 : nsStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
    1876             : {
    1877             :   return GetContext(aParentContext, mRuleTree, nullptr,
    1878             :                     nsCSSAnonBoxes::firstLetterContinuation,
    1879           0 :                     CSSPseudoElementType::InheritingAnonBox, nullptr, eNoFlags);
    1880             : }
    1881             : 
    1882             : already_AddRefed<nsStyleContext>
    1883         139 : nsStyleSet::ResolveStyleForPlaceholder()
    1884             : {
    1885             :   RefPtr<nsStyleContext>& cache =
    1886         139 :     mNonInheritingStyleContexts[nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
    1887         139 :   if (cache) {
    1888         274 :     RefPtr<nsStyleContext> retval = cache;
    1889         137 :     return retval.forget();
    1890             :   }
    1891             : 
    1892             :   RefPtr<nsStyleContext> retval =
    1893           4 :     GetContext(nullptr, mRuleTree, nullptr,
    1894             :                nsCSSAnonBoxes::oofPlaceholder,
    1895           4 :                CSSPseudoElementType::NonInheritingAnonBox, nullptr, eNoFlags);
    1896           2 :   cache = retval;
    1897           2 :   return retval.forget();
    1898             : }
    1899             : 
    1900             : void
    1901        1288 : nsStyleSet::WalkRestrictionRule(CSSPseudoElementType aPseudoType,
    1902             :                                 nsRuleWalker* aRuleWalker)
    1903             : {
    1904             :   // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
    1905        1288 :   aRuleWalker->SetLevel(SheetType::Agent, false, false);
    1906        1288 :   if (aPseudoType == CSSPseudoElementType::firstLetter)
    1907          48 :     aRuleWalker->Forward(mFirstLetterRule);
    1908        1240 :   else if (aPseudoType == CSSPseudoElementType::firstLine)
    1909          31 :     aRuleWalker->Forward(mFirstLineRule);
    1910        1209 :   else if (aPseudoType == CSSPseudoElementType::placeholder)
    1911           8 :     aRuleWalker->Forward(mPlaceholderRule);
    1912        1288 : }
    1913             : 
    1914             : void
    1915        2501 : nsStyleSet::WalkDisableTextZoomRule(Element* aElement, nsRuleWalker* aRuleWalker)
    1916             : {
    1917        2501 :   aRuleWalker->SetLevel(SheetType::Agent, false, false);
    1918        2501 :   if (aElement->IsSVGElement(nsGkAtoms::text))
    1919           0 :     aRuleWalker->Forward(mDisableTextZoomStyleRule);
    1920        2501 : }
    1921             : 
    1922             : already_AddRefed<nsStyleContext>
    1923           8 : nsStyleSet::ResolvePseudoElementStyleInternal(
    1924             :   Element* aParentElement,
    1925             :   CSSPseudoElementType aType,
    1926             :   nsStyleContext* aParentContext,
    1927             :   Element* aPseudoElement,
    1928             :   AnimationFlag aAnimationFlag)
    1929             : {
    1930           8 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    1931             : 
    1932           8 :   NS_ASSERTION(aType < CSSPseudoElementType::Count,
    1933             :                "must have pseudo element type");
    1934           8 :   NS_ASSERTION(aParentElement, "Must have parent element");
    1935             : 
    1936          16 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    1937             :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    1938          16 :                                aParentElement->OwnerDoc());
    1939           8 :   InitStyleScopes(treeContext, aParentElement);
    1940             :   PseudoElementRuleProcessorData data(PresContext(), aParentElement,
    1941             :                                       &ruleWalker, aType, treeContext,
    1942           8 :                                       aPseudoElement);
    1943           8 :   WalkRestrictionRule(aType, &ruleWalker);
    1944             :   FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1945           8 :             aParentElement, &ruleWalker);
    1946             : 
    1947           8 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    1948           8 :   nsRuleNode *visitedRuleNode = nullptr;
    1949             : 
    1950           8 :   if (treeContext.HaveRelevantLink()) {
    1951           0 :     treeContext.ResetForVisitedMatching();
    1952           0 :     ruleWalker.Reset();
    1953           0 :     WalkRestrictionRule(aType, &ruleWalker);
    1954             :     FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    1955           0 :               aParentElement, &ruleWalker);
    1956           0 :     visitedRuleNode = ruleWalker.CurrentNode();
    1957             :   }
    1958             : 
    1959             :   // For pseudos, |data.IsLink()| being true means that
    1960             :   // our parent node is a link.
    1961           8 :   uint32_t flags = eNoFlags;
    1962           8 :   if (aType == CSSPseudoElementType::before ||
    1963             :       aType == CSSPseudoElementType::after) {
    1964           0 :     if (aAnimationFlag == eWithAnimation) {
    1965           0 :       flags |= eDoAnimation;
    1966             :     }
    1967             :   }
    1968             : 
    1969           8 :   if (!nsCSSPseudoElements::PseudoElementIsFlexOrGridItem(aType)) {
    1970             :     // Only pseudo-elements that act as items in flex and grid containers
    1971             :     // have parent display-based style fixup.
    1972           8 :     flags |= eSkipParentDisplayBasedStyleFixup;
    1973             :   }
    1974             : 
    1975             :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
    1976             :                     nsCSSPseudoElements::GetPseudoAtom(aType), aType,
    1977           8 :                     aParentElement, flags);
    1978             : }
    1979             : 
    1980             : already_AddRefed<nsStyleContext>
    1981           8 : nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
    1982             :                                       CSSPseudoElementType aType,
    1983             :                                       nsStyleContext* aParentContext,
    1984             :                                       Element* aPseudoElement)
    1985             : {
    1986             :   return ResolvePseudoElementStyleInternal(aParentElement,
    1987             :                                            aType,
    1988             :                                            aParentContext,
    1989             :                                            aPseudoElement,
    1990           8 :                                            eWithAnimation);
    1991             : }
    1992             : 
    1993             : already_AddRefed<nsStyleContext>
    1994           0 : nsStyleSet::ResolvePseudoElementStyleWithoutAnimation(
    1995             :   Element* aParentElement,
    1996             :   CSSPseudoElementType aType,
    1997             :   nsStyleContext* aParentContext,
    1998             :   Element* aPseudoElement)
    1999             : {
    2000             :   return ResolvePseudoElementStyleInternal(aParentElement,
    2001             :                                            aType,
    2002             :                                            aParentContext,
    2003             :                                            aPseudoElement,
    2004           0 :                                            eWithoutAnimation);
    2005             : }
    2006             : 
    2007             : already_AddRefed<nsStyleContext>
    2008         797 : nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
    2009             :                                     CSSPseudoElementType aType,
    2010             :                                     nsStyleContext* aParentContext)
    2011             : {
    2012             :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    2013        1594 :                                aParentElement->OwnerDoc());
    2014         797 :   InitStyleScopes(treeContext, aParentElement);
    2015             :   return ProbePseudoElementStyle(aParentElement, aType, aParentContext,
    2016        1594 :                                  treeContext);
    2017             : }
    2018             : 
    2019             : already_AddRefed<nsStyleContext>
    2020        1280 : nsStyleSet::ProbePseudoElementStyle(Element* aParentElement,
    2021             :                                     CSSPseudoElementType aType,
    2022             :                                     nsStyleContext* aParentContext,
    2023             :                                     TreeMatchContext& aTreeMatchContext)
    2024             : {
    2025        1280 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2026             : 
    2027        1280 :   NS_ASSERTION(aType < CSSPseudoElementType::Count,
    2028             :                "must have pseudo element type");
    2029        1280 :   NS_ASSERTION(aParentElement, "aParentElement must not be null");
    2030             : 
    2031        1280 :   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
    2032        2560 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    2033        1280 :   aTreeMatchContext.ResetForUnvisitedMatching();
    2034             :   PseudoElementRuleProcessorData data(PresContext(), aParentElement,
    2035             :                                       &ruleWalker, aType, aTreeMatchContext,
    2036        1280 :                                       /* aPseudoElement = */ nullptr);
    2037        1280 :   WalkRestrictionRule(aType, &ruleWalker);
    2038             :   // not the root if there was a restriction rule
    2039        1280 :   nsRuleNode *adjustedRoot = ruleWalker.CurrentNode();
    2040             :   FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    2041        1280 :             aParentElement, &ruleWalker);
    2042             : 
    2043        1280 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    2044        1280 :   if (ruleNode == adjustedRoot) {
    2045        1241 :     return nullptr;
    2046             :   }
    2047             : 
    2048          39 :   nsRuleNode *visitedRuleNode = nullptr;
    2049             : 
    2050          39 :   if (aTreeMatchContext.HaveRelevantLink()) {
    2051           0 :     aTreeMatchContext.ResetForVisitedMatching();
    2052           0 :     ruleWalker.Reset();
    2053           0 :     WalkRestrictionRule(aType, &ruleWalker);
    2054             :     FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
    2055           0 :               aParentElement, &ruleWalker);
    2056           0 :     visitedRuleNode = ruleWalker.CurrentNode();
    2057             :   }
    2058             : 
    2059             :   // For pseudos, |data.IsLink()| being true means that
    2060             :   // our parent node is a link.
    2061          39 :   uint32_t flags = eNoFlags;
    2062          39 :   if (aType == CSSPseudoElementType::before ||
    2063             :       aType == CSSPseudoElementType::after) {
    2064          39 :     flags |= eDoAnimation;
    2065             :   }
    2066             : 
    2067          39 :   if (!nsCSSPseudoElements::PseudoElementIsFlexOrGridItem(aType)) {
    2068             :     // Only pseudo-elements that act as items in flex and grid containers
    2069             :     // have parent display-based style fixup.
    2070           0 :     flags |= eSkipParentDisplayBasedStyleFixup;
    2071             :   }
    2072             : 
    2073             :   RefPtr<nsStyleContext> result =
    2074          78 :     GetContext(aParentContext, ruleNode, visitedRuleNode,
    2075             :                pseudoTag, aType,
    2076          78 :                aParentElement, flags);
    2077             : 
    2078             :   // For :before and :after pseudo-elements, having display: none or no
    2079             :   // 'content' property is equivalent to not having the pseudo-element
    2080             :   // at all.
    2081         117 :   if (result &&
    2082          58 :       (pseudoTag == nsCSSPseudoElements::before ||
    2083          58 :        pseudoTag == nsCSSPseudoElements::after)) {
    2084          39 :     const nsStyleDisplay *display = result->StyleDisplay();
    2085          39 :     const nsStyleContent *content = result->StyleContent();
    2086             :     // XXXldb What is contentCount for |content: ""|?
    2087          78 :     if (display->mDisplay == StyleDisplay::None ||
    2088          39 :         content->ContentCount() == 0) {
    2089          10 :       result = nullptr;
    2090             :     }
    2091             :   }
    2092             : 
    2093          39 :   return result.forget();
    2094             : }
    2095             : 
    2096             : already_AddRefed<nsStyleContext>
    2097         210 : nsStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
    2098             :                                                nsStyleContext* aParentContext)
    2099             : {
    2100         210 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2101             : 
    2102             : #ifdef DEBUG
    2103         420 :     bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
    2104         210 :                      !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag)
    2105             : #ifdef MOZ_XUL
    2106         420 :                  && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
    2107             : #endif
    2108             :       ;
    2109         210 :     NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
    2110             : #endif
    2111             : 
    2112         420 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    2113         210 :   AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker);
    2114             :   FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nullptr,
    2115         210 :             &ruleWalker);
    2116             : 
    2117         210 :   if (aPseudoTag == nsCSSAnonBoxes::pageContent) {
    2118             :     // Add any @page rules that are specified.
    2119           0 :     nsTArray<nsCSSPageRule*> rules;
    2120           0 :     nsTArray<css::ImportantStyleData*> importantRules;
    2121           0 :     AppendPageRules(rules);
    2122           0 :     for (uint32_t i = 0, i_end = rules.Length(); i != i_end; ++i) {
    2123           0 :       css::Declaration* declaration = rules[i]->Declaration();
    2124           0 :       declaration->SetImmutable();
    2125           0 :       ruleWalker.Forward(declaration);
    2126             :       css::ImportantStyleData* importantRule =
    2127           0 :         declaration->GetImportantStyleData();
    2128           0 :       if (importantRule) {
    2129           0 :         importantRules.AppendElement(importantRule);
    2130             :       }
    2131             :     }
    2132           0 :     for (uint32_t i = 0, i_end = importantRules.Length(); i != i_end; ++i) {
    2133           0 :       ruleWalker.Forward(importantRules[i]);
    2134             :     }
    2135             :   }
    2136             : 
    2137         210 :   uint32_t flags = eNoFlags;
    2138         210 :   if (nsCSSAnonBoxes::AnonBoxSkipsParentDisplayBasedStyleFixup(aPseudoTag)) {
    2139           0 :     flags |= eSkipParentDisplayBasedStyleFixup;
    2140             :   }
    2141             : 
    2142             :   return GetContext(aParentContext, ruleWalker.CurrentNode(), nullptr,
    2143             :                     aPseudoTag, CSSPseudoElementType::InheritingAnonBox,
    2144         210 :                     nullptr, flags);
    2145             : }
    2146             : 
    2147             : already_AddRefed<nsStyleContext>
    2148           0 : nsStyleSet::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
    2149             : {
    2150           0 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2151             : 
    2152             : #ifdef DEBUG
    2153           0 :     bool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
    2154           0 :                      nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag)
    2155             : #ifdef MOZ_XUL
    2156           0 :                  && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
    2157             : #endif
    2158             :       ;
    2159           0 :     NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
    2160             : #endif
    2161             : 
    2162             :   nsCSSAnonBoxes::NonInheriting type =
    2163           0 :     nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(aPseudoTag);
    2164           0 :   RefPtr<nsStyleContext>& cache = mNonInheritingStyleContexts[type];
    2165           0 :   if (cache) {
    2166           0 :     RefPtr<nsStyleContext> retval = cache;
    2167           0 :     return retval.forget();
    2168             :   }
    2169             : 
    2170           0 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    2171           0 :   AnonBoxRuleProcessorData data(PresContext(), aPseudoTag, &ruleWalker);
    2172             :   FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nullptr,
    2173           0 :             &ruleWalker);
    2174             : 
    2175           0 :   MOZ_ASSERT(aPseudoTag != nsCSSAnonBoxes::pageContent,
    2176             :              "If nsCSSAnonBoxes::pageContent ends up non-inheriting, move the "
    2177             :              "@page handling from ResolveInheritingAnonymousBoxStyle to "
    2178             :              "ResolveNonInheritingAnonymousBoxStyle");
    2179             : 
    2180             :   RefPtr<nsStyleContext> retval =
    2181           0 :     GetContext(nullptr, ruleWalker.CurrentNode(), nullptr,
    2182             :                aPseudoTag, CSSPseudoElementType::NonInheritingAnonBox,
    2183           0 :                nullptr, eNoFlags);
    2184           0 :   cache = retval;
    2185           0 :   return retval.forget();
    2186             : }
    2187             : 
    2188             : #ifdef MOZ_XUL
    2189             : already_AddRefed<nsStyleContext>
    2190           0 : nsStyleSet::ResolveXULTreePseudoStyle(Element* aParentElement,
    2191             :                                       nsICSSAnonBoxPseudo* aPseudoTag,
    2192             :                                       nsStyleContext* aParentContext,
    2193             :                                       nsICSSPseudoComparator* aComparator)
    2194             : {
    2195           0 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2196             : 
    2197           0 :   NS_ASSERTION(aPseudoTag, "must have pseudo tag");
    2198           0 :   NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
    2199             :                "Unexpected pseudo");
    2200             : 
    2201           0 :   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
    2202             :   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
    2203           0 :                                aParentElement->OwnerDoc());
    2204           0 :   InitStyleScopes(treeContext, aParentElement);
    2205             :   XULTreeRuleProcessorData data(PresContext(), aParentElement, &ruleWalker,
    2206           0 :                                 aPseudoTag, aComparator, treeContext);
    2207             :   FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, aParentElement,
    2208           0 :             &ruleWalker);
    2209             : 
    2210           0 :   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
    2211           0 :   nsRuleNode *visitedRuleNode = nullptr;
    2212             : 
    2213           0 :   if (treeContext.HaveRelevantLink()) {
    2214           0 :     treeContext.ResetForVisitedMatching();
    2215           0 :     ruleWalker.Reset();
    2216             :     FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data,
    2217           0 :               aParentElement, &ruleWalker);
    2218           0 :     visitedRuleNode = ruleWalker.CurrentNode();
    2219             :   }
    2220             : 
    2221             :   return GetContext(aParentContext, ruleNode, visitedRuleNode,
    2222             :                     // For pseudos, |data.IsLink()| being true means that
    2223             :                     // our parent node is a link.
    2224             :                     aPseudoTag, CSSPseudoElementType::XULTree,
    2225           0 :                     nullptr, eNoFlags);
    2226             : }
    2227             : #endif
    2228             : 
    2229             : bool
    2230           9 : nsStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
    2231             : {
    2232           9 :   NS_ENSURE_FALSE(mInShutdown, false);
    2233           9 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2234             : 
    2235           9 :   nsPresContext* presContext = PresContext();
    2236          54 :   for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    2237          45 :     if (gCSSSheetTypes[i] == SheetType::ScopedDoc)
    2238           9 :       continue;
    2239             :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    2240          36 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    2241          36 :     if (ruleProc && !ruleProc->AppendFontFaceRules(presContext, aArray))
    2242           0 :       return false;
    2243             :   }
    2244           9 :   return true;
    2245             : }
    2246             : 
    2247             : nsCSSKeyframesRule*
    2248           0 : nsStyleSet::KeyframesRuleForName(const nsString& aName)
    2249             : {
    2250           0 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2251           0 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2252             : 
    2253           0 :   nsPresContext* presContext = PresContext();
    2254           0 :   for (uint32_t i = ArrayLength(gCSSSheetTypes); i-- != 0; ) {
    2255           0 :     if (gCSSSheetTypes[i] == SheetType::ScopedDoc)
    2256           0 :       continue;
    2257             :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    2258           0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    2259           0 :     if (!ruleProc)
    2260           0 :       continue;
    2261             :     nsCSSKeyframesRule* result =
    2262           0 :       ruleProc->KeyframesRuleForName(presContext, aName);
    2263           0 :     if (result)
    2264           0 :       return result;
    2265             :   }
    2266           0 :   return nullptr;
    2267             : }
    2268             : 
    2269             : nsCSSCounterStyleRule*
    2270           0 : nsStyleSet::CounterStyleRuleForName(nsIAtom* aName)
    2271             : {
    2272           0 :   NS_ENSURE_FALSE(mInShutdown, nullptr);
    2273           0 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2274             : 
    2275           0 :   nsPresContext* presContext = PresContext();
    2276           0 :   for (uint32_t i = ArrayLength(gCSSSheetTypes); i-- != 0; ) {
    2277           0 :     if (gCSSSheetTypes[i] == SheetType::ScopedDoc)
    2278           0 :       continue;
    2279             :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    2280           0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    2281           0 :     if (!ruleProc)
    2282           0 :       continue;
    2283             :     nsCSSCounterStyleRule *result =
    2284           0 :       ruleProc->CounterStyleRuleForName(presContext, aName);
    2285           0 :     if (result)
    2286           0 :       return result;
    2287             :   }
    2288           0 :   return nullptr;
    2289             : }
    2290             : 
    2291             : bool
    2292           0 : nsStyleSet::AppendFontFeatureValuesRules(
    2293             :                                  nsTArray<nsCSSFontFeatureValuesRule*>& aArray)
    2294             : {
    2295           0 :   NS_ENSURE_FALSE(mInShutdown, false);
    2296           0 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2297             : 
    2298           0 :   nsPresContext* presContext = PresContext();
    2299           0 :   for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    2300             :     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
    2301           0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    2302           0 :     if (ruleProc &&
    2303           0 :         !ruleProc->AppendFontFeatureValuesRules(presContext, aArray))
    2304             :     {
    2305           0 :       return false;
    2306             :     }
    2307             :   }
    2308           0 :   return true;
    2309             : }
    2310             : 
    2311             : already_AddRefed<gfxFontFeatureValueSet>
    2312           0 : nsStyleSet::GetFontFeatureValuesLookup()
    2313             : {
    2314           0 :   if (mInitFontFeatureValuesLookup) {
    2315           0 :     mInitFontFeatureValuesLookup = false;
    2316             : 
    2317           0 :     nsTArray<nsCSSFontFeatureValuesRule*> rules;
    2318           0 :     AppendFontFeatureValuesRules(rules);
    2319             : 
    2320           0 :     mFontFeatureValuesLookup = new gfxFontFeatureValueSet();
    2321             : 
    2322           0 :     uint32_t i, numRules = rules.Length();
    2323           0 :     for (i = 0; i < numRules; i++) {
    2324           0 :       nsCSSFontFeatureValuesRule *rule = rules[i];
    2325             : 
    2326           0 :       const nsTArray<FontFamilyName>& familyList = rule->GetFamilyList().GetFontlist();
    2327             :       const nsTArray<gfxFontFeatureValueSet::FeatureValues>&
    2328           0 :         featureValues = rule->GetFeatureValues();
    2329             : 
    2330             :       // for each family
    2331             :       size_t f, numFam;
    2332             : 
    2333           0 :       numFam = familyList.Length();
    2334           0 :       for (f = 0; f < numFam; f++) {
    2335           0 :         mFontFeatureValuesLookup->AddFontFeatureValues(familyList[f].mName,
    2336           0 :                                                        featureValues);
    2337             :       }
    2338             :     }
    2339             :   }
    2340             : 
    2341           0 :   RefPtr<gfxFontFeatureValueSet> lookup = mFontFeatureValuesLookup;
    2342           0 :   return lookup.forget();
    2343             : }
    2344             : 
    2345             : bool
    2346           0 : nsStyleSet::AppendPageRules(nsTArray<nsCSSPageRule*>& aArray)
    2347             : {
    2348           0 :   NS_ENSURE_FALSE(mInShutdown, false);
    2349           0 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2350             : 
    2351           0 :   nsPresContext* presContext = PresContext();
    2352           0 :   for (uint32_t i = 0; i < ArrayLength(gCSSSheetTypes); ++i) {
    2353           0 :     if (gCSSSheetTypes[i] == SheetType::ScopedDoc)
    2354           0 :       continue;
    2355             :     nsCSSRuleProcessor* ruleProc = static_cast<nsCSSRuleProcessor*>
    2356           0 :                                     (mRuleProcessors[gCSSSheetTypes[i]].get());
    2357           0 :     if (ruleProc && !ruleProc->AppendPageRules(presContext, aArray))
    2358           0 :       return false;
    2359             :   }
    2360           0 :   return true;
    2361             : }
    2362             : 
    2363             : void
    2364           4 : nsStyleSet::BeginShutdown()
    2365             : {
    2366           4 :   mInShutdown = 1;
    2367           4 : }
    2368             : 
    2369             : void
    2370           4 : nsStyleSet::Shutdown()
    2371             : {
    2372             :   // Make sure we drop our cached style contexts before the presshell arena
    2373             :   // starts going away.
    2374           4 :   ClearNonInheritingStyleContexts();
    2375           4 :   mRuleTree = nullptr;
    2376           4 :   GCRuleTrees();
    2377           4 :   MOZ_ASSERT(mUnusedRuleNodeList.isEmpty());
    2378           4 :   MOZ_ASSERT(mUnusedRuleNodeCount == 0);
    2379           4 : }
    2380             : 
    2381             : void
    2382          48 : nsStyleSet::RecordStyleSheetChange(CSSStyleSheet* aStyleSheet,
    2383             :                                    StyleSheet::ChangeType)
    2384             : {
    2385          48 :   MOZ_ASSERT(mBatching != 0, "Should be in an update");
    2386             : 
    2387          48 :   if (mStylesHaveChanged) {
    2388           9 :     return;
    2389             :   }
    2390             : 
    2391          39 :   if (Element* scopeElement = aStyleSheet->GetScopeElement()) {
    2392           0 :     mChangedScopeStyleRoots.AppendElement(scopeElement);
    2393           0 :     return;
    2394             :   }
    2395             : 
    2396          39 :   mStylesHaveChanged = true;
    2397             :   // If we need to restyle everything, no need to restyle individual
    2398             :   // scoped style roots.
    2399          39 :   mChangedScopeStyleRoots.Clear();
    2400             : }
    2401             : 
    2402             : void
    2403           0 : nsStyleSet::RecordShadowStyleChange(ShadowRoot* aShadowRoot)
    2404             : {
    2405           0 :   if (mStylesHaveChanged) {
    2406           0 :     return;
    2407             :   }
    2408             : 
    2409           0 :   mChangedScopeStyleRoots.AppendElement(aShadowRoot->GetHost()->AsElement());
    2410             : }
    2411             : 
    2412             : void
    2413          23 : nsStyleSet::InvalidateStyleForCSSRuleChanges()
    2414             : {
    2415          23 :   MOZ_ASSERT(!mStylesHaveChanged || mChangedScopeStyleRoots.IsEmpty());
    2416             : 
    2417          46 :   AutoTArray<RefPtr<mozilla::dom::Element>, 1> scopeRoots;
    2418          23 :   mChangedScopeStyleRoots.SwapElements(scopeRoots);
    2419          23 :   mStylesHaveChanged = false;
    2420             : 
    2421          23 :   nsPresContext* presContext = PresContext();
    2422          23 :   RestyleManager* restyleManager = presContext->RestyleManager()->AsGecko();
    2423          23 :   Element* root = presContext->Document()->GetRootElement();
    2424          23 :   if (!root) {
    2425             :     // No content to restyle
    2426           0 :     return;
    2427             :   }
    2428             : 
    2429          23 :   if (scopeRoots.IsEmpty()) {
    2430             :     // If scopeRoots is empty, we know that mStylesHaveChanged was true at
    2431             :     // the beginning of this function, and that we need to restyle the whole
    2432             :     // document.
    2433             :     restyleManager->PostRestyleEvent(root,
    2434             :                                      eRestyle_Subtree,
    2435          23 :                                      nsChangeHint(0));
    2436             :   } else {
    2437           0 :     for (Element* scopeRoot : scopeRoots) {
    2438             :       restyleManager->PostRestyleEvent(scopeRoot,
    2439             :                                        eRestyle_Subtree,
    2440           0 :                                        nsChangeHint(0));
    2441             :     }
    2442             :   }
    2443             : }
    2444             : 
    2445             : void
    2446           6 : nsStyleSet::GCRuleTrees()
    2447             : {
    2448           6 :   MOZ_ASSERT(!mInReconstruct);
    2449           6 :   MOZ_ASSERT(!mInGC);
    2450           6 :   mInGC = true;
    2451             : 
    2452        1898 :   while (!mUnusedRuleNodeList.isEmpty()) {
    2453         946 :     nsRuleNode* node = mUnusedRuleNodeList.popFirst();
    2454             : #ifdef DEBUG
    2455         946 :     if (node == mOldRootNode) {
    2456             :       // Flag that we've GCed the old root, if any.
    2457           2 :       mOldRootNode = nullptr;
    2458             :     }
    2459             : #endif
    2460         946 :     node->Destroy();
    2461             :   }
    2462             : 
    2463             : #ifdef DEBUG
    2464           6 :   NS_ASSERTION(!mOldRootNode, "Should have GCed old root node");
    2465           6 :   mOldRootNode = nullptr;
    2466             : #endif
    2467           6 :   mUnusedRuleNodeCount = 0;
    2468           6 :   mInGC = false;
    2469           6 : }
    2470             : 
    2471             : already_AddRefed<nsStyleContext>
    2472         303 : nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
    2473             :                                  nsStyleContext* aNewParentContext,
    2474             :                                  Element* aElement)
    2475             : {
    2476         303 :   MOZ_ASSERT(aStyleContext, "aStyleContext must not be null");
    2477             : 
    2478             :   // This short-circuit is OK because we don't call TryInitatingTransition
    2479             :   // during style reresolution if the style context pointer hasn't changed.
    2480         303 :   if (aStyleContext->GetParent() == aNewParentContext) {
    2481          26 :     RefPtr<nsStyleContext> ret = aStyleContext;
    2482          13 :     return ret.forget();
    2483             :   }
    2484             : 
    2485         290 :   nsIAtom* pseudoTag = aStyleContext->GetPseudo();
    2486         290 :   CSSPseudoElementType pseudoType = aStyleContext->GetPseudoType();
    2487         290 :   nsRuleNode* ruleNode = aStyleContext->RuleNode();
    2488             : 
    2489         290 :   MOZ_ASSERT(PresContext()->RestyleManager()->IsGecko(),
    2490             :              "stylo: the style set and restyle manager must have the same "
    2491             :              "StyleBackendType");
    2492         290 :   NS_ASSERTION(!PresContext()->RestyleManager()->AsGecko()->SkipAnimationRules(),
    2493             :                "we no longer handle SkipAnimationRules()");
    2494             : 
    2495         290 :   nsRuleNode* visitedRuleNode = nullptr;
    2496         290 :   nsStyleContext* visitedContext = aStyleContext->GetStyleIfVisited();
    2497             :   // Reparenting a style context just changes where we inherit from,
    2498             :   // not what rules we match or what our DOM looks like.  In
    2499             :   // particular, it doesn't change whether this is a style context for
    2500             :   // a link.
    2501         290 :   if (visitedContext) {
    2502           0 :     visitedRuleNode = visitedContext->RuleNode();
    2503             :   }
    2504             : 
    2505         290 :   uint32_t flags = eNoFlags;
    2506         290 :   if (aStyleContext->IsLinkContext()) {
    2507           0 :     flags |= eIsLink;
    2508             : 
    2509             :     // GetContext handles propagating RelevantLinkVisited state from the
    2510             :     // parent in non-link cases; all we need to pass in is if this link
    2511             :     // is visited.
    2512           0 :     if (aStyleContext->RelevantLinkVisited()) {
    2513           0 :       flags |= eIsVisitedLink;
    2514             :     }
    2515             :   }
    2516             : 
    2517         290 :   if (pseudoType == CSSPseudoElementType::NotPseudo ||
    2518          19 :       pseudoType == CSSPseudoElementType::before ||
    2519             :       pseudoType == CSSPseudoElementType::after) {
    2520         274 :     flags |= eDoAnimation;
    2521             :   }
    2522             : 
    2523         510 :   if ((aElement && aElement->IsRootOfAnonymousSubtree()) ||
    2524         220 :       SkipsParentDisplayBasedStyleFixup(aStyleContext)) {
    2525             :     // For anonymous subtree roots, don't tweak "display" value based on whether
    2526             :     // or not the parent is styled as a flex/grid container. (If the parent
    2527             :     // has anonymous-subtree kids, then we know it's not actually going to get
    2528             :     // a flex/grid container frame, anyway.)  Same for certain anonymous boxes
    2529             :     // and most pseudos.
    2530          70 :     flags |= eSkipParentDisplayBasedStyleFixup;
    2531             :   }
    2532             : 
    2533             :   return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
    2534             :                     pseudoTag, pseudoType,
    2535         290 :                     aElement, flags);
    2536             : }
    2537             : 
    2538             : struct MOZ_STACK_CLASS StatefulData : public StateRuleProcessorData {
    2539          53 :   StatefulData(nsPresContext* aPresContext, Element* aElement,
    2540             :                EventStates aStateMask, TreeMatchContext& aTreeMatchContext)
    2541          53 :     : StateRuleProcessorData(aPresContext, aElement, aStateMask,
    2542             :                              aTreeMatchContext),
    2543          53 :       mHint(nsRestyleHint(0))
    2544          53 :   {}
    2545             :   nsRestyleHint   mHint;
    2546             : };
    2547             : 
    2548             : struct MOZ_STACK_CLASS StatefulPseudoElementData : public PseudoElementStateRuleProcessorData {
    2549           0 :   StatefulPseudoElementData(nsPresContext* aPresContext, Element* aElement,
    2550             :                EventStates aStateMask, CSSPseudoElementType aPseudoType,
    2551             :                TreeMatchContext& aTreeMatchContext, Element* aPseudoElement)
    2552           0 :     : PseudoElementStateRuleProcessorData(aPresContext, aElement, aStateMask,
    2553             :                                           aPseudoType, aTreeMatchContext,
    2554             :                                           aPseudoElement),
    2555           0 :       mHint(nsRestyleHint(0))
    2556           0 :   {}
    2557             :   nsRestyleHint   mHint;
    2558             : };
    2559             : 
    2560          35 : static bool SheetHasDocumentStateStyle(nsIStyleRuleProcessor* aProcessor,
    2561             :                                          void *aData)
    2562             : {
    2563          35 :   StatefulData* data = (StatefulData*)aData;
    2564          35 :   if (aProcessor->HasDocumentStateDependentStyle(data)) {
    2565           1 :     data->mHint = eRestyle_Self;
    2566           1 :     return false; // don't continue
    2567             :   }
    2568          34 :   return true; // continue
    2569             : }
    2570             : 
    2571             : // Test if style is dependent on a document state.
    2572             : bool
    2573           2 : nsStyleSet::HasDocumentStateDependentStyle(nsIContent*    aContent,
    2574             :                                            EventStates    aStateMask)
    2575             : {
    2576           2 :   if (!aContent || !aContent->IsElement())
    2577           0 :     return false;
    2578             : 
    2579             :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    2580           4 :                                aContent->OwnerDoc());
    2581           2 :   InitStyleScopes(treeContext, aContent->AsElement());
    2582             :   StatefulData data(PresContext(), aContent->AsElement(), aStateMask,
    2583           2 :                     treeContext);
    2584           2 :   WalkRuleProcessors(SheetHasDocumentStateStyle, &data, true);
    2585           2 :   return data.mHint != 0;
    2586             : }
    2587             : 
    2588         341 : static bool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor,
    2589             :                                     void *aData)
    2590             : {
    2591         341 :   StatefulData* data = (StatefulData*)aData;
    2592         341 :   nsRestyleHint hint = aProcessor->HasStateDependentStyle(data);
    2593         341 :   data->mHint = nsRestyleHint(data->mHint | hint);
    2594         341 :   return true; // continue
    2595             : }
    2596             : 
    2597           0 : static bool SheetHasStatefulPseudoElementStyle(nsIStyleRuleProcessor* aProcessor,
    2598             :                                                void *aData)
    2599             : {
    2600           0 :   StatefulPseudoElementData* data = (StatefulPseudoElementData*)aData;
    2601           0 :   nsRestyleHint hint = aProcessor->HasStateDependentStyle(data);
    2602           0 :   data->mHint = nsRestyleHint(data->mHint | hint);
    2603           0 :   return true; // continue
    2604             : }
    2605             : 
    2606             : // Test if style is dependent on content state
    2607             : nsRestyleHint
    2608          51 : nsStyleSet::HasStateDependentStyle(Element*             aElement,
    2609             :                                    EventStates          aStateMask)
    2610             : {
    2611             :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    2612         102 :                                aElement->OwnerDoc());
    2613          51 :   InitStyleScopes(treeContext, aElement);
    2614          51 :   StatefulData data(PresContext(), aElement, aStateMask, treeContext);
    2615          51 :   WalkRuleProcessors(SheetHasStatefulStyle, &data, false);
    2616         102 :   return data.mHint;
    2617             : }
    2618             : 
    2619             : nsRestyleHint
    2620           0 : nsStyleSet::HasStateDependentStyle(Element* aElement,
    2621             :                                    CSSPseudoElementType aPseudoType,
    2622             :                                    Element* aPseudoElement,
    2623             :                                    EventStates aStateMask)
    2624             : {
    2625             :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    2626           0 :                                aElement->OwnerDoc());
    2627           0 :   InitStyleScopes(treeContext, aElement);
    2628             :   StatefulPseudoElementData data(PresContext(), aElement, aStateMask,
    2629           0 :                                  aPseudoType, treeContext, aPseudoElement);
    2630           0 :   WalkRuleProcessors(SheetHasStatefulPseudoElementStyle, &data, false);
    2631           0 :   return data.mHint;
    2632             : }
    2633             : 
    2634         648 : struct MOZ_STACK_CLASS AttributeData : public AttributeRuleProcessorData {
    2635         648 :   AttributeData(nsPresContext* aPresContext, Element* aElement,
    2636             :                 int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType,
    2637             :                 bool aAttrHasChanged, const nsAttrValue* aOtherValue,
    2638             :                 TreeMatchContext& aTreeMatchContext)
    2639         648 :     : AttributeRuleProcessorData(aPresContext, aElement, aNameSpaceID,
    2640             :                                  aAttribute, aModType, aAttrHasChanged,
    2641             :                                  aOtherValue, aTreeMatchContext),
    2642         648 :       mHint(nsRestyleHint(0))
    2643         648 :   {}
    2644             :   nsRestyleHint mHint;
    2645             :   RestyleHintData mHintData;
    2646             : };
    2647             : 
    2648             : static bool
    2649        4117 : SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)
    2650             : {
    2651        4117 :   AttributeData* data = (AttributeData*)aData;
    2652             :   nsRestyleHint hint =
    2653        4117 :     aProcessor->HasAttributeDependentStyle(data, data->mHintData);
    2654        4117 :   data->mHint = nsRestyleHint(data->mHint | hint);
    2655        4117 :   return true; // continue
    2656             : }
    2657             : 
    2658             : // Test if style is dependent on content state
    2659             : nsRestyleHint
    2660         648 : nsStyleSet::HasAttributeDependentStyle(Element*       aElement,
    2661             :                                        int32_t        aNameSpaceID,
    2662             :                                        nsIAtom*       aAttribute,
    2663             :                                        int32_t        aModType,
    2664             :                                        bool           aAttrHasChanged,
    2665             :                                        const nsAttrValue* aOtherValue,
    2666             :                                        mozilla::RestyleHintData&
    2667             :                                          aRestyleHintDataResult)
    2668             : {
    2669             :   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
    2670        1296 :                                aElement->OwnerDoc());
    2671         648 :   InitStyleScopes(treeContext, aElement);
    2672             :   AttributeData data(PresContext(), aElement, aNameSpaceID, aAttribute,
    2673        1296 :                      aModType, aAttrHasChanged, aOtherValue, treeContext);
    2674         648 :   WalkRuleProcessors(SheetHasAttributeStyle, &data, false);
    2675         648 :   if (!(data.mHint & eRestyle_Subtree)) {
    2676             :     // No point keeping the list of selectors around if we are going to
    2677             :     // restyle the whole subtree unconditionally.
    2678         636 :     aRestyleHintDataResult = Move(data.mHintData);
    2679             :   }
    2680        1296 :   return data.mHint;
    2681             : }
    2682             : 
    2683             : bool
    2684          21 : nsStyleSet::MediumFeaturesChanged()
    2685             : {
    2686          21 :   NS_ASSERTION(mBatching == 0, "rule processors out of date");
    2687             : 
    2688             :   // We can't use WalkRuleProcessors without a content node.
    2689          21 :   nsPresContext* presContext = PresContext();
    2690          21 :   bool stylesChanged = false;
    2691         210 :   for (nsIStyleRuleProcessor* processor : mRuleProcessors) {
    2692         189 :     if (!processor) {
    2693          77 :       continue;
    2694             :     }
    2695         112 :     bool thisChanged = processor->MediumFeaturesChanged(presContext);
    2696         112 :     stylesChanged = stylesChanged || thisChanged;
    2697             :   }
    2698          21 :   for (nsIStyleRuleProcessor* processor : mScopedDocSheetRuleProcessors) {
    2699           0 :     bool thisChanged = processor->MediumFeaturesChanged(presContext);
    2700           0 :     stylesChanged = stylesChanged || thisChanged;
    2701             :   }
    2702             : 
    2703          21 :   if (mBindingManager) {
    2704          21 :     bool thisChanged = false;
    2705          21 :     mBindingManager->MediumFeaturesChanged(presContext, &thisChanged);
    2706          21 :     stylesChanged = stylesChanged || thisChanged;
    2707             :   }
    2708             : 
    2709          21 :   return stylesChanged;
    2710             : }
    2711             : 
    2712             : bool
    2713           0 : nsStyleSet::EnsureUniqueInnerOnCSSSheets()
    2714             : {
    2715           0 :   AutoTArray<StyleSheet*, 32> queue;
    2716           0 :   for (SheetType type : gCSSSheetTypes) {
    2717           0 :     for (StyleSheet* sheet : mSheets[type]) {
    2718           0 :       queue.AppendElement(sheet);
    2719             :     }
    2720             :   }
    2721             : 
    2722           0 :   if (mBindingManager) {
    2723           0 :     AutoTArray<StyleSheet*, 32> sheets;
    2724             :     // XXXheycam stylo: AppendAllSheets will need to be able to return either
    2725             :     // CSSStyleSheets or ServoStyleSheets, on request (and then here requesting
    2726             :     // CSSStyleSheets).
    2727           0 :     mBindingManager->AppendAllSheets(sheets);
    2728           0 :     for (StyleSheet* sheet : sheets) {
    2729           0 :       MOZ_ASSERT(sheet->IsGecko(), "stylo: AppendAllSheets shouldn't give us "
    2730             :                                    "ServoStyleSheets yet");
    2731           0 :       queue.AppendElement(sheet->AsGecko());
    2732             :     }
    2733             :   }
    2734             : 
    2735           0 :   while (!queue.IsEmpty()) {
    2736           0 :     uint32_t idx = queue.Length() - 1;
    2737           0 :     StyleSheet* sheet = queue[idx];
    2738           0 :     queue.RemoveElementAt(idx);
    2739             : 
    2740           0 :     sheet->EnsureUniqueInner();
    2741             : 
    2742             :     // Enqueue all the sheet's children.
    2743           0 :     sheet->AppendAllChildSheets(queue);
    2744             :   }
    2745             : 
    2746           0 :   bool res = mNeedsRestyleAfterEnsureUniqueInner;
    2747           0 :   mNeedsRestyleAfterEnsureUniqueInner = false;
    2748           0 :   return res;
    2749             : }
    2750             : 
    2751             : nsIStyleRule*
    2752           0 : nsStyleSet::InitialStyleRule()
    2753             : {
    2754           0 :   if (!mInitialStyleRule) {
    2755           0 :     mInitialStyleRule = new nsInitialStyleRule;
    2756             :   }
    2757           0 :   return mInitialStyleRule;
    2758             : }
    2759             : 
    2760             : bool
    2761           0 : nsStyleSet::HasRuleProcessorUsedByMultipleStyleSets(SheetType aSheetType)
    2762             : {
    2763           0 :   MOZ_ASSERT(size_t(aSheetType) < ArrayLength(mRuleProcessors));
    2764           0 :   if (!IsCSSSheetType(aSheetType) || !mRuleProcessors[aSheetType]) {
    2765           0 :     return false;
    2766             :   }
    2767             :   nsCSSRuleProcessor* rp =
    2768           0 :     static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aSheetType].get());
    2769           0 :   return rp->IsUsedByMultipleStyleSets();
    2770             : }
    2771             : 
    2772             : void
    2773          48 : nsStyleSet::ClearSelectors()
    2774             : {
    2775             :   // We might be called before we've done our first rule tree construction.
    2776          48 :   if (!mRuleTree) {
    2777           0 :     return;
    2778             :   }
    2779          48 :   MOZ_ASSERT(PresContext()->RestyleManager()->IsGecko(),
    2780             :              "stylo: the style set and restyle manager must have the same "
    2781             :              "StyleBackendType");
    2782          48 :   PresContext()->RestyleManager()->AsGecko()->ClearSelectors();
    2783             : }
    2784             : 
    2785             : void
    2786           6 : nsStyleSet::ClearNonInheritingStyleContexts()
    2787             : {
    2788          36 :   for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
    2789          30 :     ptr = nullptr;
    2790             :   }
    2791           6 : }

Generated by: LCOV version 1.13