tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ServoStyleSet.cpp (60356B)


      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 "gfxUserFontSet.h"
     10 #include "mozilla/AttributeStyles.h"
     11 #include "mozilla/DeclarationBlock.h"
     12 #include "mozilla/DocumentStyleRootIterator.h"
     13 #include "mozilla/EffectCompositor.h"
     14 #include "mozilla/IntegerRange.h"
     15 #include "mozilla/Keyframe.h"
     16 #include "mozilla/LookAndFeel.h"
     17 #include "mozilla/MediaFeatureChange.h"
     18 #include "mozilla/PresShell.h"
     19 #include "mozilla/ProfilerLabels.h"
     20 #include "mozilla/RestyleManager.h"
     21 #include "mozilla/SMILAnimationController.h"
     22 #include "mozilla/ServoBindings.h"
     23 #include "mozilla/ServoStyleRuleMap.h"
     24 #include "mozilla/ServoStyleSetInlines.h"
     25 #include "mozilla/ServoTypes.h"
     26 #include "mozilla/StyleAnimationValue.h"
     27 #include "mozilla/css/Loader.h"
     28 #include "mozilla/dom/AnonymousContent.h"
     29 #include "mozilla/dom/CSSBinding.h"
     30 #include "mozilla/dom/CSSContainerRule.h"
     31 #include "mozilla/dom/CSSCounterStyleRule.h"
     32 #include "mozilla/dom/CSSCustomMediaRule.h"
     33 #include "mozilla/dom/CSSFontFaceRule.h"
     34 #include "mozilla/dom/CSSFontFeatureValuesRule.h"
     35 #include "mozilla/dom/CSSFontPaletteValuesRule.h"
     36 #include "mozilla/dom/CSSImportRule.h"
     37 #include "mozilla/dom/CSSKeyframeRule.h"
     38 #include "mozilla/dom/CSSKeyframesRule.h"
     39 #include "mozilla/dom/CSSLayerBlockRule.h"
     40 #include "mozilla/dom/CSSLayerStatementRule.h"
     41 #include "mozilla/dom/CSSMarginRule.h"
     42 #include "mozilla/dom/CSSMediaRule.h"
     43 #include "mozilla/dom/CSSMozDocumentRule.h"
     44 #include "mozilla/dom/CSSNamespaceRule.h"
     45 #include "mozilla/dom/CSSNestedDeclarations.h"
     46 #include "mozilla/dom/CSSPageRule.h"
     47 #include "mozilla/dom/CSSPositionTryRule.h"
     48 #include "mozilla/dom/CSSPropertyRule.h"
     49 #include "mozilla/dom/CSSScopeRule.h"
     50 #include "mozilla/dom/CSSStartingStyleRule.h"
     51 #include "mozilla/dom/CSSStyleRule.h"
     52 #include "mozilla/dom/CSSSupportsRule.h"
     53 #include "mozilla/dom/DocumentInlines.h"
     54 #include "mozilla/dom/Element.h"
     55 #include "mozilla/dom/ElementInlines.h"
     56 #include "mozilla/dom/FontFaceSet.h"
     57 #include "mozilla/dom/ViewTransition.h"
     58 #include "nsCSSAnonBoxes.h"
     59 #include "nsCSSFrameConstructor.h"
     60 #include "nsCSSPseudoElements.h"
     61 #include "nsDeviceContext.h"
     62 #include "nsIAnonymousContentCreator.h"
     63 #include "nsLayoutUtils.h"
     64 #include "nsPrintfCString.h"
     65 #include "nsWindowSizes.h"
     66 
     67 namespace mozilla {
     68 
     69 using namespace dom;
     70 
     71 #ifdef DEBUG
     72 bool ServoStyleSet::IsCurrentThreadInServoTraversal() {
     73  return sInServoTraversal && (NS_IsMainThread() || Servo_IsWorkerThread());
     74 }
     75 #endif
     76 
     77 // The definition of kOrigins relies on this.
     78 static_assert(static_cast<uint8_t>(StyleOrigin::UserAgent) ==
     79              static_cast<uint8_t>(OriginFlags::UserAgent));
     80 static_assert(static_cast<uint8_t>(StyleOrigin::User) ==
     81              static_cast<uint8_t>(OriginFlags::User));
     82 static_assert(static_cast<uint8_t>(StyleOrigin::Author) ==
     83              static_cast<uint8_t>(OriginFlags::Author));
     84 
     85 constexpr const StyleOrigin ServoStyleSet::kOrigins[];
     86 
     87 ServoStyleSet* sInServoTraversal = nullptr;
     88 
     89 // On construction, sets sInServoTraversal to the given ServoStyleSet.
     90 // On destruction, clears sInServoTraversal and calls RunPostTraversalTasks.
     91 class MOZ_RAII AutoSetInServoTraversal {
     92 public:
     93  explicit AutoSetInServoTraversal(ServoStyleSet* aSet) : mSet(aSet) {
     94    MOZ_ASSERT(!sInServoTraversal);
     95    MOZ_ASSERT(aSet);
     96    sInServoTraversal = aSet;
     97  }
     98 
     99  ~AutoSetInServoTraversal() {
    100    MOZ_ASSERT(sInServoTraversal);
    101    sInServoTraversal = nullptr;
    102    mSet->RunPostTraversalTasks();
    103  }
    104 
    105 private:
    106  ServoStyleSet* mSet;
    107 };
    108 
    109 // Sets up for one or more calls to Servo_TraverseSubtree.
    110 class MOZ_RAII AutoPrepareTraversal : public AutoSetInServoTraversal {
    111 public:
    112  explicit AutoPrepareTraversal(ServoStyleSet* aSet)
    113      : AutoSetInServoTraversal(aSet) {
    114    MOZ_ASSERT(!aSet->StylistNeedsUpdate());
    115  }
    116 };
    117 
    118 ServoStyleSet::ServoStyleSet(Document& aDocument) : mDocument(&aDocument) {
    119  PodArrayZero(mCachedAnonymousContentStyleIndexes);
    120  mRawData.reset(Servo_StyleSet_Init(&aDocument));
    121 }
    122 
    123 ServoStyleSet::~ServoStyleSet() {
    124  MOZ_ASSERT(!IsInServoTraversal());
    125  EnumerateStyleSheets([&](StyleSheet& aSheet) { aSheet.DropStyleSet(this); });
    126 }
    127 
    128 nsPresContext* ServoStyleSet::GetPresContext() {
    129  return mDocument->GetPresContext();
    130 }
    131 
    132 template <typename Functor>
    133 static void EnumerateShadowRoots(const Document& aDoc, const Functor& aCb) {
    134  const Document::ShadowRootSet& shadowRoots = aDoc.ComposedShadowRoots();
    135  for (ShadowRoot* root : shadowRoots) {
    136    MOZ_ASSERT(root);
    137    MOZ_DIAGNOSTIC_ASSERT(root->IsInComposedDoc());
    138    aCb(*root);
    139  }
    140 }
    141 
    142 void ServoStyleSet::ShellDetachedFromDocument() {
    143  ClearNonInheritingComputedStyles();
    144  mCachedAnonymousContentStyles.Clear();
    145  PodArrayZero(mCachedAnonymousContentStyleIndexes);
    146  mStyleRuleMap = nullptr;
    147 
    148  // Remove all our stylesheets...
    149  for (auto origin : kOrigins) {
    150    for (size_t count = SheetCount(origin); count--;) {
    151      RemoveStyleSheet(*SheetAt(origin, count));
    152    }
    153  }
    154 
    155  // And remove all the CascadeDatas from memory.
    156  UpdateStylistIfNeeded();
    157 
    158  // Also GC the ruletree if it got big now that the DOM no longer has
    159  // references to styles around anymore.
    160  MaybeGCRuleTree();
    161 }
    162 
    163 void ServoStyleSet::RecordShadowStyleChange(ShadowRoot& aShadowRoot) {
    164  // TODO(emilio): We could keep track of the actual shadow roots that need
    165  // their styles recomputed.
    166  SetStylistShadowDOMStyleSheetsDirty();
    167 
    168  // FIXME(emilio): This should be done using stylesheet invalidation instead.
    169  if (nsPresContext* pc = GetPresContext()) {
    170    pc->RestyleManager()->PostRestyleEvent(
    171        aShadowRoot.Host(), RestyleHint::RestyleSubtree(), nsChangeHint(0));
    172  }
    173 }
    174 
    175 void ServoStyleSet::InvalidateStyleForDocumentStateChanges(
    176    DocumentState aStatesChanged) {
    177  MOZ_ASSERT(mDocument);
    178  MOZ_ASSERT(!aStatesChanged.IsEmpty());
    179 
    180  nsPresContext* pc = GetPresContext();
    181  if (!pc) {
    182    return;
    183  }
    184 
    185  Element* root = mDocument->GetRootElement();
    186  if (!root) {
    187    return;
    188  }
    189 
    190  // TODO(emilio): It may be nicer to just invalidate stuff in a given subtree
    191  // for Shadow DOM. Consider just enumerating shadow roots instead and run
    192  // invalidation individually, passing mRawData for the UA / User sheets.
    193  AutoTArray<const StyleAuthorStyles*, 20> nonDocumentStyles;
    194 
    195  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
    196    if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
    197      nonDocumentStyles.AppendElement(authorStyles);
    198    }
    199  });
    200 
    201  Servo_InvalidateStyleForDocStateChanges(root, mRawData.get(),
    202                                          &nonDocumentStyles,
    203                                          aStatesChanged.GetInternalValue());
    204 }
    205 
    206 static const MediaFeatureChangeReason kMediaFeaturesAffectingDefaultStyle =
    207    // Zoom changes change the meaning of em units.
    208    MediaFeatureChangeReason::ZoomChange |
    209    // A resolution change changes the app-units-per-dev-pixels ratio, which
    210    // some structs (Border, Outline, Column) store for clamping. We should
    211    // arguably not do that, maybe doing it on layout directly, to try to avoid
    212    // relying on the pres context (bug 1418159).
    213    MediaFeatureChangeReason::ResolutionChange;
    214 
    215 RestyleHint ServoStyleSet::MediumFeaturesChanged(
    216    MediaFeatureChangeReason aReason) {
    217  AutoTArray<StyleAuthorStyles*, 20> nonDocumentStyles;
    218 
    219  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
    220    if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
    221      nonDocumentStyles.AppendElement(authorStyles);
    222    }
    223  });
    224 
    225  const bool mayAffectDefaultStyle =
    226      bool(aReason & kMediaFeaturesAffectingDefaultStyle);
    227  const MediumFeaturesChangedResult result =
    228      Servo_StyleSet_MediumFeaturesChanged(mRawData.get(), &nonDocumentStyles,
    229                                           mayAffectDefaultStyle);
    230 
    231  const bool viewportChanged =
    232      bool(aReason & MediaFeatureChangeReason::ViewportChange);
    233  if (viewportChanged) {
    234    InvalidateForViewportUnits(OnlyDynamic::No);
    235  }
    236 
    237  const bool rulesChanged =
    238      result.mAffectsDocumentRules || result.mAffectsNonDocumentRules;
    239 
    240  if (result.mAffectsDocumentRules) {
    241    SetStylistStyleSheetsDirty();
    242  }
    243 
    244  if (result.mAffectsNonDocumentRules) {
    245    SetStylistShadowDOMStyleSheetsDirty();
    246  }
    247 
    248  if (rulesChanged) {
    249    // TODO(emilio): This could be more granular.
    250    return RestyleHint::RestyleSubtree();
    251  }
    252 
    253  return RestyleHint{0};
    254 }
    255 
    256 MOZ_DEFINE_MALLOC_SIZE_OF(ServoStyleSetMallocSizeOf)
    257 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoStyleSetMallocEnclosingSizeOf)
    258 
    259 void ServoStyleSet::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
    260  MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
    261 
    262  aSizes.mLayoutStyleSetsOther += mallocSizeOf(this);
    263 
    264  if (mRawData) {
    265    aSizes.mLayoutStyleSetsOther += mallocSizeOf(mRawData.get());
    266    ServoStyleSetSizes sizes;
    267    // Measure mRawData. We use ServoStyleSetMallocSizeOf rather than
    268    // aMallocSizeOf to distinguish in DMD's output the memory measured within
    269    // Servo code.
    270    Servo_StyleSet_AddSizeOfExcludingThis(ServoStyleSetMallocSizeOf,
    271                                          ServoStyleSetMallocEnclosingSizeOf,
    272                                          &sizes, mRawData.get());
    273 
    274    // The StyleSet does not contain precomputed pseudos; they are in the UA
    275    // cache.
    276    MOZ_RELEASE_ASSERT(sizes.mPrecomputedPseudos == 0);
    277 
    278    aSizes.mLayoutStyleSetsStylistRuleTree += sizes.mRuleTree;
    279    aSizes.mLayoutStyleSetsStylistElementAndPseudosMaps +=
    280        sizes.mElementAndPseudosMaps;
    281    aSizes.mLayoutStyleSetsStylistInvalidationMap += sizes.mInvalidationMap;
    282    aSizes.mLayoutStyleSetsStylistRevalidationSelectors +=
    283        sizes.mRevalidationSelectors;
    284    aSizes.mLayoutStyleSetsStylistOther += sizes.mOther;
    285  }
    286 
    287  if (mStyleRuleMap) {
    288    aSizes.mLayoutStyleSetsOther +=
    289        mStyleRuleMap->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
    290  }
    291 
    292  // Measurement of the following members may be added later if DMD finds it is
    293  // worthwhile:
    294  // - mSheets
    295  // - mNonInheritingComputedStyles
    296  //
    297  // The following members are not measured:
    298  // - mDocument, because it a non-owning pointer
    299 }
    300 
    301 void ServoStyleSet::SetAuthorStyleDisabled(bool aStyleDisabled) {
    302  if (mAuthorStyleDisabled == aStyleDisabled) {
    303    return;
    304  }
    305 
    306  mAuthorStyleDisabled = aStyleDisabled;
    307  if (Element* root = mDocument->GetRootElement()) {
    308    if (nsPresContext* pc = GetPresContext()) {
    309      pc->RestyleManager()->PostRestyleEvent(
    310          root, RestyleHint::RestyleSubtree(), nsChangeHint(0));
    311    }
    312  }
    313  Servo_StyleSet_SetAuthorStyleDisabled(mRawData.get(), mAuthorStyleDisabled);
    314  // XXX Workaround for bug 1437785.
    315  SetStylistStyleSheetsDirty();
    316 }
    317 
    318 const ServoElementSnapshotTable& ServoStyleSet::Snapshots() {
    319  MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
    320  return GetPresContext()->RestyleManager()->Snapshots();
    321 }
    322 
    323 void ServoStyleSet::PreTraverseSync() {
    324  // Get the Document's root element to ensure that the cache is valid before
    325  // calling into the (potentially-parallel) Servo traversal, where a cache hit
    326  // is necessary to avoid a data race when updating the cache.
    327  (void)mDocument->GetRootElement();
    328 
    329  // FIXME(emilio): These two shouldn't be needed in theory, the call to the
    330  // same function in PresShell should do the work, but as it turns out we
    331  // ProcessPendingRestyles() twice, and runnables from frames just constructed
    332  // can end up doing editing stuff, which adds stylesheets etc...
    333  mDocument->FlushUserFontSet();
    334  UpdateStylistIfNeeded();
    335 
    336  mDocument->ResolveScheduledPresAttrs();
    337 
    338  mDocument->CacheAllKnownLangPrefs();
    339 
    340  if (gfxUserFontSet* userFontSet = mDocument->GetUserFontSet()) {
    341    nsPresContext* presContext = GetPresContext();
    342    MOZ_ASSERT(presContext,
    343               "For now, we don't call into here without a pres context");
    344 
    345    // Ensure that the @font-face data is not stale
    346    uint64_t generation = userFontSet->GetGeneration();
    347    if (generation != mUserFontSetUpdateGeneration) {
    348      mDocument->GetFonts()->CacheFontLoadability();
    349      presContext->UpdateFontCacheUserFonts(userFontSet);
    350      mUserFontSetUpdateGeneration = generation;
    351    }
    352  }
    353 
    354  MOZ_ASSERT(!StylistNeedsUpdate());
    355 }
    356 
    357 void ServoStyleSet::PreTraverse(ServoTraversalFlags aFlags, Element* aRoot) {
    358  PreTraverseSync();
    359 
    360  // Process animation stuff that we should avoid doing during the parallel
    361  // traversal.
    362  SMILAnimationController* smilController =
    363      mDocument->HasAnimationController() ? mDocument->GetAnimationController()
    364                                          : nullptr;
    365 
    366  MOZ_ASSERT(GetPresContext());
    367  if (aRoot) {
    368    GetPresContext()->EffectCompositor()->PreTraverseInSubtree(aFlags, aRoot);
    369    if (smilController) {
    370      smilController->PreTraverseInSubtree(aRoot);
    371    }
    372  } else {
    373    GetPresContext()->EffectCompositor()->PreTraverse(aFlags);
    374    if (smilController) {
    375      smilController->PreTraverse();
    376    }
    377  }
    378 }
    379 
    380 static inline already_AddRefed<ComputedStyle>
    381 ResolveStyleForTextOrFirstLetterContinuation(
    382    const StylePerDocumentStyleData* aRawData, ComputedStyle& aParent,
    383    PseudoStyleType aType) {
    384  MOZ_ASSERT(aType == PseudoStyleType::mozText ||
    385             aType == PseudoStyleType::firstLetterContinuation);
    386  auto inheritTarget = aType == PseudoStyleType::mozText
    387                           ? InheritTarget::Text
    388                           : InheritTarget::FirstLetterContinuation;
    389 
    390  RefPtr<ComputedStyle> style = aParent.GetCachedInheritingAnonBoxStyle(aType);
    391  if (!style) {
    392    style =
    393        Servo_ComputedValues_Inherit(aRawData, aType, &aParent, inheritTarget)
    394            .Consume();
    395    MOZ_ASSERT(style);
    396    aParent.SetCachedInheritedAnonBoxStyle(style);
    397  }
    398 
    399  return style.forget();
    400 }
    401 
    402 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleForText(
    403    nsIContent* aTextNode, ComputedStyle* aParentStyle) {
    404  MOZ_ASSERT(aTextNode && aTextNode->IsText());
    405  MOZ_ASSERT(aTextNode->GetParent());
    406  MOZ_ASSERT(aParentStyle);
    407 
    408  return ResolveStyleForTextOrFirstLetterContinuation(
    409      mRawData.get(), *aParentStyle, PseudoStyleType::mozText);
    410 }
    411 
    412 already_AddRefed<ComputedStyle>
    413 ServoStyleSet::ResolveStyleForFirstLetterContinuation(
    414    ComputedStyle* aParentStyle) {
    415  MOZ_ASSERT(aParentStyle);
    416 
    417  return ResolveStyleForTextOrFirstLetterContinuation(
    418      mRawData.get(), *aParentStyle, PseudoStyleType::firstLetterContinuation);
    419 }
    420 
    421 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleForPlaceholder() {
    422  RefPtr<ComputedStyle>& cache = mNonInheritingComputedStyles
    423      [nsCSSAnonBoxes::NonInheriting::oofPlaceholder];
    424  if (cache) {
    425    RefPtr<ComputedStyle> retval = cache;
    426    return retval.forget();
    427  }
    428 
    429  RefPtr<ComputedStyle> computedValues =
    430      Servo_ComputedValues_Inherit(mRawData.get(),
    431                                   PseudoStyleType::oofPlaceholder, nullptr,
    432                                   InheritTarget::PlaceholderFrame)
    433          .Consume();
    434  MOZ_ASSERT(computedValues);
    435 
    436  cache = computedValues;
    437  return computedValues.forget();
    438 }
    439 
    440 static inline bool LazyPseudoIsCacheable(PseudoStyleType aType,
    441                                         const Element& aOriginatingElement,
    442                                         ComputedStyle* aParentStyle) {
    443  return aParentStyle &&
    444         !nsCSSPseudoElements::IsEagerlyCascadedInServo(aType) &&
    445         aOriginatingElement.HasServoData() &&
    446         !Servo_Element_IsPrimaryStyleReusedViaRuleNode(&aOriginatingElement);
    447 }
    448 
    449 already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePseudoElementStyle(
    450    const Element& aOriginatingElement, PseudoStyleType aType,
    451    nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle,
    452    IsProbe aIsProbe) {
    453  // Runs from frame construction, this should have clean styles already, except
    454  // with non-lazy FC...
    455  UpdateStylistIfNeeded();
    456  MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
    457 
    458  // caching is done using `aType` only, therefore results would be wrong for
    459  // pseudos with functional parameters (e.g. `::highlight(foo)`).
    460  const bool cacheable =
    461      !aFunctionalPseudoParameter &&
    462      LazyPseudoIsCacheable(aType, aOriginatingElement, aParentStyle);
    463  RefPtr<ComputedStyle> style =
    464      cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
    465 
    466  const bool isProbe = aIsProbe == IsProbe::Yes;
    467 
    468  if (!style) {
    469    // FIXME(emilio): Why passing null for probing as the parent style?
    470    //
    471    // There are callers which do pass the wrong parent style and it would
    472    // assert (like ComputeSelectionStyle()). That's messy!
    473    style = Servo_ResolvePseudoStyle(
    474                &aOriginatingElement, aType, aFunctionalPseudoParameter,
    475                isProbe, isProbe ? nullptr : aParentStyle, mRawData.get())
    476                .Consume();
    477    if (!style) {
    478      MOZ_ASSERT(isProbe);
    479      return nullptr;
    480    }
    481    if (cacheable) {
    482      aParentStyle->SetCachedLazyPseudoStyle(style);
    483    }
    484  }
    485 
    486  MOZ_ASSERT(style);
    487 
    488  if (isProbe && !GeneratedContentPseudoExists(*aParentStyle, *style)) {
    489    return nullptr;
    490  }
    491 
    492  return style.forget();
    493 }
    494 
    495 already_AddRefed<ComputedStyle>
    496 ServoStyleSet::ResolveInheritingAnonymousBoxStyle(PseudoStyleType aType,
    497                                                  ComputedStyle* aParentStyle) {
    498  MOZ_ASSERT(PseudoStyle::IsInheritingAnonBox(aType));
    499  MOZ_ASSERT_IF(aParentStyle, !StylistNeedsUpdate());
    500 
    501  UpdateStylistIfNeeded();
    502 
    503  RefPtr<ComputedStyle> style = nullptr;
    504 
    505  if (aParentStyle) {
    506    style = aParentStyle->GetCachedInheritingAnonBoxStyle(aType);
    507  }
    508 
    509  if (!style) {
    510    style = Servo_ComputedValues_GetForAnonymousBox(aParentStyle, aType,
    511                                                    mRawData.get())
    512                .Consume();
    513    MOZ_ASSERT(style);
    514    if (aParentStyle) {
    515      aParentStyle->SetCachedInheritedAnonBoxStyle(style);
    516    }
    517  }
    518 
    519  return style.forget();
    520 }
    521 
    522 already_AddRefed<ComputedStyle>
    523 ServoStyleSet::ResolveNonInheritingAnonymousBoxStyle(PseudoStyleType aType) {
    524  MOZ_ASSERT(aType != PseudoStyleType::pageContent,
    525             "Use ResolvePageContentStyle for page content");
    526  MOZ_ASSERT(PseudoStyle::IsNonInheritingAnonBox(aType));
    527 
    528  nsCSSAnonBoxes::NonInheriting type =
    529      nsCSSAnonBoxes::NonInheritingTypeForPseudoType(aType);
    530  RefPtr<ComputedStyle>& cache = mNonInheritingComputedStyles[type];
    531  if (cache) {
    532    RefPtr<ComputedStyle> retval = cache;
    533    return retval.forget();
    534  }
    535 
    536  UpdateStylistIfNeeded();
    537 
    538  // We always want to skip parent-based display fixup here.  It never makes
    539  // sense for non-inheriting anonymous boxes.  (Static assertions in
    540  // nsCSSAnonBoxes.cpp ensure that all non-inheriting non-anonymous boxes
    541  // are indeed annotated as skipping this fixup.)
    542  MOZ_ASSERT(!PseudoStyle::IsNonInheritingAnonBox(PseudoStyleType::viewport),
    543             "viewport needs fixup to handle blockifying it");
    544 
    545  RefPtr<ComputedStyle> computedValues =
    546      Servo_ComputedValues_GetForAnonymousBox(nullptr, aType, mRawData.get())
    547          .Consume();
    548  MOZ_ASSERT(computedValues);
    549 
    550  cache = computedValues;
    551  return computedValues.forget();
    552 }
    553 
    554 already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePageContentStyle(
    555    const nsAtom* aPageName, const StylePagePseudoClassFlags& aPseudo) {
    556  // The empty atom is used to indicate no specified page name, and is not
    557  // usable as a page-rule selector. Changing this to null is a slight
    558  // optimization to avoid the Servo code from doing an unnecessary hashtable
    559  // lookup, and still use the style cache in this case.
    560  if (aPageName == nsGkAtoms::_empty) {
    561    aPageName = nullptr;
    562  }
    563  // Only use the cache when we are doing a lookup for page styles without a
    564  // page-name or any pseudo classes.
    565  const bool useCache = !aPageName && !aPseudo;
    566  RefPtr<ComputedStyle>& cache =
    567      mNonInheritingComputedStyles[nsCSSAnonBoxes::NonInheriting::pageContent];
    568  if (useCache && cache) {
    569    RefPtr<ComputedStyle> retval = cache;
    570    return retval.forget();
    571  }
    572 
    573  UpdateStylistIfNeeded();
    574 
    575  RefPtr<ComputedStyle> computedValues =
    576      Servo_ComputedValues_GetForPageContent(mRawData.get(), aPageName, aPseudo)
    577          .Consume();
    578  MOZ_ASSERT(computedValues);
    579 
    580  if (useCache) {
    581    cache = computedValues;
    582  }
    583  return computedValues.forget();
    584 }
    585 
    586 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveXULTreePseudoStyle(
    587    dom::Element* aParentElement, nsCSSAnonBoxPseudoStaticAtom* aPseudoTag,
    588    ComputedStyle* aParentStyle, const AtomArray& aInputWord) {
    589  MOZ_ASSERT(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag));
    590  MOZ_ASSERT(aParentStyle);
    591  NS_ASSERTION(!StylistNeedsUpdate(),
    592               "Stylesheets modified when resolving XUL tree pseudo");
    593 
    594  return Servo_ComputedValues_ResolveXULTreePseudoStyle(
    595             aParentElement, aPseudoTag, aParentStyle, &aInputWord,
    596             mRawData.get())
    597      .Consume();
    598 }
    599 
    600 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStartingStyle(
    601    dom::Element& aElement) {
    602  nsPresContext* pc = GetPresContext();
    603  if (!pc) {
    604    return nullptr;
    605  }
    606 
    607  return Servo_ResolveStartingStyle(
    608             &aElement, &pc->RestyleManager()->Snapshots(), mRawData.get())
    609      .Consume();
    610 }
    611 
    612 already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePositionTry(
    613    dom::Element& aElement, ComputedStyle& aStyle,
    614    const StylePositionTryFallbacksItem& aFallback) {
    615  return Servo_ComputedValues_GetForPositionTry(mRawData.get(), &aStyle,
    616                                                &aElement, &aFallback)
    617      .Consume();
    618 }
    619 
    620 // manage the set of style sheets in the style set
    621 void ServoStyleSet::AppendStyleSheet(StyleSheet& aSheet) {
    622  MOZ_ASSERT(aSheet.IsApplicable());
    623  MOZ_ASSERT(aSheet.RawContents(),
    624             "Raw sheet should be in place before insertion.");
    625 
    626  aSheet.AddStyleSet(this);
    627 
    628  // Maintain a mirrored list of sheets on the servo side.
    629  // Servo will remove aSheet from its original position as part of the call
    630  // to Servo_StyleSet_AppendStyleSheet.
    631  Servo_StyleSet_AppendStyleSheet(mRawData.get(), &aSheet);
    632  SetStylistStyleSheetsDirty();
    633 
    634  if (mStyleRuleMap) {
    635    mStyleRuleMap->SheetAdded(aSheet);
    636  }
    637 }
    638 
    639 void ServoStyleSet::RemoveStyleSheet(StyleSheet& aSheet) {
    640  aSheet.DropStyleSet(this);
    641 
    642  // Maintain a mirrored list of sheets on the servo side.
    643  Servo_StyleSet_RemoveStyleSheet(mRawData.get(), &aSheet);
    644  SetStylistStyleSheetsDirty();
    645 
    646  if (mStyleRuleMap) {
    647    mStyleRuleMap->SheetRemoved(aSheet);
    648  }
    649 }
    650 
    651 void ServoStyleSet::InsertStyleSheetBefore(StyleSheet& aNewSheet,
    652                                           StyleSheet& aReferenceSheet) {
    653  MOZ_ASSERT(aNewSheet.IsApplicable());
    654  MOZ_ASSERT(aReferenceSheet.IsApplicable());
    655  MOZ_ASSERT(&aNewSheet != &aReferenceSheet,
    656             "Can't place sheet before itself.");
    657  MOZ_ASSERT(aNewSheet.GetOrigin() == aReferenceSheet.GetOrigin(),
    658             "Sheets should be in the same origin");
    659  MOZ_ASSERT(aNewSheet.RawContents(),
    660             "Raw sheet should be in place before insertion.");
    661  MOZ_ASSERT(aReferenceSheet.RawContents(),
    662             "Reference sheet should have a raw sheet.");
    663 
    664  // Servo will remove aNewSheet from its original position as part of the
    665  // call to Servo_StyleSet_InsertStyleSheetBefore.
    666  aNewSheet.AddStyleSet(this);
    667 
    668  // Maintain a mirrored list of sheets on the servo side.
    669  Servo_StyleSet_InsertStyleSheetBefore(mRawData.get(), &aNewSheet,
    670                                        &aReferenceSheet);
    671  SetStylistStyleSheetsDirty();
    672 
    673  if (mStyleRuleMap) {
    674    mStyleRuleMap->SheetAdded(aNewSheet);
    675  }
    676 }
    677 
    678 size_t ServoStyleSet::SheetCount(Origin aOrigin) const {
    679  return Servo_StyleSet_GetSheetCount(mRawData.get(), aOrigin);
    680 }
    681 
    682 StyleSheet* ServoStyleSet::SheetAt(Origin aOrigin, size_t aIndex) const {
    683  return const_cast<StyleSheet*>(
    684      Servo_StyleSet_GetSheetAt(mRawData.get(), aOrigin, aIndex));
    685 }
    686 
    687 ServoStyleSet::PageSizeAndOrientation
    688 ServoStyleSet::GetDefaultPageSizeAndOrientation() {
    689  PageSizeAndOrientation retval;
    690  const RefPtr<ComputedStyle> style =
    691      ResolvePageContentStyle(nullptr, StylePagePseudoClassFlags::NONE);
    692  const StylePageSize& pageSize = style->StylePage()->mSize;
    693 
    694  if (pageSize.IsSize()) {
    695    const nscoord w = pageSize.AsSize().width.ToAppUnits();
    696    const nscoord h = pageSize.AsSize().height.ToAppUnits();
    697    // Ignoring sizes that include a zero width or height.
    698    // These are also ignored in nsPageFrame::ComputePageSize()
    699    // when calculating the scaling for a page size.
    700    // In bug 1807985, we might add similar handling for @page margin/size
    701    // combinations that produce a zero-sized page-content box.
    702    if (w > 0 && h > 0) {
    703      retval.size.emplace(w, h);
    704      if (w > h) {
    705        retval.orientation.emplace(StylePageSizeOrientation::Landscape);
    706      } else if (w < h) {
    707        retval.orientation.emplace(StylePageSizeOrientation::Portrait);
    708      }
    709    }
    710  } else if (pageSize.IsOrientation()) {
    711    retval.orientation.emplace(pageSize.AsOrientation());
    712  } else {
    713    MOZ_ASSERT(pageSize.IsAuto(), "Impossible page size");
    714  }
    715  return retval;
    716 }
    717 
    718 void ServoStyleSet::AppendAllNonDocumentAuthorSheets(
    719    nsTArray<StyleSheet*>& aArray) const {
    720  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
    721    for (auto index : IntegerRange(aShadowRoot.SheetCount())) {
    722      aArray.AppendElement(aShadowRoot.SheetAt(index));
    723    }
    724    aArray.AppendElements(aShadowRoot.AdoptedStyleSheets());
    725  });
    726 }
    727 
    728 void ServoStyleSet::AddDocStyleSheet(StyleSheet& aSheet) {
    729  MOZ_ASSERT(aSheet.IsApplicable());
    730  MOZ_ASSERT(aSheet.RawContents(),
    731             "Raw sheet should be in place by this point.");
    732 
    733  size_t index = mDocument->FindDocStyleSheetInsertionPoint(aSheet);
    734  aSheet.AddStyleSet(this);
    735 
    736  if (index < SheetCount(Origin::Author)) {
    737    // This case is insert before.
    738    StyleSheet* beforeSheet = SheetAt(Origin::Author, index);
    739    Servo_StyleSet_InsertStyleSheetBefore(mRawData.get(), &aSheet, beforeSheet);
    740  } else {
    741    Servo_StyleSet_AppendStyleSheet(mRawData.get(), &aSheet);
    742  }
    743  SetStylistStyleSheetsDirty();
    744 
    745  if (mStyleRuleMap) {
    746    mStyleRuleMap->SheetAdded(aSheet);
    747  }
    748 }
    749 
    750 bool ServoStyleSet::GeneratedContentPseudoExists(
    751    const ComputedStyle& aParentStyle, const ComputedStyle& aPseudoStyle) {
    752  auto type = aPseudoStyle.GetPseudoType();
    753  MOZ_ASSERT(type != PseudoStyleType::NotPseudo);
    754 
    755  if (type == PseudoStyleType::marker) {
    756    // ::marker only exist for list items (for now).
    757    if (!aParentStyle.StyleDisplay()->IsListItem()) {
    758      return false;
    759    }
    760    const auto& content = aPseudoStyle.StyleContent()->mContent;
    761    // ::marker does not exist if 'content' is 'none' (this trumps
    762    // any 'list-style-type' or 'list-style-image' values).
    763    if (content.IsNone()) {
    764      return false;
    765    }
    766    // ::marker only exist if we have 'content' or at least one of
    767    // 'list-style-type' or 'list-style-image'.
    768    if (aPseudoStyle.StyleList()->mListStyleType.IsNone() &&
    769        aPseudoStyle.StyleList()->mListStyleImage.IsNone() &&
    770        content.IsNormal()) {
    771      return false;
    772    }
    773  }
    774  // For ::before and ::after pseudo-elements, no 'content' items is
    775  // equivalent to not having the pseudo-element at all.
    776  if (type == PseudoStyleType::before || type == PseudoStyleType::after) {
    777    if (!aPseudoStyle.StyleContent()->mContent.IsItems()) {
    778      return false;
    779    }
    780    MOZ_ASSERT(!aPseudoStyle.StyleContent()->NonAltContentItems().IsEmpty(),
    781               "IsItems() implies we have at least one item");
    782  }
    783  if (type == PseudoStyleType::before || type == PseudoStyleType::after ||
    784      type == PseudoStyleType::marker || type == PseudoStyleType::backdrop) {
    785    // display:none is equivalent to not having a pseudo at all.
    786    if (aPseudoStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
    787      return false;
    788    }
    789  }
    790  return true;
    791 }
    792 
    793 bool ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags) {
    794  AUTO_PROFILER_LABEL_CATEGORY_PAIR_RELEVANT_FOR_JS(LAYOUT_StyleComputation);
    795  MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
    796 
    797  if (!mDocument->GetServoRestyleRoot()) {
    798    return false;
    799  }
    800 
    801  PreTraverse(aFlags);
    802  const SnapshotTable& snapshots = Snapshots();
    803 
    804  // Restyle the document from the root element and each of the document level
    805  // NAC subtree roots.
    806  bool postTraversalRequired = false;
    807 
    808  if (ShouldTraverseInParallel()) {
    809    aFlags |= ServoTraversalFlags::ParallelTraversal;
    810  }
    811 
    812  // Do the first traversal.
    813  DocumentStyleRootIterator iter(mDocument->GetServoRestyleRoot());
    814  while (Element* root = iter.GetNextStyleRoot()) {
    815    MOZ_ASSERT(MayTraverseFrom(root));
    816 
    817    Element* parent = root->GetFlattenedTreeParentElementForStyle();
    818    MOZ_ASSERT_IF(parent,
    819                  !parent->HasAnyOfFlags(Element::kAllServoDescendantBits));
    820 
    821    if (MOZ_UNLIKELY(!root->HasServoData()) && !parent) {
    822      StyleNewSubtree(root);
    823      postTraversalRequired = true;
    824      continue;
    825    }
    826 
    827    AutoPrepareTraversal guard(this);
    828 
    829    postTraversalRequired |=
    830        Servo_TraverseSubtree(root, mRawData.get(), &snapshots, aFlags) ||
    831        root->HasAnyOfFlags(Element::kAllServoDescendantBits |
    832                            NODE_NEEDS_FRAME);
    833 
    834    uint32_t existingBits = mDocument->GetServoRestyleRootDirtyBits();
    835    Element* newRoot = nullptr;
    836    while (parent && parent->HasDirtyDescendantsForServo()) {
    837      MOZ_ASSERT(root == mDocument->GetServoRestyleRoot(),
    838                 "Restyle root shouldn't have magically changed");
    839      // If any style invalidation was triggered in our siblings, then we may
    840      // need to post-traverse them, even if the root wasn't restyled after
    841      // all.
    842      // We need to propagate the existing bits to the ancestor.
    843      parent->SetFlags(existingBits);
    844      newRoot = parent;
    845      parent = parent->GetFlattenedTreeParentElementForStyle();
    846    }
    847 
    848    if (newRoot) {
    849      mDocument->SetServoRestyleRoot(
    850          newRoot, existingBits | ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO);
    851      postTraversalRequired = true;
    852    }
    853  }
    854 
    855  // If there are still animation restyles needed, trigger a second traversal to
    856  // update CSS animations or transitions' styles.
    857  //
    858  // Note that we need to check the style root again, because doing another
    859  // PreTraverse on the EffectCompositor might alter the style root. But we
    860  // don't need to worry about NAC, since document-level NAC shouldn't have
    861  // animations.
    862  //
    863  // We don't need to do this for SMIL since SMIL only updates its animation
    864  // values once at the begin of a tick. As a result, even if the previous
    865  // traversal caused, for example, the font-size to change, the SMIL style
    866  // won't be updated until the next tick anyway.
    867  if (GetPresContext()->EffectCompositor()->PreTraverse(aFlags)) {
    868    DocumentStyleRootIterator iter(mDocument->GetServoRestyleRoot());
    869    while (Element* root = iter.GetNextStyleRoot()) {
    870      AutoPrepareTraversal guard(this);
    871      postTraversalRequired |=
    872          Servo_TraverseSubtree(root, mRawData.get(), &snapshots, aFlags) ||
    873          root->HasAnyOfFlags(Element::kAllServoDescendantBits |
    874                              NODE_NEEDS_FRAME);
    875    }
    876  }
    877 
    878  return postTraversalRequired;
    879 }
    880 
    881 void ServoStyleSet::StyleNewSubtree(Element* aRoot) {
    882  MOZ_ASSERT(GetPresContext());
    883  MOZ_ASSERT(!aRoot->HasServoData());
    884  MOZ_ASSERT(aRoot->GetFlattenedTreeParentNodeForStyle(),
    885             "Not in the flat tree? Fishy!");
    886  PreTraverseSync();
    887  AutoPrepareTraversal guard(this);
    888 
    889  // Do the traversal. The snapshots will not be used.
    890  const SnapshotTable& snapshots = Snapshots();
    891  auto flags = ServoTraversalFlags::Empty;
    892  if (ShouldTraverseInParallel()) {
    893    flags |= ServoTraversalFlags::ParallelTraversal;
    894  }
    895 
    896  DebugOnly<bool> postTraversalRequired =
    897      Servo_TraverseSubtree(aRoot, mRawData.get(), &snapshots, flags);
    898  MOZ_ASSERT(!postTraversalRequired);
    899 
    900  // Annoyingly, the newly-styled content may have animations that need
    901  // starting, which requires traversing them again. Mark the elements
    902  // that need animation processing, then do a forgetful traversal to
    903  // update the styles and clear the animation bits.
    904  if (GetPresContext()->EffectCompositor()->PreTraverseInSubtree(flags,
    905                                                                 aRoot)) {
    906    postTraversalRequired =
    907        Servo_TraverseSubtree(aRoot, mRawData.get(), &snapshots,
    908                              ServoTraversalFlags::AnimationOnly |
    909                                  ServoTraversalFlags::FinalAnimationTraversal);
    910    MOZ_ASSERT(!postTraversalRequired);
    911  }
    912 }
    913 
    914 void ServoStyleSet::MarkOriginsDirty(OriginFlags aChangedOrigins) {
    915  SetStylistStyleSheetsDirty();
    916  Servo_StyleSet_NoteStyleSheetsChanged(mRawData.get(), aChangedOrigins);
    917 }
    918 
    919 void ServoStyleSet::SetStylistStyleSheetsDirty() {
    920  mStylistState |= StylistState::StyleSheetsDirty;
    921 
    922  // We need to invalidate cached style in getComputedStyle for undisplayed
    923  // elements, since we don't know if any of the style sheet change that we do
    924  // would affect undisplayed elements.
    925  //
    926  // We don't allow to call getComputedStyle in elements without a pres shell
    927  // yet, so it is fine if there's no pres context here.
    928  if (nsPresContext* presContext = GetPresContext()) {
    929    presContext->RestyleManager()->IncrementUndisplayedRestyleGeneration();
    930  }
    931 }
    932 
    933 void ServoStyleSet::SetStylistShadowDOMStyleSheetsDirty() {
    934  mStylistState |= StylistState::ShadowDOMStyleSheetsDirty;
    935  if (nsPresContext* presContext = GetPresContext()) {
    936    presContext->RestyleManager()->IncrementUndisplayedRestyleGeneration();
    937  }
    938 }
    939 
    940 static OriginFlags ToOriginFlags(StyleOrigin aOrigin) {
    941  switch (aOrigin) {
    942    case StyleOrigin::UserAgent:
    943      return OriginFlags::UserAgent;
    944    case StyleOrigin::User:
    945      return OriginFlags::User;
    946    default:
    947      MOZ_FALLTHROUGH_ASSERT("Unknown origin?");
    948    case StyleOrigin::Author:
    949      return OriginFlags::Author;
    950  }
    951 }
    952 
    953 void ServoStyleSet::ImportRuleLoaded(StyleSheet& aSheet) {
    954  if (mStyleRuleMap) {
    955    mStyleRuleMap->SheetAdded(aSheet);
    956  }
    957 
    958  // TODO: Should probably consider ancestor sheets too.
    959  if (!aSheet.IsApplicable()) {
    960    return;
    961  }
    962 
    963  // TODO(emilio): Could handle it better given we know it is an insertion, and
    964  // use the style invalidation machinery stuff that we do for regular sheet
    965  // insertions.
    966  MarkOriginsDirty(ToOriginFlags(aSheet.GetOrigin()));
    967 }
    968 
    969 void ServoStyleSet::RuleAdded(StyleSheet& aSheet, css::Rule& aRule) {
    970  if (mStyleRuleMap) {
    971    mStyleRuleMap->RuleAdded(aSheet, aRule);
    972  }
    973 
    974  if (!aSheet.IsApplicable() || aRule.IsIncompleteImportRule()) {
    975    return;
    976  }
    977 
    978  RuleChangedInternal(aSheet, aRule, StyleRuleChangeKind::Insertion);
    979 }
    980 
    981 void ServoStyleSet::RuleRemoved(StyleSheet& aSheet, css::Rule& aRule) {
    982  if (mStyleRuleMap) {
    983    mStyleRuleMap->RuleRemoved(aSheet, aRule);
    984  }
    985 
    986  if (!aSheet.IsApplicable()) {
    987    return;
    988  }
    989 
    990  RuleChangedInternal(aSheet, aRule, StyleRuleChangeKind::Removal);
    991 }
    992 
    993 static Maybe<StyleCssRuleRef> ToRuleRef(css::Rule& aRule) {
    994  switch (aRule.Type()) {
    995 #define CASE_FOR(constant_, type_)                          \
    996  case StyleCssRuleType::constant_:                         \
    997    return Some(StyleCssRuleRef::constant_(                 \
    998        static_cast<dom::CSS##type_##Rule&>(aRule).Raw())); \
    999    break;
   1000    CASE_FOR(CounterStyle, CounterStyle)
   1001    CASE_FOR(Style, Style)
   1002    CASE_FOR(Import, Import)
   1003    CASE_FOR(Media, Media)
   1004    CASE_FOR(Keyframes, Keyframes)
   1005    CASE_FOR(Margin, Margin)
   1006    CASE_FOR(CustomMedia, CustomMedia)
   1007    CASE_FOR(FontFeatureValues, FontFeatureValues)
   1008    CASE_FOR(FontPaletteValues, FontPaletteValues)
   1009    CASE_FOR(FontFace, FontFace)
   1010    CASE_FOR(Page, Page)
   1011    CASE_FOR(Property, Property)
   1012    CASE_FOR(Document, MozDocument)
   1013    CASE_FOR(Supports, Supports)
   1014    CASE_FOR(LayerBlock, LayerBlock)
   1015    CASE_FOR(LayerStatement, LayerStatement)
   1016    CASE_FOR(Container, Container)
   1017    CASE_FOR(Scope, Scope)
   1018    CASE_FOR(StartingStyle, StartingStyle)
   1019    CASE_FOR(PositionTry, PositionTry)
   1020    CASE_FOR(NestedDeclarations, NestedDeclarations)
   1021    CASE_FOR(Namespace, Namespace)
   1022 #undef CASE_FOR
   1023    case StyleCssRuleType::Keyframe:
   1024      // No equivalent.
   1025      break;
   1026  }
   1027  return Nothing{};
   1028 }
   1029 
   1030 void ServoStyleSet::RuleChangedInternal(StyleSheet& aSheet, css::Rule& aRule,
   1031                                        const StyleRuleChange& aChange) {
   1032  MOZ_ASSERT(aSheet.IsApplicable());
   1033  SetStylistStyleSheetsDirty();
   1034 
   1035  nsTArray<StyleCssRuleRef> ancestors;
   1036 
   1037  auto* parent = aRule.GetParentRule();
   1038  while (parent) {
   1039    if (const auto ref = ToRuleRef(*parent)) {
   1040      ancestors.AppendElement(*ref);
   1041    }
   1042    parent = parent->GetParentRule();
   1043  }
   1044 #define CASE_FOR(constant_, type_)                                        \
   1045  case StyleCssRuleType::constant_:                                       \
   1046    return Servo_StyleSet_##constant_##RuleChanged(                       \
   1047        mRawData.get(), static_cast<dom::CSS##type_##Rule&>(aRule).Raw(), \
   1048        &aSheet, aChange.mKind, &ancestors);
   1049  switch (aRule.Type()) {
   1050    CASE_FOR(CounterStyle, CounterStyle)
   1051    CASE_FOR(Style, Style)
   1052    CASE_FOR(Import, Import)
   1053    CASE_FOR(CustomMedia, CustomMedia)
   1054    CASE_FOR(Media, Media)
   1055    CASE_FOR(Keyframes, Keyframes)
   1056    CASE_FOR(Margin, Margin)
   1057    CASE_FOR(FontFeatureValues, FontFeatureValues)
   1058    CASE_FOR(FontPaletteValues, FontPaletteValues)
   1059    CASE_FOR(FontFace, FontFace)
   1060    CASE_FOR(Page, Page)
   1061    CASE_FOR(Property, Property)
   1062    CASE_FOR(Document, MozDocument)
   1063    CASE_FOR(Supports, Supports)
   1064    CASE_FOR(LayerBlock, LayerBlock)
   1065    CASE_FOR(LayerStatement, LayerStatement)
   1066    CASE_FOR(Container, Container)
   1067    CASE_FOR(Scope, Scope)
   1068    CASE_FOR(StartingStyle, StartingStyle)
   1069    CASE_FOR(PositionTry, PositionTry)
   1070    CASE_FOR(NestedDeclarations, NestedDeclarations)
   1071    // @namespace can only be inserted / removed when there are only other
   1072    // @namespace and @import rules, and can't be mutated.
   1073    case StyleCssRuleType::Namespace:
   1074      break;
   1075    case StyleCssRuleType::Keyframe:
   1076      // FIXME: We should probably just forward to the parent @keyframes rule? I
   1077      // think that'd do the right thing, but meanwhile...
   1078      return MarkOriginsDirty(ToOriginFlags(aSheet.GetOrigin()));
   1079  }
   1080 
   1081 #undef CASE_FOR
   1082 }
   1083 
   1084 void ServoStyleSet::RuleChanged(StyleSheet& aSheet, css::Rule* aRule,
   1085                                const StyleRuleChange& aChange) {
   1086  if (!aSheet.IsApplicable()) {
   1087    return;
   1088  }
   1089 
   1090  if (!aRule) {
   1091    MOZ_ASSERT(!aChange.mOldBlock);
   1092    MOZ_ASSERT(!aChange.mNewBlock);
   1093    // FIXME: This is done for StyleSheet.media attribute changes and such
   1094    MarkOriginsDirty(ToOriginFlags(aSheet.GetOrigin()));
   1095  } else {
   1096    if (mStyleRuleMap && aChange.mOldBlock != aChange.mNewBlock) {
   1097      mStyleRuleMap->RuleDeclarationsChanged(*aRule, aChange.mOldBlock->Raw(),
   1098                                             aChange.mNewBlock->Raw());
   1099    }
   1100    RuleChangedInternal(aSheet, *aRule, aChange);
   1101  }
   1102 }
   1103 
   1104 void ServoStyleSet::SheetCloned(StyleSheet& aSheet) {
   1105  mNeedsRestyleAfterEnsureUniqueInner = true;
   1106  if (mStyleRuleMap) {
   1107    mStyleRuleMap->SheetCloned(aSheet);
   1108  }
   1109 }
   1110 
   1111 #ifdef DEBUG
   1112 void ServoStyleSet::AssertTreeIsClean() {
   1113  DocumentStyleRootIterator iter(mDocument);
   1114  while (Element* root = iter.GetNextStyleRoot()) {
   1115    Servo_AssertTreeIsClean(root);
   1116  }
   1117 }
   1118 #endif
   1119 
   1120 bool ServoStyleSet::GetKeyframesForName(
   1121    const Element& aElement, const ComputedStyle& aStyle, nsAtom* aName,
   1122    const StyleComputedTimingFunction& aTimingFunction,
   1123    nsTArray<Keyframe>& aKeyframes) {
   1124  MOZ_ASSERT(!StylistNeedsUpdate());
   1125  if (Servo_StyleSet_GetKeyframesForName(mRawData.get(), &aElement, &aStyle,
   1126                                         aName, &aTimingFunction,
   1127                                         &aKeyframes)) {
   1128    return true;
   1129  }
   1130  if (StringBeginsWith(nsDependentAtomString(aName),
   1131                       ViewTransition::kGroupAnimPrefix)) {
   1132    if (auto* vt = mDocument->GetActiveViewTransition()) {
   1133      if (vt->GetGroupKeyframes(aName, aTimingFunction, aKeyframes)) {
   1134        return true;
   1135      }
   1136    }
   1137  }
   1138  return false;
   1139 }
   1140 
   1141 nsTArray<ComputedKeyframeValues> ServoStyleSet::GetComputedKeyframeValuesFor(
   1142    const nsTArray<Keyframe>& aKeyframes, Element* aElement,
   1143    const PseudoStyleRequest& aPseudo, const ComputedStyle* aStyle) {
   1144  nsTArray<ComputedKeyframeValues> result(aKeyframes.Length());
   1145 
   1146  // Construct each nsTArray<PropertyStyleAnimationValuePair> here.
   1147  result.AppendElements(aKeyframes.Length());
   1148 
   1149  // FIXME: Bug 1922095. For view transition pseudo-element, we should just
   1150  // use the pseudo-element here.
   1151  Servo_GetComputedKeyframeValues(&aKeyframes, aElement, aPseudo.mType, aStyle,
   1152                                  mRawData.get(), &result);
   1153  return result;
   1154 }
   1155 
   1156 void ServoStyleSet::GetAnimationValues(
   1157    StyleLockedDeclarationBlock* aDeclarations, Element* aElement,
   1158    const ComputedStyle* aComputedStyle,
   1159    nsTArray<RefPtr<StyleAnimationValue>>& aAnimationValues) {
   1160  // Servo_GetAnimationValues below won't handle ignoring existing element
   1161  // data for bfcached documents. (See comment in ResolveStyleLazily
   1162  // about these bfcache issues.)
   1163  Servo_GetAnimationValues(aDeclarations, aElement, aComputedStyle,
   1164                           mRawData.get(), &aAnimationValues);
   1165 }
   1166 
   1167 already_AddRefed<ComputedStyle> ServoStyleSet::GetBaseContextForElement(
   1168    Element* aElement, const ComputedStyle* aStyle) {
   1169  return Servo_StyleSet_GetBaseComputedValuesForElement(
   1170             mRawData.get(), aElement, aStyle, &Snapshots())
   1171      .Consume();
   1172 }
   1173 
   1174 already_AddRefed<StyleAnimationValue> ServoStyleSet::ComputeAnimationValue(
   1175    Element* aElement, StyleLockedDeclarationBlock* aDeclarations,
   1176    const ComputedStyle* aStyle) {
   1177  return Servo_AnimationValue_Compute(aElement, aDeclarations, aStyle,
   1178                                      mRawData.get())
   1179      .Consume();
   1180 }
   1181 
   1182 bool ServoStyleSet::UsesFontMetrics() const {
   1183  return Servo_StyleSet_UsesFontMetrics(mRawData.get());
   1184 }
   1185 
   1186 bool ServoStyleSet::UsesRootFontMetrics() const {
   1187  return Servo_StyleSet_UsesRootFontMetrics(mRawData.get());
   1188 }
   1189 
   1190 bool ServoStyleSet::EnsureUniqueInnerOnCSSSheets() {
   1191  using SheetOwner = Variant<ServoStyleSet*, ShadowRoot*>;
   1192 
   1193  AutoTArray<std::pair<StyleSheet*, SheetOwner>, 32> queue;
   1194  EnumerateStyleSheets([&](StyleSheet& aSheet) {
   1195    queue.AppendElement(std::make_pair(&aSheet, SheetOwner{this}));
   1196  });
   1197 
   1198  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
   1199    for (auto index : IntegerRange(aShadowRoot.SheetCount())) {
   1200      queue.AppendElement(
   1201          std::make_pair(aShadowRoot.SheetAt(index), SheetOwner{&aShadowRoot}));
   1202    }
   1203    for (const auto& adopted : aShadowRoot.AdoptedStyleSheets()) {
   1204      queue.AppendElement(
   1205          std::make_pair(adopted.get(), SheetOwner{&aShadowRoot}));
   1206    }
   1207  });
   1208 
   1209  while (!queue.IsEmpty()) {
   1210    auto [sheet, owner] = queue.PopLastElement();
   1211 
   1212    if (sheet->HasForcedUniqueInner()) {
   1213      // We already processed this sheet and its children.
   1214      // Normally we don't hit this but adopted stylesheets can have dupes so we
   1215      // can save some work here.
   1216      continue;
   1217    }
   1218 
   1219    // Only call EnsureUniqueInner for complete sheets. If we do call it on
   1220    // incomplete sheets, we'll cause problems when the sheet is actually
   1221    // loaded. We don't care about incomplete sheets here anyway, because this
   1222    // method is only invoked by nsPresContext::EnsureSafeToHandOutCSSRules.
   1223    // The CSSRule objects we are handing out won't contain any rules derived
   1224    // from incomplete sheets (because they aren't yet applied in styling).
   1225    if (sheet->IsComplete()) {
   1226      sheet->EnsureUniqueInner();
   1227    }
   1228 
   1229    // Enqueue all the sheet's children.
   1230    for (StyleSheet* child : sheet->ChildSheets()) {
   1231      queue.AppendElement(std::make_pair(child, owner));
   1232    }
   1233  }
   1234 
   1235  if (mNeedsRestyleAfterEnsureUniqueInner) {
   1236    // TODO(emilio): We could make this faster if needed tracking the specific
   1237    // origins and sheets that have been cloned. But the only caller of this
   1238    // doesn't seem to really care about perf.
   1239    MarkOriginsDirty(OriginFlags::All);
   1240    ForceDirtyAllShadowStyles();
   1241  }
   1242  bool res = mNeedsRestyleAfterEnsureUniqueInner;
   1243  mNeedsRestyleAfterEnsureUniqueInner = false;
   1244  return res;
   1245 }
   1246 
   1247 void ServoStyleSet::ClearCachedStyleData() {
   1248  ClearNonInheritingComputedStyles();
   1249  Servo_StyleSet_RebuildCachedData(mRawData.get());
   1250  mCachedAnonymousContentStyles.Clear();
   1251  PodArrayZero(mCachedAnonymousContentStyleIndexes);
   1252 }
   1253 
   1254 void ServoStyleSet::ForceDirtyAllShadowStyles() {
   1255  bool anyShadow = false;
   1256  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
   1257    if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
   1258      anyShadow = true;
   1259      Servo_AuthorStyles_ForceDirty(authorStyles);
   1260    }
   1261  });
   1262  if (anyShadow) {
   1263    SetStylistShadowDOMStyleSheetsDirty();
   1264  }
   1265 }
   1266 
   1267 void ServoStyleSet::CompatibilityModeChanged() {
   1268  Servo_StyleSet_CompatModeChanged(mRawData.get());
   1269  SetStylistStyleSheetsDirty();
   1270  ForceDirtyAllShadowStyles();
   1271 }
   1272 
   1273 void ServoStyleSet::ClearNonInheritingComputedStyles() {
   1274  for (RefPtr<ComputedStyle>& ptr : mNonInheritingComputedStyles) {
   1275    ptr = nullptr;
   1276  }
   1277 }
   1278 
   1279 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveStyleLazily(
   1280    const Element& aElement, const PseudoStyleRequest& aPseudoRequest,
   1281    StyleRuleInclusion aRuleInclusion) {
   1282  PreTraverseSync();
   1283  MOZ_ASSERT(!StylistNeedsUpdate());
   1284 
   1285  AutoSetInServoTraversal guard(this);
   1286 
   1287  /**
   1288   * NB: This is needed because we process animations and transitions on the
   1289   * pseudo-elements themselves, not on the parent's EagerPseudoStyles.
   1290   *
   1291   * That means that that style doesn't account for animations, and we can't do
   1292   * that easily from the traversal without doing wasted work.
   1293   *
   1294   * As such, we just lie here a bit, which is the entrypoint of
   1295   * getComputedStyle, the only API where this can be observed, to look at the
   1296   * style of the pseudo-element if it exists instead.
   1297   */
   1298  const Element* elementForStyleResolution = &aElement;
   1299  PseudoStyleType pseudoTypeForStyleResolution = aPseudoRequest.mType;
   1300  if (auto* pseudo = aElement.GetPseudoElement(aPseudoRequest)) {
   1301    elementForStyleResolution = pseudo;
   1302    pseudoTypeForStyleResolution = PseudoStyleType::NotPseudo;
   1303  }
   1304 
   1305  nsPresContext* pc = GetPresContext();
   1306  MOZ_ASSERT(pc, "For now, no style resolution without a pres context");
   1307  auto* restyleManager = pc->RestyleManager();
   1308  const bool canUseCache = aRuleInclusion == StyleRuleInclusion::All &&
   1309                           aElement.OwnerDoc() == mDocument &&
   1310                           pc->PresShell()->DidInitialize();
   1311  return Servo_ResolveStyleLazily(
   1312             elementForStyleResolution, pseudoTypeForStyleResolution,
   1313             aPseudoRequest.mIdentifier.get(), aRuleInclusion,
   1314             &restyleManager->Snapshots(),
   1315             restyleManager->GetUndisplayedRestyleGeneration(), canUseCache,
   1316             mRawData.get())
   1317      .Consume();
   1318 }
   1319 
   1320 void ServoStyleSet::AppendFontFaceRules(
   1321    nsTArray<nsFontFaceRuleContainer>& aArray) {
   1322  // TODO(emilio): Can we make this so this asserts instead?
   1323  UpdateStylistIfNeeded();
   1324  Servo_StyleSet_GetFontFaceRules(mRawData.get(), &aArray);
   1325 }
   1326 
   1327 const StyleLockedCounterStyleRule* ServoStyleSet::CounterStyleRuleForName(
   1328    nsAtom* aName) {
   1329  MOZ_ASSERT(!StylistNeedsUpdate());
   1330  return Servo_StyleSet_GetCounterStyleRule(mRawData.get(), aName);
   1331 }
   1332 
   1333 already_AddRefed<gfxFontFeatureValueSet>
   1334 ServoStyleSet::BuildFontFeatureValueSet() {
   1335  MOZ_ASSERT(!StylistNeedsUpdate());
   1336  RefPtr<gfxFontFeatureValueSet> set =
   1337      Servo_StyleSet_BuildFontFeatureValueSet(mRawData.get());
   1338  return set.forget();
   1339 }
   1340 
   1341 already_AddRefed<gfx::FontPaletteValueSet>
   1342 ServoStyleSet::BuildFontPaletteValueSet() {
   1343  MOZ_ASSERT(!StylistNeedsUpdate());
   1344  RefPtr<gfx::FontPaletteValueSet> set =
   1345      Servo_StyleSet_BuildFontPaletteValueSet(mRawData.get());
   1346  return set.forget();
   1347 }
   1348 
   1349 already_AddRefed<ComputedStyle> ServoStyleSet::ResolveForDeclarations(
   1350    const ComputedStyle* aParentOrNull,
   1351    const StyleLockedDeclarationBlock* aDeclarations) {
   1352  // No need to update the stylist, we're only cascading aDeclarations.
   1353  return Servo_StyleSet_ResolveForDeclarations(mRawData.get(), aParentOrNull,
   1354                                               aDeclarations)
   1355      .Consume();
   1356 }
   1357 
   1358 void ServoStyleSet::UpdateStylist() {
   1359  AUTO_PROFILER_LABEL_RELEVANT_FOR_JS("Update stylesheet information", LAYOUT);
   1360  MOZ_ASSERT(StylistNeedsUpdate());
   1361 
   1362  AutoTArray<StyleAuthorStyles*, 20> nonDocumentStyles;
   1363  Element* root = mDocument->GetRootElement();
   1364  const ServoElementSnapshotTable* snapshots = nullptr;
   1365  if (nsPresContext* pc = GetPresContext()) {
   1366    snapshots = &pc->RestyleManager()->Snapshots();
   1367  }
   1368 
   1369  if (MOZ_UNLIKELY(mStylistState & StylistState::ShadowDOMStyleSheetsDirty)) {
   1370    EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
   1371      if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
   1372        nonDocumentStyles.AppendElement(authorStyles);
   1373      }
   1374    });
   1375  }
   1376  Servo_StyleSet_FlushStyleSheets(mRawData.get(), root, snapshots,
   1377                                  &nonDocumentStyles);
   1378  mStylistState = StylistState::NotDirty;
   1379 }
   1380 
   1381 void ServoStyleSet::MaybeGCRuleTree() {
   1382  MOZ_ASSERT(NS_IsMainThread());
   1383  Servo_MaybeGCRuleTree(mRawData.get());
   1384 }
   1385 
   1386 /* static */
   1387 bool ServoStyleSet::MayTraverseFrom(const Element* aElement) {
   1388  MOZ_ASSERT(aElement->IsInComposedDoc());
   1389  nsINode* parent = aElement->GetFlattenedTreeParentNodeForStyle();
   1390  if (!parent) {
   1391    return false;
   1392  }
   1393 
   1394  if (!parent->IsElement()) {
   1395    MOZ_ASSERT(parent->IsDocument());
   1396    return true;
   1397  }
   1398 
   1399  if (!parent->AsElement()->HasServoData()) {
   1400    return false;
   1401  }
   1402 
   1403  return !Servo_Element_IsDisplayNone(parent->AsElement());
   1404 }
   1405 
   1406 bool ServoStyleSet::ShouldTraverseInParallel() const {
   1407  MOZ_ASSERT(mDocument->GetPresShell(), "Styling a document without a shell?");
   1408  if (!mDocument->GetPresShell()->IsActive()) {
   1409    return false;
   1410  }
   1411  if (profiler_feature_active(ProfilerFeature::SequentialStyle)) {
   1412    return false;
   1413  }
   1414  return true;
   1415 }
   1416 
   1417 void ServoStyleSet::RunPostTraversalTasks() {
   1418  MOZ_ASSERT(!IsInServoTraversal());
   1419 
   1420  if (mPostTraversalTasks.IsEmpty()) {
   1421    return;
   1422  }
   1423 
   1424  nsTArray<PostTraversalTask> tasks = std::move(mPostTraversalTasks);
   1425 
   1426  for (auto& task : tasks) {
   1427    task.Run();
   1428  }
   1429 }
   1430 
   1431 ServoStyleRuleMap* ServoStyleSet::StyleRuleMap() {
   1432  if (!mStyleRuleMap) {
   1433    mStyleRuleMap = MakeUnique<ServoStyleRuleMap>();
   1434  }
   1435  mStyleRuleMap->EnsureTable(*this);
   1436  return mStyleRuleMap.get();
   1437 }
   1438 
   1439 bool ServoStyleSet::MightHaveAttributeDependency(const Element& aElement,
   1440                                                 nsAtom* aAttribute) const {
   1441  return Servo_StyleSet_MightHaveAttributeDependency(mRawData.get(), &aElement,
   1442                                                     aAttribute);
   1443 }
   1444 
   1445 bool ServoStyleSet::MightHaveNthOfIDDependency(const Element& aElement,
   1446                                               nsAtom* aOldID,
   1447                                               nsAtom* aNewID) const {
   1448  return Servo_StyleSet_MightHaveNthOfIDDependency(mRawData.get(), &aElement,
   1449                                                   aOldID, aNewID);
   1450 }
   1451 
   1452 bool ServoStyleSet::MightHaveNthOfClassDependency(const Element& aElement) {
   1453  return Servo_StyleSet_MightHaveNthOfClassDependency(mRawData.get(), &aElement,
   1454                                                      &Snapshots());
   1455 }
   1456 
   1457 void ServoStyleSet::MaybeInvalidateRelativeSelectorIDDependency(
   1458    const Element& aElement, nsAtom* aOldID, nsAtom* aNewID,
   1459    const ServoElementSnapshotTable& aSnapshots) {
   1460  Servo_StyleSet_MaybeInvalidateRelativeSelectorIDDependency(
   1461      mRawData.get(), &aElement, aOldID, aNewID, &aSnapshots);
   1462 }
   1463 
   1464 void ServoStyleSet::MaybeInvalidateRelativeSelectorClassDependency(
   1465    const Element& aElement, const ServoElementSnapshotTable& aSnapshots) {
   1466  Servo_StyleSet_MaybeInvalidateRelativeSelectorClassDependency(
   1467      mRawData.get(), &aElement, &aSnapshots);
   1468 }
   1469 
   1470 void ServoStyleSet::MaybeInvalidateRelativeSelectorCustomStateDependency(
   1471    const Element& aElement, nsAtom* state,
   1472    const ServoElementSnapshotTable& aSnapshots) {
   1473  Servo_StyleSet_MaybeInvalidateRelativeSelectorCustomStateDependency(
   1474      mRawData.get(), &aElement, state, &aSnapshots);
   1475 }
   1476 
   1477 void ServoStyleSet::MaybeInvalidateRelativeSelectorAttributeDependency(
   1478    const Element& aElement, nsAtom* aAttribute,
   1479    const ServoElementSnapshotTable& aSnapshots) {
   1480  Servo_StyleSet_MaybeInvalidateRelativeSelectorAttributeDependency(
   1481      mRawData.get(), &aElement, aAttribute, &aSnapshots);
   1482 }
   1483 
   1484 void ServoStyleSet::MaybeInvalidateRelativeSelectorStateDependency(
   1485    const Element& aElement, ElementState aState,
   1486    const ServoElementSnapshotTable& aSnapshots) {
   1487  Servo_StyleSet_MaybeInvalidateRelativeSelectorStateDependency(
   1488      mRawData.get(), &aElement, aState.GetInternalValue(), &aSnapshots);
   1489 }
   1490 
   1491 void ServoStyleSet::MaybeInvalidateRelativeSelectorForEmptyDependency(
   1492    const Element& aElement) {
   1493  Servo_StyleSet_MaybeInvalidateRelativeSelectorEmptyDependency(mRawData.get(),
   1494                                                                &aElement);
   1495 }
   1496 
   1497 void ServoStyleSet::MaybeInvalidateRelativeSelectorForNthEdgeDependency(
   1498    const Element& aElement,
   1499    StyleRelativeSelectorNthEdgeInvalidateFor aInvalidateFor) {
   1500  Servo_StyleSet_MaybeInvalidateRelativeSelectorNthEdgeDependency(
   1501      mRawData.get(), &aElement, aInvalidateFor);
   1502 }
   1503 
   1504 void ServoStyleSet::MaybeInvalidateRelativeSelectorForNthDependencyFromSibling(
   1505    const Element* aFromSibling, bool aForceRestyleSiblings) {
   1506  if (!aFromSibling) {
   1507    return;
   1508  }
   1509  Servo_StyleSet_MaybeInvalidateRelativeSelectorNthDependencyFromSibling(
   1510      mRawData.get(), aFromSibling, aForceRestyleSiblings);
   1511 }
   1512 
   1513 void ServoStyleSet::MaybeInvalidateForElementInsertion(
   1514    const Element& aElement) {
   1515  Servo_StyleSet_MaybeInvalidateRelativeSelectorForInsertion(mRawData.get(),
   1516                                                             &aElement);
   1517 }
   1518 
   1519 void ServoStyleSet::MaybeInvalidateForElementAppend(
   1520    const nsIContent& aFirstContent) {
   1521  Servo_StyleSet_MaybeInvalidateRelativeSelectorForAppend(mRawData.get(),
   1522                                                          &aFirstContent);
   1523 }
   1524 
   1525 void ServoStyleSet::MaybeInvalidateForElementRemove(const Element& aElement) {
   1526  Servo_StyleSet_MaybeInvalidateRelativeSelectorForRemoval(mRawData.get(),
   1527                                                           &aElement);
   1528 }
   1529 
   1530 bool ServoStyleSet::MightHaveNthOfAttributeDependency(
   1531    const Element& aElement, nsAtom* aAttribute) const {
   1532  return Servo_StyleSet_MightHaveNthOfAttributeDependency(
   1533      mRawData.get(), &aElement, aAttribute);
   1534 }
   1535 
   1536 bool ServoStyleSet::HasStateDependency(const Element& aElement,
   1537                                       dom::ElementState aState) const {
   1538  return Servo_StyleSet_HasStateDependency(mRawData.get(), &aElement,
   1539                                           aState.GetInternalValue());
   1540 }
   1541 
   1542 bool ServoStyleSet::HasNthOfStateDependency(const Element& aElement,
   1543                                            dom::ElementState aState) const {
   1544  return Servo_StyleSet_HasNthOfStateDependency(mRawData.get(), &aElement,
   1545                                                aState.GetInternalValue());
   1546 }
   1547 
   1548 bool ServoStyleSet::HasNthOfCustomStateDependency(const Element& aElement,
   1549                                                  nsAtom* aState) const {
   1550  return Servo_StyleSet_HasNthOfCustomStateDependency(mRawData.get(), &aElement,
   1551                                                      aState);
   1552 }
   1553 
   1554 void ServoStyleSet::RestyleSiblingsForNthOf(const Element& aElement,
   1555                                            uint32_t aFlags) const {
   1556  Servo_StyleSet_RestyleSiblingsForNthOf(&aElement, aFlags);
   1557 }
   1558 
   1559 bool ServoStyleSet::HasDocumentStateDependency(
   1560    dom::DocumentState aState) const {
   1561  return Servo_StyleSet_HasDocumentStateDependency(mRawData.get(),
   1562                                                   aState.GetInternalValue());
   1563 }
   1564 
   1565 already_AddRefed<ComputedStyle> ServoStyleSet::ReparentComputedStyle(
   1566    ComputedStyle* aComputedStyle, ComputedStyle* aNewParent,
   1567    ComputedStyle* aNewLayoutParent, Element* aElement) {
   1568  return Servo_ReparentStyle(aComputedStyle, aNewParent, aNewLayoutParent,
   1569                             aElement, mRawData.get())
   1570      .Consume();
   1571 }
   1572 
   1573 void ServoStyleSet::InvalidateForViewportUnits(OnlyDynamic aOnlyDynamic) {
   1574  dom::Element* root = mDocument->GetRootElement();
   1575  if (!root) {
   1576    return;
   1577  }
   1578 
   1579  Servo_InvalidateForViewportUnits(mRawData.get(), root,
   1580                                   aOnlyDynamic == OnlyDynamic::Yes);
   1581 }
   1582 
   1583 void ServoStyleSet::RegisterProperty(const PropertyDefinition& aDefinition,
   1584                                     ErrorResult& aRv) {
   1585  using Result = StyleRegisterCustomPropertyResult;
   1586  auto result = Servo_RegisterCustomProperty(
   1587      RawData(), mDocument->DefaultStyleAttrURLData(), &aDefinition.mName,
   1588      &aDefinition.mSyntax, aDefinition.mInherits,
   1589      aDefinition.mInitialValue.WasPassed() ? &aDefinition.mInitialValue.Value()
   1590                                            : nullptr);
   1591  switch (result) {
   1592    case Result::SuccessfullyRegistered:
   1593      if (Element* root = mDocument->GetRootElement()) {
   1594        if (nsPresContext* pc = GetPresContext()) {
   1595          pc->RestyleManager()->PostRestyleEvent(
   1596              root, RestyleHint::RecascadeSubtree(), nsChangeHint(0));
   1597        }
   1598      }
   1599      mDocument->PostCustomPropertyRegistered(aDefinition);
   1600      break;
   1601    case Result::InvalidName:
   1602      return aRv.ThrowSyntaxError("Invalid name");
   1603    case Result::InvalidSyntax:
   1604      return aRv.ThrowSyntaxError("Invalid syntax descriptor");
   1605    case Result::InvalidInitialValue:
   1606      return aRv.ThrowSyntaxError("Invalid initial value syntax");
   1607    case Result::NoInitialValue:
   1608      return aRv.ThrowSyntaxError(
   1609          "Initial value is required when syntax is not universal");
   1610    case Result::InitialValueNotComputationallyIndependent:
   1611      return aRv.ThrowSyntaxError(
   1612          "Initial value is required when syntax is not universal");
   1613    case Result::AlreadyRegistered:
   1614      return aRv.ThrowInvalidModificationError("Property already registered");
   1615  }
   1616 }
   1617 
   1618 NS_IMPL_ISUPPORTS(UACacheReporter, nsIMemoryReporter)
   1619 
   1620 MOZ_DEFINE_MALLOC_SIZE_OF(ServoUACacheMallocSizeOf)
   1621 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoUACacheMallocEnclosingSizeOf)
   1622 
   1623 NS_IMETHODIMP
   1624 UACacheReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
   1625                                nsISupports* aData, bool aAnonymize) {
   1626  ServoStyleSetSizes sizes;
   1627  Servo_UACache_AddSizeOf(ServoUACacheMallocSizeOf,
   1628                          ServoUACacheMallocEnclosingSizeOf, &sizes);
   1629 
   1630 #define REPORT(_path, _amount, _desc)                                     \
   1631  do {                                                                    \
   1632    size_t __amount = _amount; /* evaluate _amount only once */           \
   1633    if (__amount > 0) {                                                   \
   1634      MOZ_COLLECT_REPORT(_path, KIND_HEAP, UNITS_BYTES, __amount, _desc); \
   1635    }                                                                     \
   1636  } while (0)
   1637 
   1638  // The UA cache does not contain the rule tree; that's in the StyleSet.
   1639  MOZ_RELEASE_ASSERT(sizes.mRuleTree == 0);
   1640 
   1641  REPORT("explicit/layout/servo-ua-cache/precomputed-pseudos",
   1642         sizes.mPrecomputedPseudos,
   1643         "Memory used by precomputed pseudo-element declarations within the "
   1644         "UA cache.");
   1645 
   1646  REPORT("explicit/layout/servo-ua-cache/element-and-pseudos-maps",
   1647         sizes.mElementAndPseudosMaps,
   1648         "Memory used by element and pseudos maps within the UA cache.");
   1649 
   1650  REPORT("explicit/layout/servo-ua-cache/invalidation-map",
   1651         sizes.mInvalidationMap,
   1652         "Memory used by invalidation maps within the UA cache.");
   1653 
   1654  REPORT("explicit/layout/servo-ua-cache/revalidation-selectors",
   1655         sizes.mRevalidationSelectors,
   1656         "Memory used by selectors for cache revalidation within the UA "
   1657         "cache.");
   1658 
   1659  REPORT("explicit/layout/servo-ua-cache/other", sizes.mOther,
   1660         "Memory used by other data within the UA cache");
   1661 
   1662  return NS_OK;
   1663 }
   1664 
   1665 }  // namespace mozilla