LCOV - code coverage report
Current view: top level - layout/style - ServoStyleSet.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 565 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 76 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/ServoStyleSet.h"
       8             : 
       9             : #include "gfxPlatformFontList.h"
      10             : #include "mozilla/AutoRestyleTimelineMarker.h"
      11             : #include "mozilla/DocumentStyleRootIterator.h"
      12             : #include "mozilla/ServoBindings.h"
      13             : #include "mozilla/ServoRestyleManager.h"
      14             : #include "mozilla/ServoStyleRuleMap.h"
      15             : #include "mozilla/css/Loader.h"
      16             : #include "mozilla/dom/AnonymousContent.h"
      17             : #include "mozilla/dom/ChildIterator.h"
      18             : #include "mozilla/dom/FontFaceSet.h"
      19             : #include "mozilla/dom/Element.h"
      20             : #include "mozilla/dom/ElementInlines.h"
      21             : #include "mozilla/RestyleManagerInlines.h"
      22             : #include "nsCSSAnonBoxes.h"
      23             : #include "nsCSSFrameConstructor.h"
      24             : #include "nsCSSPseudoElements.h"
      25             : #include "nsCSSRuleProcessor.h"
      26             : #include "nsDeviceContext.h"
      27             : #include "nsHTMLStyleSheet.h"
      28             : #include "nsIAnonymousContentCreator.h"
      29             : #include "nsIDocumentInlines.h"
      30             : #include "nsPrintfCString.h"
      31             : #include "nsSMILAnimationController.h"
      32             : #include "nsStyleContext.h"
      33             : #include "nsStyleSet.h"
      34             : #include "gfxUserFontSet.h"
      35             : 
      36             : using namespace mozilla;
      37             : using namespace mozilla::dom;
      38             : 
      39           0 : ServoStyleSet::ServoStyleSet()
      40             :   : mPresContext(nullptr)
      41             :   , mAuthorStyleDisabled(false)
      42             :   , mStylistState(StylistState::NotDirty)
      43             :   , mUserFontSetUpdateGeneration(0)
      44             :   , mUserFontCacheUpdateGeneration(0)
      45           0 :   , mNeedsRestyleAfterEnsureUniqueInner(false)
      46             : {
      47           0 : }
      48             : 
      49           0 : ServoStyleSet::~ServoStyleSet()
      50             : {
      51           0 :   for (auto& sheetArray : mSheets) {
      52           0 :     for (auto& sheet : sheetArray) {
      53           0 :       sheet->DropStyleSet(this);
      54             :     }
      55             :   }
      56           0 : }
      57             : 
      58             : void
      59           0 : ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
      60             : {
      61           0 :   mPresContext = aPresContext;
      62           0 :   mRawSet.reset(Servo_StyleSet_Init(aPresContext));
      63           0 :   mBindingManager = aBindingManager;
      64             : 
      65           0 :   mPresContext->DeviceContext()->InitFontCache();
      66             : 
      67             :   // Now that we have an mRawSet, go ahead and notify about whatever stylesheets
      68             :   // we have so far.
      69           0 :   for (auto& sheetArray : mSheets) {
      70           0 :     for (auto& sheet : sheetArray) {
      71             :       // There's no guarantee this will create a list on the servo side whose
      72             :       // ordering matches the list that would have been created had all those
      73             :       // sheets been appended/prepended/etc after we had mRawSet. That's okay
      74             :       // because Servo only needs to maintain relative ordering within a sheet
      75             :       // type, which this preserves.
      76             : 
      77           0 :       MOZ_ASSERT(sheet->RawContents(),
      78             :                  "We should only append non-null raw sheets.");
      79           0 :       Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet);
      80             :     }
      81             :   }
      82             : 
      83             :   // No need to Servo_StyleSet_FlushStyleSheets because we just created the
      84             :   // mRawSet, so there was nothing to flush.
      85           0 : }
      86             : 
      87             : void
      88           0 : ServoStyleSet::BeginShutdown()
      89             : {
      90           0 :   nsIDocument* doc = mPresContext->Document();
      91             : 
      92             :   // Remove the style rule map from document's observer and drop it.
      93           0 :   if (mStyleRuleMap) {
      94           0 :     doc->RemoveObserver(mStyleRuleMap);
      95           0 :     doc->CSSLoader()->RemoveObserver(mStyleRuleMap);
      96           0 :     mStyleRuleMap = nullptr;
      97             :   }
      98           0 : }
      99             : 
     100             : void
     101           0 : ServoStyleSet::Shutdown()
     102             : {
     103             :   // Make sure we drop our cached style contexts before the presshell arena
     104             :   // starts going away.
     105           0 :   ClearNonInheritingStyleContexts();
     106           0 :   mRawSet = nullptr;
     107           0 : }
     108             : 
     109             : void
     110           0 : ServoStyleSet::InvalidateStyleForCSSRuleChanges()
     111             : {
     112           0 :   MOZ_ASSERT(StylistNeedsUpdate());
     113           0 :   mPresContext->RestyleManager()->AsServo()->PostRestyleEventForCSSRuleChanges();
     114           0 : }
     115             : 
     116             : bool
     117           0 : ServoStyleSet::MediumFeaturesChanged() const
     118             : {
     119           0 :   return Servo_StyleSet_MediumFeaturesChanged(mRawSet.get());
     120             : }
     121             : 
     122             : size_t
     123           0 : ServoStyleSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     124             : {
     125           0 :   size_t n = aMallocSizeOf(this);
     126             : 
     127           0 :   if (mStyleRuleMap) {
     128           0 :     n += mStyleRuleMap->SizeOfIncludingThis(aMallocSizeOf);
     129             :   }
     130             : 
     131             :   // Measurement of the following members may be added later if DMD finds it is
     132             :   // worthwhile:
     133             :   // - mRawSet
     134             :   // - mSheets
     135             :   // - mNonInheritingStyleContexts
     136             :   //
     137             :   // The following members are not measured:
     138             :   // - mPresContext, because it a non-owning pointer
     139             : 
     140           0 :   return n;
     141             : }
     142             : 
     143             : bool
     144           0 : ServoStyleSet::GetAuthorStyleDisabled() const
     145             : {
     146           0 :   return mAuthorStyleDisabled;
     147             : }
     148             : 
     149             : nsresult
     150           0 : ServoStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled)
     151             : {
     152           0 :   if (mAuthorStyleDisabled == aStyleDisabled) {
     153           0 :     return NS_OK;
     154             :   }
     155             : 
     156           0 :   mAuthorStyleDisabled = aStyleDisabled;
     157           0 :   ForceAllStyleDirty();
     158             : 
     159           0 :   return NS_OK;
     160             : }
     161             : 
     162             : void
     163           0 : ServoStyleSet::BeginUpdate()
     164             : {
     165           0 : }
     166             : 
     167             : nsresult
     168           0 : ServoStyleSet::EndUpdate()
     169             : {
     170           0 :   return NS_OK;
     171             : }
     172             : 
     173             : already_AddRefed<nsStyleContext>
     174           0 : ServoStyleSet::ResolveStyleFor(Element* aElement,
     175             :                                nsStyleContext* aParentContext,
     176             :                                LazyComputeBehavior aMayCompute)
     177             : {
     178           0 :   return GetContext(aElement, aParentContext, nullptr,
     179           0 :                     CSSPseudoElementType::NotPseudo, aMayCompute);
     180             : }
     181             : 
     182             : already_AddRefed<ServoStyleContext>
     183           0 : ServoStyleSet::GetContext(nsIContent* aContent,
     184             :                           nsStyleContext* aParentContext,
     185             :                           nsIAtom* aPseudoTag,
     186             :                           CSSPseudoElementType aPseudoType,
     187             :                           LazyComputeBehavior aMayCompute)
     188             : {
     189           0 :   MOZ_ASSERT(aContent->IsElement());
     190           0 :   Element* element = aContent->AsElement();
     191             : 
     192           0 :   RefPtr<ServoComputedValues> computedValues;
     193           0 :   if (aMayCompute == LazyComputeBehavior::Allow) {
     194           0 :     PreTraverseSync();
     195             :     computedValues =
     196           0 :       ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo);
     197             :   } else {
     198           0 :     computedValues = ResolveServoStyle(element);
     199             :   }
     200             : 
     201           0 :   MOZ_ASSERT(computedValues);
     202           0 :   return GetContext(computedValues.forget(), aParentContext, aPseudoTag, aPseudoType,
     203           0 :                     element);
     204             : }
     205             : 
     206             : already_AddRefed<ServoStyleContext>
     207           0 : ServoStyleSet::GetContext(already_AddRefed<ServoComputedValues> aComputedValues,
     208             :                           nsStyleContext* aParentContext,
     209             :                           nsIAtom* aPseudoTag,
     210             :                           CSSPseudoElementType aPseudoType,
     211             :                           Element* aElementForAnimation)
     212             : {
     213           0 :   bool isLink = false;
     214           0 :   bool isVisitedLink = false;
     215             :   // If we need visited styles for callers where `aElementForAnimation` is null,
     216             :   // we can precompute these and pass them as flags, similar to nsStyleSet.cpp.
     217           0 :   if (aElementForAnimation) {
     218           0 :     isLink = nsCSSRuleProcessor::IsLink(aElementForAnimation);
     219           0 :     isVisitedLink = nsCSSRuleProcessor::GetContentState(aElementForAnimation)
     220           0 :                                        .HasState(NS_EVENT_STATE_VISITED);
     221             :   }
     222             : 
     223           0 :   RefPtr<ServoComputedValues> computedValues = Move(aComputedValues);
     224             :   RefPtr<ServoComputedValues> visitedComputedValues =
     225           0 :     Servo_ComputedValues_GetVisitedStyle(computedValues).Consume();
     226             : 
     227             :   // If `visitedComputedValues` is non-null, then there was a relevant link and
     228             :   // visited styles were computed.  This corresponds to the cases where Gecko's
     229             :   // style system produces `aVisitedRuleNode`.
     230             :   // Set up `parentIfVisited` depending on whether our parent context has a
     231             :   // a visited style.  If it doesn't but we do have visited styles, use the
     232             :   // regular parent context for visited.
     233             :   nsStyleContext *parentIfVisited =
     234           0 :     aParentContext ? aParentContext->GetStyleIfVisited() : nullptr;
     235           0 :   if (!parentIfVisited) {
     236           0 :     if (visitedComputedValues) {
     237           0 :       parentIfVisited = aParentContext;
     238             :     }
     239             :   }
     240             : 
     241             :   // The true visited state of the relevant link is used to decided whether
     242             :   // visited styles should be consulted for all visited dependent properties.
     243           0 :   bool relevantLinkVisited = isLink ? isVisitedLink :
     244           0 :     (aParentContext && aParentContext->RelevantLinkVisited());
     245             : 
     246             :   RefPtr<ServoStyleContext> result =
     247           0 :     ServoStyleContext::Create(aParentContext, mPresContext, aPseudoTag, aPseudoType,
     248           0 :                               computedValues.forget());
     249             : 
     250           0 :   if (visitedComputedValues) {
     251             :     RefPtr<ServoStyleContext> resultIfVisited =
     252           0 :       ServoStyleContext::Create(parentIfVisited, mPresContext, aPseudoTag, aPseudoType,
     253           0 :                                 visitedComputedValues.forget());
     254           0 :     resultIfVisited->SetIsStyleIfVisited();
     255           0 :     result->SetStyleIfVisited(resultIfVisited.forget());
     256             : 
     257           0 :     if (relevantLinkVisited) {
     258           0 :       result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
     259             :     }
     260             :   }
     261             : 
     262             :   // Set the body color on the pres context. See nsStyleSet::GetContext
     263           0 :   if (aElementForAnimation &&
     264           0 :       aElementForAnimation->IsHTMLElement(nsGkAtoms::body) &&
     265           0 :       aPseudoType == CSSPseudoElementType::NotPseudo &&
     266           0 :       mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
     267           0 :     nsIDocument* doc = aElementForAnimation->GetUncomposedDoc();
     268           0 :     if (doc && doc->GetBodyElement() == aElementForAnimation) {
     269             :       // Update the prescontext's body color
     270           0 :       mPresContext->SetBodyTextColor(result->StyleColor()->mColor);
     271             :     }
     272             :   }
     273           0 :   return result.forget();
     274             : }
     275             : 
     276             : const ServoElementSnapshotTable&
     277           0 : ServoStyleSet::Snapshots()
     278             : {
     279           0 :   return mPresContext->RestyleManager()->AsServo()->Snapshots();
     280             : }
     281             : 
     282             : void
     283           0 : ServoStyleSet::ResolveMappedAttrDeclarationBlocks()
     284             : {
     285           0 :   if (nsHTMLStyleSheet* sheet = mPresContext->Document()->GetAttributeStyleSheet()) {
     286           0 :     sheet->CalculateMappedServoDeclarations(mPresContext);
     287             :   }
     288             : 
     289           0 :   mPresContext->Document()->ResolveScheduledSVGPresAttrs();
     290           0 : }
     291             : 
     292             : void
     293           0 : ServoStyleSet::PreTraverseSync()
     294             : {
     295           0 :   ResolveMappedAttrDeclarationBlocks();
     296             : 
     297           0 :   nsCSSRuleProcessor::InitSystemMetrics();
     298             : 
     299             :   // This is lazily computed and pseudo matching needs to access
     300             :   // it so force computation early.
     301           0 :   mPresContext->Document()->GetDocumentState();
     302             : 
     303           0 :   if (gfxUserFontSet* userFontSet = mPresContext->Document()->GetUserFontSet()) {
     304             :     // Ensure that the @font-face data is not stale
     305           0 :     uint64_t generation = userFontSet->GetGeneration();
     306           0 :     if (generation != mUserFontSetUpdateGeneration) {
     307           0 :       mPresContext->DeviceContext()->UpdateFontCacheUserFonts(userFontSet);
     308           0 :       mUserFontSetUpdateGeneration = generation;
     309             :     }
     310             : 
     311             :     // Ensure that the FontFaceSet's cached document principal is up to date.
     312             :     FontFaceSet* fontFaceSet =
     313           0 :       static_cast<FontFaceSet::UserFontSet*>(userFontSet)->GetFontFaceSet();
     314           0 :     fontFaceSet->UpdateStandardFontLoadPrincipal();
     315           0 :     bool principalChanged = fontFaceSet->HasStandardFontLoadPrincipalChanged();
     316             : 
     317             :     // Ensure that the user font cache holds up-to-date data on whether
     318             :     // our font set is allowed to re-use fonts from the cache.
     319           0 :     uint32_t cacheGeneration = gfxUserFontSet::UserFontCache::Generation();
     320           0 :     if (principalChanged) {
     321           0 :       gfxUserFontSet::UserFontCache::ClearAllowedFontSets(userFontSet);
     322             :     }
     323           0 :     if (cacheGeneration != mUserFontCacheUpdateGeneration || principalChanged) {
     324           0 :       gfxUserFontSet::UserFontCache::UpdateAllowedFontSets(userFontSet);
     325           0 :       mUserFontCacheUpdateGeneration = cacheGeneration;
     326             :     }
     327             :   }
     328             : 
     329           0 :   UpdateStylistIfNeeded();
     330           0 :   mPresContext->CacheAllLangs();
     331           0 : }
     332             : 
     333             : void
     334           0 : ServoStyleSet::PreTraverse(Element* aRoot,
     335             :                            EffectCompositor::AnimationRestyleType aRestyleType)
     336             : {
     337           0 :   PreTraverseSync();
     338             : 
     339             :   // Process animation stuff that we should avoid doing during the parallel
     340             :   // traversal.
     341             :   nsSMILAnimationController* smilController =
     342           0 :     mPresContext->Document()->GetAnimationController();
     343           0 :   if (aRoot) {
     344           0 :     mPresContext->EffectCompositor()
     345           0 :                 ->PreTraverseInSubtree(aRoot, aRestyleType);
     346           0 :     if (smilController) {
     347           0 :       smilController->PreTraverseInSubtree(aRoot);
     348             :     }
     349             :   } else {
     350           0 :     mPresContext->EffectCompositor()->PreTraverse(aRestyleType);
     351           0 :     if (smilController) {
     352           0 :       smilController->PreTraverse();
     353             :     }
     354             :   }
     355           0 : }
     356             : 
     357             : bool
     358           0 : ServoStyleSet::PrepareAndTraverseSubtree(
     359             :   RawGeckoElementBorrowed aRoot,
     360             :   TraversalRootBehavior aRootBehavior,
     361             :   TraversalRestyleBehavior aRestyleBehavior)
     362             : {
     363             :   bool forAnimationOnly =
     364           0 :     aRestyleBehavior == TraversalRestyleBehavior::ForAnimationOnly;
     365             : 
     366             :   AutoRestyleTimelineMarker marker(
     367           0 :     mPresContext->GetDocShell(), forAnimationOnly);
     368             : 
     369             :   // Get the Document's root element to ensure that the cache is valid before
     370             :   // calling into the (potentially-parallel) Servo traversal, where a cache hit
     371             :   // is necessary to avoid a data race when updating the cache.
     372           0 :   mozilla::Unused << aRoot->OwnerDoc()->GetRootElement();
     373             : 
     374           0 :   MOZ_ASSERT(!StylistNeedsUpdate());
     375           0 :   AutoSetInServoTraversal guard(this);
     376             : 
     377           0 :   const SnapshotTable& snapshots = Snapshots();
     378             : 
     379           0 :   bool isInitial = !aRoot->HasServoData();
     380             :   bool forReconstruct =
     381           0 :     aRestyleBehavior == TraversalRestyleBehavior::ForReconstruct;
     382             : #ifdef DEBUG
     383             :   bool forNewlyBoundElement =
     384           0 :     aRestyleBehavior == TraversalRestyleBehavior::ForNewlyBoundElement;
     385             : #endif
     386             :   bool postTraversalRequired = Servo_TraverseSubtree(
     387           0 :     aRoot, mRawSet.get(), &snapshots, aRootBehavior, aRestyleBehavior);
     388           0 :   MOZ_ASSERT(!(isInitial || forReconstruct || forNewlyBoundElement) ||
     389             :              !postTraversalRequired);
     390             : 
     391             :   // Don't need to trigger a second traversal if this restyle only needs
     392             :   // animation-only restyle.
     393           0 :   if (forAnimationOnly) {
     394           0 :     return postTraversalRequired;
     395             :   }
     396             : 
     397           0 :   auto root = const_cast<Element*>(aRoot);
     398             : 
     399             :   // If there are still animation restyles needed, trigger a second traversal to
     400             :   // update CSS animations or transitions' styles.
     401             :   //
     402             :   // We don't need to do this for SMIL since SMIL only updates its animation
     403             :   // values once at the begin of a tick. As a result, even if the previous
     404             :   // traversal caused, for example, the font-size to change, the SMIL style
     405             :   // won't be updated until the next tick anyway.
     406           0 :   EffectCompositor* compositor = mPresContext->EffectCompositor();
     407             :   EffectCompositor::AnimationRestyleType restyleType =
     408           0 :     EffectCompositor::AnimationRestyleType::Throttled;
     409           0 :   if (forReconstruct ? compositor->PreTraverseInSubtree(root, restyleType)
     410             :                      : compositor->PreTraverse(restyleType)) {
     411           0 :     if (Servo_TraverseSubtree(
     412           0 :           aRoot, mRawSet.get(), &snapshots, aRootBehavior, aRestyleBehavior)) {
     413           0 :       MOZ_ASSERT(!forReconstruct);
     414           0 :       if (isInitial) {
     415             :         // We're doing initial styling, and the additional animation
     416             :         // traversal changed the styles that were set by the first traversal.
     417             :         // This would normally require a post-traversal to update the style
     418             :         // contexts, and the DOM now has dirty descendant bits and RestyleData
     419             :         // in expectation of that post-traversal. But since this is actually
     420             :         // the initial styling, there are no style contexts to update and no
     421             :         // frames to apply the change hints to, so we don't need to do that
     422             :         // post-traversal. Instead, just drop this state and tell the caller
     423             :         // that no post-traversal is required.
     424           0 :         MOZ_ASSERT(!postTraversalRequired);
     425           0 :         ServoRestyleManager::ClearRestyleStateFromSubtree(root);
     426             :       } else {
     427           0 :         postTraversalRequired = true;
     428             :       }
     429             :     }
     430             :   }
     431             : 
     432           0 :   return postTraversalRequired;
     433             : }
     434             : 
     435             : already_AddRefed<nsStyleContext>
     436           0 : ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
     437             :                                    nsStyleContext* aParentContext)
     438             : {
     439           0 :   MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
     440           0 :   MOZ_ASSERT(aTextNode->GetParent());
     441           0 :   MOZ_ASSERT(aParentContext);
     442             : 
     443             :   // Gecko expects text node style contexts to be like elements that match no
     444             :   // rules: inherit the inherit structs, reset the reset structs. This is cheap
     445             :   // enough to do on the main thread, which means that the parallel style system
     446             :   // can avoid worrying about text nodes.
     447             :   const ServoComputedValues* parentComputedValues =
     448           0 :     aParentContext->ComputedValues();
     449             :   RefPtr<ServoComputedValues> computedValues =
     450           0 :     Servo_ComputedValues_Inherit(mRawSet.get(),
     451             :                                  parentComputedValues,
     452           0 :                                  InheritTarget::Text).Consume();
     453             : 
     454           0 :   return GetContext(computedValues.forget(), aParentContext,
     455             :                     nsCSSAnonBoxes::mozText,
     456             :                     CSSPseudoElementType::InheritingAnonBox,
     457           0 :                     nullptr);
     458             : }
     459             : 
     460             : already_AddRefed<nsStyleContext>
     461           0 : ServoStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
     462             : {
     463             :   const ServoComputedValues* parent =
     464           0 :     aParentContext->ComputedValues();
     465             :   RefPtr<ServoComputedValues> computedValues =
     466           0 :     Servo_ComputedValues_Inherit(mRawSet.get(),
     467             :                                  parent,
     468             :                                  InheritTarget::FirstLetterContinuation)
     469           0 :                                  .Consume();
     470           0 :   MOZ_ASSERT(computedValues);
     471             : 
     472           0 :   return GetContext(computedValues.forget(), aParentContext,
     473             :                     nsCSSAnonBoxes::firstLetterContinuation,
     474             :                     CSSPseudoElementType::InheritingAnonBox,
     475           0 :                     nullptr);
     476             : }
     477             : 
     478             : already_AddRefed<nsStyleContext>
     479           0 : ServoStyleSet::ResolveStyleForPlaceholder()
     480             : {
     481             :   RefPtr<nsStyleContext>& cache =
     482           0 :     mNonInheritingStyleContexts[nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
     483           0 :   if (cache) {
     484           0 :     RefPtr<nsStyleContext> retval = cache;
     485           0 :     return retval.forget();
     486             :   }
     487             : 
     488             :   RefPtr<ServoComputedValues> computedValues =
     489           0 :     Servo_ComputedValues_Inherit(mRawSet.get(),
     490             :                                  nullptr,
     491             :                                  InheritTarget::PlaceholderFrame)
     492           0 :                                  .Consume();
     493           0 :   MOZ_ASSERT(computedValues);
     494             : 
     495             :   RefPtr<nsStyleContext> retval =
     496           0 :     GetContext(computedValues.forget(), nullptr,
     497             :                nsCSSAnonBoxes::oofPlaceholder,
     498             :                CSSPseudoElementType::NonInheritingAnonBox,
     499           0 :                nullptr);
     500           0 :   cache = retval;
     501           0 :   return retval.forget();
     502             : }
     503             : 
     504             : already_AddRefed<nsStyleContext>
     505           0 : ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
     506             :                                          CSSPseudoElementType aType,
     507             :                                          nsStyleContext* aParentContext,
     508             :                                          Element* aPseudoElement)
     509             : {
     510           0 :   UpdateStylistIfNeeded();
     511             : 
     512           0 :   MOZ_ASSERT(aType < CSSPseudoElementType::Count);
     513             : 
     514           0 :   RefPtr<ServoComputedValues> computedValues;
     515           0 :   if (aPseudoElement) {
     516           0 :     MOZ_ASSERT(aType == aPseudoElement->GetPseudoElementType());
     517           0 :     computedValues = Servo_ResolveStyle(aPseudoElement,
     518           0 :                                         mRawSet.get()).Consume();
     519             :   } else {
     520             :     const ServoComputedValues* parentStyle =
     521           0 :       aParentContext ? aParentContext->ComputedValues() : nullptr;
     522             :     computedValues =
     523           0 :       Servo_ResolvePseudoStyle(aOriginatingElement,
     524             :                                aType,
     525             :                                /* is_probe = */ false,
     526             :                                parentStyle,
     527           0 :                                mRawSet.get()).Consume();
     528             :   }
     529             : 
     530           0 :   MOZ_ASSERT(computedValues);
     531             : 
     532           0 :   bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
     533           0 :                          aType == CSSPseudoElementType::after;
     534             : 
     535           0 :   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
     536           0 :   return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
     537           0 :                     isBeforeOrAfter ? aOriginatingElement : nullptr);
     538             : }
     539             : 
     540             : already_AddRefed<nsStyleContext>
     541           0 : ServoStyleSet::ResolveTransientStyle(Element* aElement,
     542             :                                      nsIAtom* aPseudoTag,
     543             :                                      CSSPseudoElementType aPseudoType,
     544             :                                      StyleRuleInclusion aRuleInclusion)
     545             : {
     546             :   RefPtr<ServoComputedValues> computedValues =
     547           0 :     ResolveTransientServoStyle(aElement, aPseudoType, aRuleInclusion);
     548             : 
     549           0 :   return GetContext(computedValues.forget(),
     550             :                     nullptr,
     551             :                     aPseudoTag,
     552           0 :                     aPseudoType, nullptr);
     553             : }
     554             : 
     555             : already_AddRefed<ServoComputedValues>
     556           0 : ServoStyleSet::ResolveTransientServoStyle(
     557             :     Element* aElement,
     558             :     CSSPseudoElementType aPseudoType,
     559             :     StyleRuleInclusion aRuleInclusion)
     560             : {
     561           0 :   PreTraverseSync();
     562           0 :   return ResolveStyleLazily(aElement, aPseudoType, aRuleInclusion);
     563             : }
     564             : 
     565             : already_AddRefed<ServoStyleContext>
     566           0 : ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
     567             :                                                   nsStyleContext* aParentContext)
     568             : {
     569           0 :   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
     570             :              !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
     571             : 
     572           0 :   UpdateStylistIfNeeded();
     573             : 
     574             :   bool skipFixup =
     575           0 :     nsCSSAnonBoxes::AnonBoxSkipsParentDisplayBasedStyleFixup(aPseudoTag);
     576             : 
     577             :   const ServoComputedValues* parentStyle =
     578           0 :     aParentContext ? aParentContext->ComputedValues()
     579           0 :                    : nullptr;
     580             :   RefPtr<ServoComputedValues> computedValues =
     581           0 :     Servo_ComputedValues_GetForAnonymousBox(parentStyle, aPseudoTag, skipFixup,
     582           0 :                                             mRawSet.get()).Consume();
     583             : #ifdef DEBUG
     584           0 :   if (!computedValues) {
     585           0 :     nsString pseudo;
     586           0 :     aPseudoTag->ToString(pseudo);
     587           0 :     NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
     588             :              NS_ConvertUTF16toUTF8(pseudo).get()).get());
     589           0 :     MOZ_CRASH();
     590             :   }
     591             : #endif
     592             : 
     593           0 :   return GetContext(computedValues.forget(), aParentContext, aPseudoTag,
     594           0 :                     CSSPseudoElementType::InheritingAnonBox, nullptr);
     595             : }
     596             : 
     597             : already_AddRefed<nsStyleContext>
     598           0 : ServoStyleSet::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
     599             : {
     600           0 :   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
     601             :              nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
     602           0 :   MOZ_ASSERT(aPseudoTag != nsCSSAnonBoxes::pageContent,
     603             :              "If nsCSSAnonBoxes::pageContent ends up non-inheriting, check "
     604             :              "whether we need to do anything to move the "
     605             :              "@page handling from ResolveInheritingAnonymousBoxStyle to "
     606             :              "ResolveNonInheritingAnonymousBoxStyle");
     607             : 
     608             :   nsCSSAnonBoxes::NonInheriting type =
     609           0 :     nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(aPseudoTag);
     610           0 :   RefPtr<nsStyleContext>& cache = mNonInheritingStyleContexts[type];
     611           0 :   if (cache) {
     612           0 :     RefPtr<nsStyleContext> retval = cache;
     613           0 :     return retval.forget();
     614             :   }
     615             : 
     616           0 :   UpdateStylistIfNeeded();
     617             : 
     618             :   // We always want to skip parent-based display fixup here.  It never makes
     619             :   // sense for non-inheriting anonymous boxes.  (Static assertions in
     620             :   // nsCSSAnonBoxes.cpp ensure that all non-inheriting non-anonymous boxes
     621             :   // are indeed annotated as skipping this fixup.)
     622           0 :   MOZ_ASSERT(!nsCSSAnonBoxes::IsNonInheritingAnonBox(nsCSSAnonBoxes::viewport),
     623             :              "viewport needs fixup to handle blockifying it");
     624             :   RefPtr<ServoComputedValues> computedValues =
     625           0 :     Servo_ComputedValues_GetForAnonymousBox(nullptr, aPseudoTag, true,
     626           0 :                                             mRawSet.get()).Consume();
     627             : #ifdef DEBUG
     628           0 :   if (!computedValues) {
     629           0 :     nsString pseudo;
     630           0 :     aPseudoTag->ToString(pseudo);
     631           0 :     NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
     632             :              NS_ConvertUTF16toUTF8(pseudo).get()).get());
     633           0 :     MOZ_CRASH();
     634             :   }
     635             : #endif
     636             : 
     637             :   RefPtr<nsStyleContext> retval =
     638           0 :     GetContext(computedValues.forget(), nullptr, aPseudoTag,
     639           0 :                CSSPseudoElementType::NonInheritingAnonBox, nullptr);
     640           0 :   cache = retval;
     641           0 :   return retval.forget();
     642             : }
     643             : 
     644             : // manage the set of style sheets in the style set
     645             : nsresult
     646           0 : ServoStyleSet::AppendStyleSheet(SheetType aType,
     647             :                                 ServoStyleSheet* aSheet)
     648             : {
     649           0 :   MOZ_ASSERT(aSheet);
     650           0 :   MOZ_ASSERT(aSheet->IsApplicable());
     651           0 :   MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
     652           0 :   MOZ_ASSERT(aSheet->RawContents(), "Raw sheet should be in place before insertion.");
     653             : 
     654           0 :   RemoveSheetOfType(aType, aSheet);
     655           0 :   AppendSheetOfType(aType, aSheet);
     656             : 
     657           0 :   if (mRawSet) {
     658             :     // Maintain a mirrored list of sheets on the servo side.
     659             :     // Servo will remove aSheet from its original position as part of the call
     660             :     // to Servo_StyleSet_AppendStyleSheet.
     661           0 :     Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet);
     662           0 :     SetStylistStyleSheetsDirty();
     663             :   }
     664             : 
     665           0 :   return NS_OK;
     666             : }
     667             : 
     668             : nsresult
     669           0 : ServoStyleSet::PrependStyleSheet(SheetType aType,
     670             :                                  ServoStyleSheet* aSheet)
     671             : {
     672           0 :   MOZ_ASSERT(aSheet);
     673           0 :   MOZ_ASSERT(aSheet->IsApplicable());
     674           0 :   MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
     675           0 :   MOZ_ASSERT(aSheet->RawContents(),
     676             :              "Raw sheet should be in place before insertion.");
     677             : 
     678           0 :   RemoveSheetOfType(aType, aSheet);
     679           0 :   PrependSheetOfType(aType, aSheet);
     680             : 
     681           0 :   if (mRawSet) {
     682             :     // Maintain a mirrored list of sheets on the servo side.
     683             :     // Servo will remove aSheet from its original position as part of the call
     684             :     // to Servo_StyleSet_PrependStyleSheet.
     685           0 :     Servo_StyleSet_PrependStyleSheet(mRawSet.get(), aSheet);
     686           0 :     SetStylistStyleSheetsDirty();
     687             :   }
     688             : 
     689           0 :   return NS_OK;
     690             : }
     691             : 
     692             : nsresult
     693           0 : ServoStyleSet::RemoveStyleSheet(SheetType aType,
     694             :                                 ServoStyleSheet* aSheet)
     695             : {
     696           0 :   MOZ_ASSERT(aSheet);
     697           0 :   MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
     698             : 
     699           0 :   RemoveSheetOfType(aType, aSheet);
     700           0 :   if (mRawSet) {
     701             :     // Maintain a mirrored list of sheets on the servo side.
     702           0 :     Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet);
     703           0 :     SetStylistStyleSheetsDirty();
     704             :   }
     705             : 
     706           0 :   return NS_OK;
     707             : }
     708             : 
     709             : nsresult
     710           0 : ServoStyleSet::ReplaceSheets(SheetType aType,
     711             :                              const nsTArray<RefPtr<ServoStyleSheet>>& aNewSheets)
     712             : {
     713             :   // Gecko uses a two-dimensional array keyed by sheet type, whereas Servo
     714             :   // stores a flattened list. This makes ReplaceSheets a pretty clunky thing
     715             :   // to express. If the need ever arises, we can easily make this more efficent,
     716             :   // probably by aligning the representations better between engines.
     717             : 
     718           0 :   SetStylistStyleSheetsDirty();
     719             : 
     720             :   // Remove all the existing sheets first.
     721           0 :   for (const auto& sheet : mSheets[aType]) {
     722           0 :     sheet->DropStyleSet(this);
     723           0 :     if (mRawSet) {
     724           0 :       Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), sheet);
     725             :     }
     726             :   }
     727           0 :   mSheets[aType].Clear();
     728             : 
     729             :   // Add in all the new sheets.
     730           0 :   for (auto& sheet : aNewSheets) {
     731           0 :     AppendSheetOfType(aType, sheet);
     732           0 :     if (mRawSet) {
     733           0 :       MOZ_ASSERT(sheet->RawContents(), "Raw sheet should be in place before replacement.");
     734           0 :       Servo_StyleSet_AppendStyleSheet(mRawSet.get(), sheet);
     735             :     }
     736             :   }
     737             : 
     738           0 :   return NS_OK;
     739             : }
     740             : 
     741             : nsresult
     742           0 : ServoStyleSet::InsertStyleSheetBefore(SheetType aType,
     743             :                                       ServoStyleSheet* aNewSheet,
     744             :                                       ServoStyleSheet* aReferenceSheet)
     745             : {
     746           0 :   MOZ_ASSERT(aNewSheet);
     747           0 :   MOZ_ASSERT(aReferenceSheet);
     748           0 :   MOZ_ASSERT(aNewSheet->IsApplicable());
     749           0 :   MOZ_ASSERT(aNewSheet != aReferenceSheet, "Can't place sheet before itself.");
     750           0 :   MOZ_ASSERT(aNewSheet->RawContents(), "Raw sheet should be in place before insertion.");
     751           0 :   MOZ_ASSERT(aReferenceSheet->RawContents(), "Reference sheet should have a raw sheet.");
     752             : 
     753             :   // Servo will remove aNewSheet from its original position as part of the
     754             :   // call to Servo_StyleSet_InsertStyleSheetBefore.
     755           0 :   RemoveSheetOfType(aType, aNewSheet);
     756           0 :   InsertSheetOfType(aType, aNewSheet, aReferenceSheet);
     757             : 
     758           0 :   if (mRawSet) {
     759             :     // Maintain a mirrored list of sheets on the servo side.
     760             :     Servo_StyleSet_InsertStyleSheetBefore(
     761           0 :         mRawSet.get(), aNewSheet, aReferenceSheet);
     762           0 :     SetStylistStyleSheetsDirty();
     763             :   }
     764             : 
     765           0 :   return NS_OK;
     766             : }
     767             : 
     768             : void
     769           0 : ServoStyleSet::UpdateStyleSheet(ServoStyleSheet* aSheet)
     770             : {
     771           0 :   MOZ_ASSERT(aSheet);
     772             :   // TODO(emilio): Get rid of this.
     773           0 : }
     774             : 
     775             : int32_t
     776           0 : ServoStyleSet::SheetCount(SheetType aType) const
     777             : {
     778           0 :   MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
     779           0 :   return mSheets[aType].Length();
     780             : }
     781             : 
     782             : ServoStyleSheet*
     783           0 : ServoStyleSet::StyleSheetAt(SheetType aType, int32_t aIndex) const
     784             : {
     785           0 :   MOZ_ASSERT(nsStyleSet::IsCSSSheetType(aType));
     786           0 :   return mSheets[aType][aIndex];
     787             : }
     788             : 
     789             : void
     790           0 : ServoStyleSet::AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const
     791             : {
     792           0 :   if (mBindingManager) {
     793           0 :     mBindingManager->AppendAllSheets(aArray);
     794             :   }
     795           0 : }
     796             : 
     797             : nsresult
     798           0 : ServoStyleSet::RemoveDocStyleSheet(ServoStyleSheet* aSheet)
     799             : {
     800           0 :   return RemoveStyleSheet(SheetType::Doc, aSheet);
     801             : }
     802             : 
     803             : nsresult
     804           0 : ServoStyleSet::AddDocStyleSheet(ServoStyleSheet* aSheet,
     805             :                                 nsIDocument* aDocument)
     806             : {
     807           0 :   MOZ_ASSERT(aSheet->IsApplicable());
     808           0 :   MOZ_ASSERT(aSheet->RawContents(), "Raw sheet should be in place by this point.");
     809             : 
     810           0 :   RefPtr<StyleSheet> strong(aSheet);
     811             : 
     812           0 :   RemoveSheetOfType(SheetType::Doc, aSheet);
     813             : 
     814             :   size_t index =
     815           0 :     aDocument->FindDocStyleSheetInsertionPoint(mSheets[SheetType::Doc], aSheet);
     816             : 
     817           0 :   if (index < mSheets[SheetType::Doc].Length()) {
     818             :     // This case is insert before.
     819           0 :     ServoStyleSheet *beforeSheet = mSheets[SheetType::Doc][index];
     820           0 :     InsertSheetOfType(SheetType::Doc, aSheet, beforeSheet);
     821             : 
     822           0 :     if (mRawSet) {
     823             :       // Maintain a mirrored list of sheets on the servo side.
     824           0 :       Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet, beforeSheet);
     825           0 :       SetStylistStyleSheetsDirty();
     826             :     }
     827             :   } else {
     828             :     // This case is append.
     829           0 :     AppendSheetOfType(SheetType::Doc, aSheet);
     830             : 
     831           0 :     if (mRawSet) {
     832             :       // Maintain a mirrored list of sheets on the servo side.
     833           0 :       Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet);
     834           0 :       SetStylistStyleSheetsDirty();
     835             :     }
     836             :   }
     837             : 
     838           0 :   return NS_OK;
     839             : }
     840             : 
     841             : already_AddRefed<nsStyleContext>
     842           0 : ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
     843             :                                        CSSPseudoElementType aType,
     844             :                                        nsStyleContext* aParentContext)
     845             : {
     846           0 :   UpdateStylistIfNeeded();
     847             : 
     848             :   // NB: We ignore aParentContext, because in some cases
     849             :   // (first-line/first-letter on anonymous box blocks) Gecko passes something
     850             :   // nonsensical there.  In all other cases we want to inherit directly from
     851             :   // aOriginatingElement's styles anyway.
     852           0 :   MOZ_ASSERT(aType < CSSPseudoElementType::Count);
     853             : 
     854             :   RefPtr<ServoComputedValues> computedValues =
     855           0 :     Servo_ResolvePseudoStyle(aOriginatingElement, aType,
     856             :                              /* is_probe = */ true,
     857             :                              nullptr,
     858           0 :                              mRawSet.get()).Consume();
     859           0 :   if (!computedValues) {
     860           0 :     return nullptr;
     861             :   }
     862             : 
     863             :   // For :before and :after pseudo-elements, having display: none or no
     864             :   // 'content' property is equivalent to not having the pseudo-element
     865             :   // at all.
     866           0 :   bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
     867           0 :                          aType == CSSPseudoElementType::after;
     868           0 :   if (isBeforeOrAfter) {
     869           0 :     const nsStyleDisplay* display = Servo_GetStyleDisplay(computedValues);
     870           0 :     const nsStyleContent* content = Servo_GetStyleContent(computedValues);
     871             :     // XXXldb What is contentCount for |content: ""|?
     872           0 :     if (display->mDisplay == StyleDisplay::None ||
     873           0 :         content->ContentCount() == 0) {
     874           0 :       return nullptr;
     875             :     }
     876             :   }
     877             : 
     878           0 :   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
     879           0 :   return GetContext(computedValues.forget(), aParentContext, pseudoTag, aType,
     880           0 :                     isBeforeOrAfter ? aOriginatingElement : nullptr);
     881             : }
     882             : 
     883             : nsRestyleHint
     884           0 : ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
     885             :                                       EventStates aStateMask)
     886             : {
     887           0 :   NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
     888           0 :   return nsRestyleHint(0);
     889             : }
     890             : 
     891             : nsRestyleHint
     892           0 : ServoStyleSet::HasStateDependentStyle(dom::Element* aElement,
     893             :                                       CSSPseudoElementType aPseudoType,
     894             :                                      dom::Element* aPseudoElement,
     895             :                                      EventStates aStateMask)
     896             : {
     897           0 :   NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
     898           0 :   return nsRestyleHint(0);
     899             : }
     900             : 
     901             : bool
     902           0 : ServoStyleSet::StyleDocument(TraversalRestyleBehavior aRestyleBehavior)
     903             : {
     904           0 :   MOZ_ASSERT(
     905             :     aRestyleBehavior == TraversalRestyleBehavior::Normal ||
     906             :     aRestyleBehavior == TraversalRestyleBehavior::ForCSSRuleChanges,
     907             :     "StyleDocument() should be only called for normal traversal or CSS rule "
     908             :     "changes");
     909             : 
     910           0 :   PreTraverse();
     911             : 
     912             :   // Restyle the document from the root element and each of the document level
     913             :   // NAC subtree roots.
     914           0 :   bool postTraversalRequired = false;
     915           0 :   DocumentStyleRootIterator iter(mPresContext->Document());
     916           0 :   while (Element* root = iter.GetNextStyleRoot()) {
     917           0 :     if (PrepareAndTraverseSubtree(root,
     918             :                                   TraversalRootBehavior::Normal,
     919             :                                   aRestyleBehavior)) {
     920           0 :       postTraversalRequired = true;
     921             :     }
     922           0 :   }
     923           0 :   return postTraversalRequired;
     924             : }
     925             : 
     926             : bool
     927           0 : ServoStyleSet::StyleDocumentForAnimationOnly()
     928             : {
     929           0 :   PreTraverse(nullptr, EffectCompositor::AnimationRestyleType::Full);
     930             : 
     931           0 :   bool postTraversalRequired = false;
     932           0 :   DocumentStyleRootIterator iter(mPresContext->Document());
     933           0 :   while (Element* root = iter.GetNextStyleRoot()) {
     934           0 :     if (PrepareAndTraverseSubtree(root,
     935             :                                   TraversalRootBehavior::Normal,
     936             :                                   TraversalRestyleBehavior::ForAnimationOnly)) {
     937           0 :       postTraversalRequired = true;
     938             :     }
     939           0 :   }
     940           0 :   return postTraversalRequired;
     941             : }
     942             : 
     943             : void
     944           0 : ServoStyleSet::StyleNewSubtree(Element* aRoot)
     945             : {
     946           0 :   MOZ_ASSERT(!aRoot->HasServoData());
     947             : 
     948           0 :   PreTraverse();
     949             : 
     950             :   DebugOnly<bool> postTraversalRequired =
     951           0 :     PrepareAndTraverseSubtree(aRoot,
     952             :                               TraversalRootBehavior::Normal,
     953           0 :                               TraversalRestyleBehavior::Normal);
     954           0 :   MOZ_ASSERT(!postTraversalRequired);
     955           0 : }
     956             : 
     957             : void
     958           0 : ServoStyleSet::StyleNewChildren(Element* aParent)
     959             : {
     960           0 :   PreTraverse();
     961             : 
     962             :   PrepareAndTraverseSubtree(aParent,
     963             :                             TraversalRootBehavior::UnstyledChildrenOnly,
     964           0 :                             TraversalRestyleBehavior::Normal);
     965             :   // We can't assert that Servo_TraverseSubtree returns false, since aParent
     966             :   // or some of its other children might have pending restyles.
     967           0 : }
     968             : 
     969             : void
     970           0 : ServoStyleSet::StyleNewlyBoundElement(Element* aElement)
     971             : {
     972           0 :   PreTraverse();
     973             : 
     974             :   // In general the element is always styled by the time we're applying XBL
     975             :   // bindings, because we need to style the element to know what the binding
     976             :   // URI is. However, programmatic consumers of the XBL service (like the
     977             :   // XML pretty printer) _can_ apply bindings without having styled the bound
     978             :   // element. We could assert against this and require the callers manually
     979             :   // resolve the style first, but it's easy enough to just handle here.
     980             :   //
     981             :   // Also, when applying XBL bindings to elements within a display:none or
     982             :   // unstyled subtree (for example, when <object> elements are wrapped to be
     983             :   // exposed to JS), we need to tell the traversal that it is OK to
     984             :   // skip restyling, rather than panic when trying to unwrap the styles
     985             :   // it expects to have just computed.
     986             : 
     987             :   TraversalRootBehavior rootBehavior =
     988           0 :     MOZ_UNLIKELY(!aElement->HasServoData())
     989           0 :       ? TraversalRootBehavior::Normal
     990           0 :       : TraversalRootBehavior::UnstyledChildrenOnly;
     991             : 
     992             :   PrepareAndTraverseSubtree(aElement,
     993             :                             rootBehavior,
     994           0 :                             TraversalRestyleBehavior::ForNewlyBoundElement);
     995           0 : }
     996             : 
     997             : void
     998           0 : ServoStyleSet::StyleSubtreeForReconstruct(Element* aRoot)
     999             : {
    1000           0 :   PreTraverse(aRoot);
    1001             : 
    1002             :   DebugOnly<bool> postTraversalRequired =
    1003           0 :     PrepareAndTraverseSubtree(aRoot,
    1004             :                               TraversalRootBehavior::Normal,
    1005           0 :                               TraversalRestyleBehavior::ForReconstruct);
    1006           0 :   MOZ_ASSERT(!postTraversalRequired);
    1007           0 : }
    1008             : 
    1009             : void
    1010           0 : ServoStyleSet::ForceAllStyleDirty()
    1011             : {
    1012           0 :   SetStylistStyleSheetsDirty();
    1013           0 :   Servo_StyleSet_NoteStyleSheetsChanged(mRawSet.get(), mAuthorStyleDisabled);
    1014           0 : }
    1015             : 
    1016             : void
    1017           0 : ServoStyleSet::RecordStyleSheetChange(
    1018             :     ServoStyleSheet* aSheet,
    1019             :     StyleSheet::ChangeType aChangeType)
    1020             : {
    1021           0 :   SetStylistStyleSheetsDirty();
    1022           0 :   switch (aChangeType) {
    1023             :     case StyleSheet::ChangeType::RuleAdded:
    1024             :     case StyleSheet::ChangeType::RuleRemoved:
    1025             :     case StyleSheet::ChangeType::RuleChanged:
    1026             :       // FIXME(emilio): We can presumably do better in a bunch of these.
    1027           0 :       return ForceAllStyleDirty();
    1028             :     case StyleSheet::ChangeType::ApplicableStateChanged:
    1029             :     case StyleSheet::ChangeType::Added:
    1030             :     case StyleSheet::ChangeType::Removed:
    1031             :       // Do nothing, we've already recorded the change in the
    1032             :       // Append/Remove/Replace methods, etc, and will act consequently.
    1033           0 :       return;
    1034             :   }
    1035             : }
    1036             : 
    1037             : #ifdef DEBUG
    1038             : void
    1039           0 : ServoStyleSet::AssertTreeIsClean()
    1040             : {
    1041           0 :   DocumentStyleRootIterator iter(mPresContext->Document());
    1042           0 :   while (Element* root = iter.GetNextStyleRoot()) {
    1043           0 :     Servo_AssertTreeIsClean(root);
    1044           0 :   }
    1045           0 : }
    1046             : #endif
    1047             : 
    1048             : bool
    1049           0 : ServoStyleSet::GetKeyframesForName(const nsString& aName,
    1050             :                                    const nsTimingFunction& aTimingFunction,
    1051             :                                    nsTArray<Keyframe>& aKeyframes)
    1052             : {
    1053           0 :   UpdateStylistIfNeeded();
    1054             : 
    1055           0 :   NS_ConvertUTF16toUTF8 name(aName);
    1056           0 :   return Servo_StyleSet_GetKeyframesForName(mRawSet.get(),
    1057             :                                             &name,
    1058             :                                             &aTimingFunction,
    1059           0 :                                             &aKeyframes);
    1060             : }
    1061             : 
    1062             : nsTArray<ComputedKeyframeValues>
    1063           0 : ServoStyleSet::GetComputedKeyframeValuesFor(
    1064             :   const nsTArray<Keyframe>& aKeyframes,
    1065             :   Element* aElement,
    1066             :   ServoComputedValuesBorrowed aComputedValues)
    1067             : {
    1068           0 :   nsTArray<ComputedKeyframeValues> result(aKeyframes.Length());
    1069             : 
    1070             :   // Construct each nsTArray<PropertyStyleAnimationValuePair> here.
    1071           0 :   result.AppendElements(aKeyframes.Length());
    1072             : 
    1073             :   Servo_GetComputedKeyframeValues(&aKeyframes,
    1074             :                                   aElement,
    1075             :                                   aComputedValues,
    1076           0 :                                   mRawSet.get(),
    1077           0 :                                   &result);
    1078           0 :   return result;
    1079             : }
    1080             : 
    1081             : void
    1082           0 : ServoStyleSet::GetAnimationValues(
    1083             :   RawServoDeclarationBlock* aDeclarations,
    1084             :   Element* aElement,
    1085             :   ServoComputedValuesBorrowed aComputedValues,
    1086             :   nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues)
    1087             : {
    1088             :   Servo_GetAnimationValues(aDeclarations,
    1089             :                            aElement,
    1090             :                            aComputedValues,
    1091           0 :                            mRawSet.get(),
    1092           0 :                            &aAnimationValues);
    1093           0 : }
    1094             : 
    1095             : already_AddRefed<ServoComputedValues>
    1096           0 : ServoStyleSet::GetBaseComputedValuesForElement(
    1097             :   Element* aElement,
    1098             :   CSSPseudoElementType aPseudoType,
    1099             :   ServoComputedValuesBorrowed aStyle)
    1100             : {
    1101           0 :   return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
    1102             :                                                         aElement,
    1103             :                                                         aStyle,
    1104           0 :                                                         &Snapshots(),
    1105           0 :                                                         aPseudoType).Consume();
    1106             : }
    1107             : 
    1108             : already_AddRefed<RawServoAnimationValue>
    1109           0 : ServoStyleSet::ComputeAnimationValue(
    1110             :   Element* aElement,
    1111             :   RawServoDeclarationBlock* aDeclarations,
    1112             :   ServoComputedValuesBorrowed aComputedValues)
    1113             : {
    1114           0 :   return Servo_AnimationValue_Compute(aElement,
    1115             :                                       aDeclarations,
    1116             :                                       aComputedValues,
    1117           0 :                                       mRawSet.get()).Consume();
    1118             : }
    1119             : 
    1120             : bool
    1121           0 : ServoStyleSet::EnsureUniqueInnerOnCSSSheets()
    1122             : {
    1123           0 :   AutoTArray<StyleSheet*, 32> queue;
    1124           0 :   for (auto& entryArray : mSheets) {
    1125           0 :     for (auto& sheet : entryArray) {
    1126           0 :       queue.AppendElement(sheet);
    1127             :     }
    1128             :   }
    1129             :   // This is a stub until more of the functionality of nsStyleSet is
    1130             :   // replicated for Servo here.
    1131             : 
    1132             :   // Bug 1290276 will replicate the nsStyleSet work of checking
    1133             :   // a nsBindingManager
    1134             : 
    1135           0 :   while (!queue.IsEmpty()) {
    1136           0 :     uint32_t idx = queue.Length() - 1;
    1137           0 :     StyleSheet* sheet = queue[idx];
    1138           0 :     queue.RemoveElementAt(idx);
    1139             : 
    1140           0 :     sheet->EnsureUniqueInner();
    1141             : 
    1142             :     // Enqueue all the sheet's children.
    1143           0 :     sheet->AppendAllChildSheets(queue);
    1144             :   }
    1145             : 
    1146           0 :   bool res = mNeedsRestyleAfterEnsureUniqueInner;
    1147           0 :   mNeedsRestyleAfterEnsureUniqueInner = false;
    1148           0 :   return res;
    1149             : }
    1150             : 
    1151             : void
    1152           0 : ServoStyleSet::RebuildData()
    1153             : {
    1154           0 :   ClearNonInheritingStyleContexts();
    1155           0 :   Servo_StyleSet_RebuildData(mRawSet.get());
    1156           0 : }
    1157             : 
    1158             : void
    1159           0 : ServoStyleSet::ClearDataAndMarkDeviceDirty()
    1160             : {
    1161           0 :   ClearNonInheritingStyleContexts();
    1162           0 :   Servo_StyleSet_Clear(mRawSet.get());
    1163           0 :   mStylistState |= StylistState::FullyDirty;
    1164           0 : }
    1165             : 
    1166             : void
    1167           0 : ServoStyleSet::CompatibilityModeChanged()
    1168             : {
    1169           0 :   Servo_StyleSet_CompatModeChanged(mRawSet.get());
    1170           0 : }
    1171             : 
    1172             : already_AddRefed<ServoComputedValues>
    1173           0 : ServoStyleSet::ResolveServoStyle(Element* aElement)
    1174             : {
    1175           0 :   UpdateStylistIfNeeded();
    1176           0 :   return Servo_ResolveStyle(aElement, mRawSet.get()).Consume();
    1177             : }
    1178             : 
    1179             : void
    1180           0 : ServoStyleSet::ClearNonInheritingStyleContexts()
    1181             : {
    1182           0 :   for (RefPtr<nsStyleContext>& ptr : mNonInheritingStyleContexts) {
    1183           0 :     ptr = nullptr;
    1184             :   }
    1185           0 : }
    1186             : 
    1187             : already_AddRefed<ServoComputedValues>
    1188           0 : ServoStyleSet::ResolveStyleLazily(Element* aElement,
    1189             :                                   CSSPseudoElementType aPseudoType,
    1190             :                                   StyleRuleInclusion aRuleInclusion)
    1191             : {
    1192           0 :   mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType);
    1193           0 :   MOZ_ASSERT(!StylistNeedsUpdate());
    1194             : 
    1195           0 :   AutoSetInServoTraversal guard(this);
    1196             : 
    1197             :   /**
    1198             :    * NB: This is needed because we process animations and transitions on the
    1199             :    * pseudo-elements themselves, not on the parent's EagerPseudoStyles.
    1200             :    *
    1201             :    * That means that that style doesn't account for animations, and we can't do
    1202             :    * that easily from the traversal without doing wasted work.
    1203             :    *
    1204             :    * As such, we just lie here a bit, which is the entrypoint of
    1205             :    * getComputedStyle, the only API where this can be observed, to look at the
    1206             :    * style of the pseudo-element if it exists instead.
    1207             :    */
    1208           0 :   Element* elementForStyleResolution = aElement;
    1209           0 :   CSSPseudoElementType pseudoTypeForStyleResolution = aPseudoType;
    1210           0 :   if (aPseudoType == CSSPseudoElementType::before) {
    1211           0 :     if (Element* pseudo = nsLayoutUtils::GetBeforePseudo(aElement)) {
    1212           0 :       elementForStyleResolution = pseudo;
    1213           0 :       pseudoTypeForStyleResolution = CSSPseudoElementType::NotPseudo;
    1214             :     }
    1215           0 :   } else if (aPseudoType == CSSPseudoElementType::after) {
    1216           0 :     if (Element* pseudo = nsLayoutUtils::GetAfterPseudo(aElement)) {
    1217           0 :       elementForStyleResolution = pseudo;
    1218           0 :       pseudoTypeForStyleResolution = CSSPseudoElementType::NotPseudo;
    1219             :     }
    1220             :   }
    1221             : 
    1222             :   RefPtr<ServoComputedValues> computedValues =
    1223           0 :     Servo_ResolveStyleLazily(elementForStyleResolution,
    1224             :                              pseudoTypeForStyleResolution,
    1225             :                              aRuleInclusion,
    1226           0 :                              &Snapshots(),
    1227           0 :                              mRawSet.get()).Consume();
    1228             : 
    1229           0 :   if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoType)) {
    1230             :     computedValues =
    1231           0 :       Servo_ResolveStyleLazily(elementForStyleResolution,
    1232             :                                pseudoTypeForStyleResolution,
    1233             :                                aRuleInclusion,
    1234           0 :                                &Snapshots(),
    1235           0 :                                mRawSet.get()).Consume();
    1236             :   }
    1237             : 
    1238           0 :   return computedValues.forget();
    1239             : }
    1240             : 
    1241             : bool
    1242           0 : ServoStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
    1243             : {
    1244           0 :   UpdateStylistIfNeeded();
    1245           0 :   Servo_StyleSet_GetFontFaceRules(mRawSet.get(), &aArray);
    1246           0 :   return true;
    1247             : }
    1248             : 
    1249             : nsCSSCounterStyleRule*
    1250           0 : ServoStyleSet::CounterStyleRuleForName(nsIAtom* aName)
    1251             : {
    1252           0 :   return Servo_StyleSet_GetCounterStyleRule(mRawSet.get(), aName);
    1253             : }
    1254             : 
    1255             : already_AddRefed<ServoComputedValues>
    1256           0 : ServoStyleSet::ResolveForDeclarations(
    1257             :   ServoComputedValuesBorrowedOrNull aParentOrNull,
    1258             :   RawServoDeclarationBlockBorrowed aDeclarations)
    1259             : {
    1260           0 :   UpdateStylistIfNeeded();
    1261           0 :   return Servo_StyleSet_ResolveForDeclarations(mRawSet.get(),
    1262             :                                                aParentOrNull,
    1263           0 :                                                aDeclarations).Consume();
    1264             : }
    1265             : 
    1266             : void
    1267           0 : ServoStyleSet::UpdateStylist()
    1268             : {
    1269           0 :   MOZ_ASSERT(StylistNeedsUpdate());
    1270           0 :   if (mStylistState & StylistState::FullyDirty) {
    1271           0 :     RebuildData();
    1272             : 
    1273           0 :     if (mStylistState & StylistState::StyleSheetsDirty) {
    1274             :       // Normally, whoever was in charge of posting a RebuildAllStyleDataEvent,
    1275             :       // would also be in charge of posting a restyle/change hint according to
    1276             :       // it.
    1277             :       //
    1278             :       // However, other stylesheets may have been added to the document in the
    1279             :       // same period, so when both bits are set, we need to do a full subtree
    1280             :       // update, because we can no longer reason about the state of the style
    1281             :       // data.
    1282             :       //
    1283             :       // We could not clear the invalidations when rebuilding the data and
    1284             :       // process them here... But it's not clear if that complexity is worth
    1285             :       // to handle this edge case more efficiently.
    1286           0 :       if (Element* root = mPresContext->Document()->GetDocumentElement()) {
    1287           0 :         Servo_NoteExplicitHints(root, eRestyle_Subtree, nsChangeHint(0));
    1288             :       }
    1289             :     }
    1290             :   } else {
    1291           0 :     MOZ_ASSERT(mStylistState & StylistState::StyleSheetsDirty);
    1292           0 :     Element* root = mPresContext->Document()->GetDocumentElement();
    1293           0 :     Servo_StyleSet_FlushStyleSheets(mRawSet.get(), root);
    1294             :   }
    1295           0 :   mStylistState = StylistState::NotDirty;
    1296           0 : }
    1297             : 
    1298             : void
    1299           0 : ServoStyleSet::MaybeGCRuleTree()
    1300             : {
    1301           0 :   MOZ_ASSERT(NS_IsMainThread());
    1302           0 :   Servo_MaybeGCRuleTree(mRawSet.get());
    1303           0 : }
    1304             : 
    1305             : void
    1306           0 : ServoStyleSet::PrependSheetOfType(SheetType aType,
    1307             :                                   ServoStyleSheet* aSheet)
    1308             : {
    1309           0 :   aSheet->AddStyleSet(this);
    1310           0 :   mSheets[aType].InsertElementAt(0, aSheet);
    1311           0 : }
    1312             : 
    1313             : void
    1314           0 : ServoStyleSet::AppendSheetOfType(SheetType aType,
    1315             :                                  ServoStyleSheet* aSheet)
    1316             : {
    1317           0 :   aSheet->AddStyleSet(this);
    1318           0 :   mSheets[aType].AppendElement(aSheet);
    1319           0 : }
    1320             : 
    1321             : void
    1322           0 : ServoStyleSet::InsertSheetOfType(SheetType aType,
    1323             :                                  ServoStyleSheet* aSheet,
    1324             :                                  ServoStyleSheet* aBeforeSheet)
    1325             : {
    1326           0 :   for (uint32_t i = 0; i < mSheets[aType].Length(); ++i) {
    1327           0 :     if (mSheets[aType][i] == aBeforeSheet) {
    1328           0 :       aSheet->AddStyleSet(this);
    1329           0 :       mSheets[aType].InsertElementAt(i, aSheet);
    1330           0 :       return;
    1331             :     }
    1332             :   }
    1333             : }
    1334             : 
    1335             : void
    1336           0 : ServoStyleSet::RemoveSheetOfType(SheetType aType,
    1337             :                                  ServoStyleSheet* aSheet)
    1338             : {
    1339           0 :   for (uint32_t i = 0; i < mSheets[aType].Length(); ++i) {
    1340           0 :     if (mSheets[aType][i] == aSheet) {
    1341           0 :       aSheet->DropStyleSet(this);
    1342           0 :       mSheets[aType].RemoveElementAt(i);
    1343             :     }
    1344             :   }
    1345           0 : }
    1346             : 
    1347             : void
    1348           0 : ServoStyleSet::RunPostTraversalTasks()
    1349             : {
    1350           0 :   MOZ_ASSERT(!IsInServoTraversal());
    1351             : 
    1352           0 :   if (mPostTraversalTasks.IsEmpty()) {
    1353           0 :     return;
    1354             :   }
    1355             : 
    1356           0 :   nsTArray<PostTraversalTask> tasks;
    1357           0 :   tasks.SwapElements(mPostTraversalTasks);
    1358             : 
    1359           0 :   for (auto& task : tasks) {
    1360           0 :     task.Run();
    1361             :   }
    1362             : }
    1363             : 
    1364             : ServoStyleRuleMap*
    1365           0 : ServoStyleSet::StyleRuleMap()
    1366             : {
    1367           0 :   if (!mStyleRuleMap) {
    1368           0 :     mStyleRuleMap = new ServoStyleRuleMap(this);
    1369           0 :     nsIDocument* doc = mPresContext->Document();
    1370           0 :     doc->AddObserver(mStyleRuleMap);
    1371           0 :     doc->CSSLoader()->AddObserver(mStyleRuleMap);
    1372             :   }
    1373           0 :   return mStyleRuleMap;
    1374             : }
    1375             : 
    1376             : bool
    1377           0 : ServoStyleSet::MightHaveAttributeDependency(const Element& aElement,
    1378             :                                             nsIAtom* aAttribute) const
    1379             : {
    1380             :   return Servo_StyleSet_MightHaveAttributeDependency(
    1381           0 :       mRawSet.get(), &aElement, aAttribute);
    1382             : }
    1383             : 
    1384             : bool
    1385           0 : ServoStyleSet::HasStateDependency(const Element& aElement,
    1386             :                                   EventStates aState) const
    1387             : {
    1388           0 :   return Servo_StyleSet_HasStateDependency(
    1389           0 :       mRawSet.get(), &aElement, aState.ServoValue());
    1390             : }
    1391             : 
    1392             : ServoStyleSet* ServoStyleSet::sInServoTraversal = nullptr;

Generated by: LCOV version 1.13