tor-browser

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

ServoStyleSet.h (27278B)


      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 #ifndef mozilla_ServoStyleSet_h
      8 #define mozilla_ServoStyleSet_h
      9 
     10 #include "MainThreadUtils.h"
     11 #include "mozilla/AlreadyAddRefed.h"
     12 #include "mozilla/AnonymousContentKey.h"
     13 #include "mozilla/AtomArray.h"
     14 #include "mozilla/EnumeratedArray.h"
     15 #include "mozilla/Maybe.h"
     16 #include "mozilla/PostTraversalTask.h"
     17 #include "mozilla/ServoBindingTypes.h"
     18 #include "mozilla/ServoUtils.h"
     19 #include "mozilla/UniquePtr.h"
     20 #include "mozilla/dom/RustTypes.h"
     21 #include "nsAtom.h"
     22 #include "nsCSSAnonBoxes.h"
     23 #include "nsCSSPseudoElements.h"
     24 #include "nsChangeHint.h"
     25 #include "nsCoord.h"
     26 #include "nsIMemoryReporter.h"
     27 #include "nsSize.h"
     28 #include "nsTArray.h"
     29 
     30 namespace mozilla {
     31 enum class MediaFeatureChangeReason : uint8_t;
     32 enum class StylePageSizeOrientation : uint8_t;
     33 enum class StyleRuleChangeKind : uint32_t;
     34 enum class StyleRelativeSelectorNthEdgeInvalidateFor : uint8_t;
     35 union StylePositionTryFallbacksItem;
     36 struct StyleRuleChange;
     37 
     38 class ErrorResult;
     39 
     40 template <typename Integer, typename Number, typename LinearStops>
     41 struct StyleTimingFunction;
     42 struct StylePagePseudoClassFlags;
     43 struct StylePiecewiseLinearFunction;
     44 using StyleComputedTimingFunction =
     45    StyleTimingFunction<int32_t, float, StylePiecewiseLinearFunction>;
     46 
     47 namespace css {
     48 class Rule;
     49 }  // namespace css
     50 namespace dom {
     51 class CSSImportRule;
     52 class Element;
     53 class ShadowRoot;
     54 struct PropertyDefinition;
     55 }  // namespace dom
     56 namespace gfx {
     57 class FontPaletteValueSet;
     58 }  // namespace gfx
     59 class StyleSheet;
     60 struct Keyframe;
     61 class ServoElementSnapshotTable;
     62 class ComputedStyle;
     63 class ServoStyleRuleMap;
     64 class StyleSheet;
     65 }  // namespace mozilla
     66 class gfxFontFeatureValueSet;
     67 class nsIContent;
     68 
     69 class nsPresContext;
     70 class nsWindowSizes;
     71 struct TreeMatchContext;
     72 
     73 namespace mozilla {
     74 
     75 // A few flags used to track which kind of stylist state we may need to
     76 // update.
     77 enum class StylistState : uint8_t {
     78  // The stylist is not dirty, we should do nothing.
     79  NotDirty = 0,
     80 
     81  // The style sheets have changed, so we need to update the style data.
     82  StyleSheetsDirty = 1 << 0,
     83 
     84  // Some of the style sheets of the shadow trees in the document have
     85  // changed.
     86  ShadowDOMStyleSheetsDirty = 1 << 1,
     87 };
     88 
     89 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StylistState)
     90 
     91 enum class StyleOrigin : uint8_t;
     92 
     93 // Bitfield type to represent Servo stylesheet origins.
     94 enum class OriginFlags : uint8_t {
     95  UserAgent = 0x01,
     96  User = 0x02,
     97  Author = 0x04,
     98  All = 0x07,
     99 };
    100 
    101 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OriginFlags)
    102 
    103 /**
    104 * The set of style sheets that apply to a document, backed by a Servo
    105 * Stylist.  A ServoStyleSet contains StyleSheets.
    106 */
    107 class ServoStyleSet {
    108  friend class RestyleManager;
    109  using SnapshotTable = ServoElementSnapshotTable;
    110  using Origin = StyleOrigin;
    111 
    112  // We assert that these match the Servo ones in the definition of this array.
    113  static constexpr Origin kOrigins[] = {
    114      Origin(static_cast<uint8_t>(OriginFlags::UserAgent)),
    115      Origin(static_cast<uint8_t>(OriginFlags::User)),
    116      Origin(static_cast<uint8_t>(OriginFlags::Author)),
    117  };
    118 
    119 public:
    120  static bool IsInServoTraversal() { return mozilla::IsInServoTraversal(); }
    121 
    122 #ifdef DEBUG
    123  // Used for debug assertions. We make this debug-only to prevent callers from
    124  // accidentally using it instead of IsInServoTraversal, which is cheaper. We
    125  // can change this if a use-case arises.
    126  static bool IsCurrentThreadInServoTraversal();
    127 #endif
    128 
    129  static ServoStyleSet* Current() { return sInServoTraversal; }
    130 
    131  explicit ServoStyleSet(dom::Document&);
    132  ~ServoStyleSet();
    133 
    134  void ShellDetachedFromDocument();
    135 
    136  // Called when a rules in a stylesheet in this set, or a child sheet of that,
    137  // are mutated from CSSOM.
    138  void RuleAdded(StyleSheet&, css::Rule&);
    139  void RuleRemoved(StyleSheet&, css::Rule&);
    140  void RuleChanged(StyleSheet&, css::Rule*, const StyleRuleChange&);
    141  void SheetCloned(StyleSheet&);
    142  void ImportRuleLoaded(StyleSheet&);
    143 
    144  // Runs style invalidation due to document state changes.
    145  void InvalidateStyleForDocumentStateChanges(
    146      dom::DocumentState aStatesChanged);
    147 
    148  void RecordShadowStyleChange(dom::ShadowRoot&);
    149 
    150  bool StyleSheetsHaveChanged() const { return StylistNeedsUpdate(); }
    151 
    152  RestyleHint MediumFeaturesChanged(MediaFeatureChangeReason);
    153 
    154  // Evaluates a given SourceSizeList, returning the optimal viewport width in
    155  // app units.
    156  //
    157  // The SourceSizeList parameter can be null, in which case it will return
    158  // 100vw.
    159  inline nscoord EvaluateSourceSizeList(
    160      const StyleSourceSizeList* aSourceSizeList) const;
    161 
    162  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
    163  const StylePerDocumentStyleData* RawData() const { return mRawData.get(); }
    164 
    165  bool GetAuthorStyleDisabled() const { return mAuthorStyleDisabled; }
    166 
    167  bool UsesFontMetrics() const;
    168 
    169  bool UsesRootFontMetrics() const;
    170 
    171  void SetAuthorStyleDisabled(bool aStyleDisabled);
    172 
    173  // Get a CopmutedStyle for a text node (which no rules will match).
    174  //
    175  // The returned ComputedStyle will have nsCSSAnonBoxes::mozText() as its
    176  // pseudo.
    177  //
    178  // (Perhaps mozText should go away and we shouldn't even create style
    179  // contexts for such content nodes, when text-combine-upright is not
    180  // present.  However, not doing any rule matching for them is a first step.)
    181  already_AddRefed<ComputedStyle> ResolveStyleForText(
    182      nsIContent* aTextNode, ComputedStyle* aParentStyle);
    183 
    184  // Get a ComputedStyle for a first-letter continuation (which no rules will
    185  // match).
    186  //
    187  // The returned ComputedStyle will have
    188  // nsCSSAnonBoxes::firstLetterContinuation() as its pseudo.
    189  //
    190  // (Perhaps nsCSSAnonBoxes::firstLetterContinuation() should go away and we
    191  // shouldn't even create ComputedStyles for such frames.  However, not doing
    192  // any rule matching for them is a first step.  And right now we do use this
    193  // ComputedStyle for some things)
    194  already_AddRefed<ComputedStyle> ResolveStyleForFirstLetterContinuation(
    195      ComputedStyle* aParentStyle);
    196 
    197  // Get a ComputedStyle for a placeholder frame (which no rules will match).
    198  //
    199  // The returned ComputedStyle will have nsCSSAnonBoxes::oofPlaceholder() as
    200  // its pseudo.
    201  //
    202  // (Perhaps nsCSSAnonBoxes::oofPaceholder() should go away and we shouldn't
    203  // even create ComputedStyle for placeholders.  However, not doing any rule
    204  // matching for them is a first step.)
    205  already_AddRefed<ComputedStyle> ResolveStyleForPlaceholder();
    206 
    207  // Returns whether a given pseudo-element should exist or not.
    208  static bool GeneratedContentPseudoExists(const ComputedStyle& aParentStyle,
    209                                           const ComputedStyle& aPseudoStyle);
    210 
    211  enum class IsProbe {
    212    No,
    213    Yes,
    214  };
    215 
    216  // Get a style for a pseudo-element.
    217  //
    218  // If IsProbe is Yes, then no style is returned if there are no rules matching
    219  // for the pseudo-element, or GeneratedContentPseudoExists returns false.
    220  //
    221  // If IsProbe is No, then the style is guaranteed to be non-null.
    222  already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
    223      const dom::Element& aOriginatingElement, PseudoStyleType,
    224      nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle,
    225      IsProbe = IsProbe::No);
    226 
    227  already_AddRefed<ComputedStyle> ProbePseudoElementStyle(
    228      const dom::Element& aOriginatingElement, PseudoStyleType aType,
    229      nsAtom* aFunctionalPseudoParameter, ComputedStyle* aParentStyle) {
    230    return ResolvePseudoElementStyle(aOriginatingElement, aType,
    231                                     aFunctionalPseudoParameter, aParentStyle,
    232                                     IsProbe::Yes);
    233  }
    234 
    235  // Resolves style for a (possibly-pseudo) Element without assuming that the
    236  // style has been resolved. If the element was unstyled and a new style
    237  // was resolved, it is not stored in the DOM. (That is, the element remains
    238  // unstyled.)
    239  already_AddRefed<ComputedStyle> ResolveStyleLazily(
    240      const dom::Element&, const PseudoStyleRequest& aPseudoRequest = {},
    241      StyleRuleInclusion = StyleRuleInclusion::All);
    242 
    243  // Get a ComputedStyle for an anonymous box. The pseudo type must be an
    244  // inheriting anon box.
    245  already_AddRefed<ComputedStyle> ResolveInheritingAnonymousBoxStyle(
    246      PseudoStyleType, ComputedStyle* aParentStyle);
    247 
    248  // Get a ComputedStyle for an anonymous box. The pseudo type must be
    249  // a non-inheriting anon box, and must not be page-content.
    250  // See ResolvePageContentStyle for resolving page-content style.
    251  already_AddRefed<ComputedStyle> ResolveNonInheritingAnonymousBoxStyle(
    252      PseudoStyleType aType);
    253 
    254  // Get a ComputedStyle for a pageContent box with the specified page-name.
    255  // A page name that is null or the empty atom and has no pseudo classes gets
    256  // the global page style.
    257  already_AddRefed<ComputedStyle> ResolvePageContentStyle(
    258      const nsAtom* aPageName, const StylePagePseudoClassFlags& aPseudo);
    259 
    260  already_AddRefed<ComputedStyle> ResolveXULTreePseudoStyle(
    261      dom::Element* aParentElement, nsCSSAnonBoxPseudoStaticAtom* aPseudoTag,
    262      ComputedStyle* aParentStyle, const AtomArray& aInputWord);
    263 
    264  // Try to resolve the staring style for a given element. Please call this
    265  // function after checking if it may have rules inside @starting-style.
    266  already_AddRefed<ComputedStyle> ResolveStartingStyle(dom::Element& aElement);
    267 
    268  already_AddRefed<ComputedStyle> ResolvePositionTry(
    269      dom::Element& aElement, ComputedStyle& aStyle,
    270      const StylePositionTryFallbacksItem&);
    271 
    272  size_t SheetCount(Origin) const;
    273  StyleSheet* SheetAt(Origin, size_t aIndex) const;
    274 
    275  struct PageSizeAndOrientation {
    276    Maybe<StylePageSizeOrientation> orientation;
    277    Maybe<nsSize> size;
    278  };
    279  // Gets the default page size and orientation (the size/orientation specified
    280  // by @page rules without a selector list), if any.
    281  //
    282  // If the specified size is just an orientation, then the size will be set to
    283  // nothing and the orientation will be set accordingly.
    284  // If the specified size is auto or square, then the orientation will be set
    285  // to nothing.
    286  // Otherwise, the size will and orientation is determined by the specified
    287  // page size.
    288  PageSizeAndOrientation GetDefaultPageSizeAndOrientation();
    289 
    290  void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const;
    291 
    292  // Manage the set of style sheets in the style set
    293  void AppendStyleSheet(StyleSheet&);
    294  void InsertStyleSheetBefore(StyleSheet&, StyleSheet& aReferenceSheet);
    295  void RemoveStyleSheet(StyleSheet&);
    296  void AddDocStyleSheet(StyleSheet&);
    297 
    298  /**
    299   * Performs a Servo traversal to compute style for all dirty nodes in the
    300   * document.
    301   *
    302   * This will traverse all of the document's style roots (that is, its document
    303   * element, and the roots of the document-level native anonymous content).
    304   *
    305   * We specify |ForCSSRuleChanges| to try to update all CSS animations
    306   * when we call this function due to CSS rule changes since @keyframes rules
    307   * may have changed.
    308   *
    309   * Returns true if a post-traversal is required.
    310   */
    311  bool StyleDocument(ServoTraversalFlags aFlags);
    312 
    313  /**
    314   * Eagerly styles a subtree of unstyled nodes that was just appended to the
    315   * tree. This is used in situations where we need the style immediately and
    316   * cannot wait for a future batch restyle.
    317   */
    318  void StyleNewSubtree(dom::Element* aRoot);
    319 
    320  /**
    321   * Helper for correctly calling UpdateStylist without paying the cost of an
    322   * extra function call in the common no-rebuild-needed case.
    323   */
    324  void UpdateStylistIfNeeded() {
    325    if (StylistNeedsUpdate()) {
    326      UpdateStylist();
    327    }
    328  }
    329 
    330  /**
    331   * Checks whether the rule tree has crossed its threshold for unused nodes,
    332   * and if so, frees them.
    333   */
    334  void MaybeGCRuleTree();
    335 
    336  /**
    337   * Returns true if the given element may be used as the root of a style
    338   * traversal. Reasons for false include having an unstyled parent, or having
    339   * a parent that is display:none.
    340   *
    341   * Most traversal callsites don't need to check this, but some do.
    342   */
    343  static bool MayTraverseFrom(const dom::Element* aElement);
    344 
    345 #ifdef DEBUG
    346  void AssertTreeIsClean();
    347 #else
    348  void AssertTreeIsClean() {}
    349 #endif
    350 
    351  /**
    352   * Clears any cached style data that may depend on all sorts of computed
    353   * values.
    354   *
    355   * Right now this clears the non-inheriting ComputedStyle cache, resets the
    356   * default computed values, and clears cached anonymous content style.
    357   *
    358   * This does _not_, however, clear the stylist.
    359   */
    360  void ClearCachedStyleData();
    361 
    362  /**
    363   * Notifies the Servo stylesheet that the document's compatibility mode has
    364   * changed.
    365   */
    366  void CompatibilityModeChanged();
    367 
    368  template <typename T>
    369  void EnumerateStyleSheets(T aCb) {
    370    for (auto origin : kOrigins) {
    371      for (size_t i = 0, count = SheetCount(origin); i < count; ++i) {
    372        aCb(*SheetAt(origin, i));
    373      }
    374    }
    375  }
    376 
    377  /**
    378   * Resolve style for the given element, and return it as a
    379   * ComputedStyle.
    380   *
    381   * FIXME(emilio): Is there a point in this after bug 1367904?
    382   */
    383  static inline already_AddRefed<ComputedStyle> ResolveServoStyle(
    384      const dom::Element&);
    385 
    386  bool GetKeyframesForName(const dom::Element&, const ComputedStyle&,
    387                           nsAtom* aName,
    388                           const StyleComputedTimingFunction& aTimingFunction,
    389                           nsTArray<Keyframe>& aKeyframes);
    390 
    391  nsTArray<ComputedKeyframeValues> GetComputedKeyframeValuesFor(
    392      const nsTArray<Keyframe>& aKeyframes, dom::Element* aElement,
    393      const PseudoStyleRequest& aPseudoRequest, const ComputedStyle* aStyle);
    394 
    395  void GetAnimationValues(
    396      StyleLockedDeclarationBlock* aDeclarations, dom::Element* aElement,
    397      const mozilla::ComputedStyle* aStyle,
    398      nsTArray<RefPtr<StyleAnimationValue>>& aAnimationValues);
    399 
    400  void AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
    401 
    402  const StyleLockedCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
    403 
    404  // Get all the currently-active font feature values set.
    405  already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
    406 
    407  // Get the set of all currently-active font-palette-values.
    408  already_AddRefed<gfx::FontPaletteValueSet> BuildFontPaletteValueSet();
    409 
    410  already_AddRefed<ComputedStyle> GetBaseContextForElement(
    411      dom::Element* aElement, const ComputedStyle* aStyle);
    412 
    413  /**
    414   * Resolve style for a given declaration block with/without the parent style.
    415   * If the parent style is not specified, the document default computed values
    416   * is used.
    417   */
    418  already_AddRefed<ComputedStyle> ResolveForDeclarations(
    419      const ComputedStyle* aParentOrNull,
    420      const StyleLockedDeclarationBlock* aDeclarations);
    421 
    422  already_AddRefed<StyleAnimationValue> ComputeAnimationValue(
    423      dom::Element* aElement, StyleLockedDeclarationBlock* aDeclaration,
    424      const mozilla::ComputedStyle* aStyle);
    425 
    426  void AppendTask(PostTraversalTask aTask) {
    427    MOZ_ASSERT(IsInServoTraversal());
    428 
    429    // We currently only use PostTraversalTasks while the Servo font metrics
    430    // mutex is locked.  If we need to use them in other situations during
    431    // a traversal, we should assert that we've taken appropriate
    432    // synchronization measures.
    433    AssertIsMainThreadOrServoFontMetricsLocked();
    434 
    435    mPostTraversalTasks.AppendElement(aTask);
    436  }
    437 
    438  // Returns true if a restyle of the document is needed due to cloning
    439  // sheet inners.
    440  bool EnsureUniqueInnerOnCSSSheets();
    441 
    442  // Returns the style rule map.
    443  ServoStyleRuleMap* StyleRuleMap();
    444 
    445  /**
    446   * Returns true if a modification to an an attribute with the specified
    447   * local name might require us to restyle the element.
    448   *
    449   * This function allows us to skip taking a an attribute snapshot when
    450   * the modified attribute doesn't appear in an attribute selector in
    451   * a style sheet.
    452   */
    453  bool MightHaveAttributeDependency(const dom::Element&,
    454                                    nsAtom* aAttribute) const;
    455 
    456  /**
    457   * Returns true if a modification to an attribute with the specified local
    458   * name might require us to restyle the element's siblings.
    459   */
    460  bool MightHaveNthOfAttributeDependency(const dom::Element&,
    461                                         nsAtom* aAttribute) const;
    462 
    463  /**
    464   * Returns true if a modification to a class might require us to restyle the
    465   * element's siblings.
    466   */
    467  bool MightHaveNthOfClassDependency(const dom::Element&);
    468 
    469  /**
    470   * Returns true if a modification to an ID might require us to restyle the
    471   * element's siblings.
    472   */
    473  bool MightHaveNthOfIDDependency(const dom::Element&, nsAtom* aOldID,
    474                                  nsAtom* aNewID) const;
    475 
    476  /**
    477   * Maybe invalidate if a modification to an ID might require us to restyle
    478   * the relative selector it refers to.
    479   */
    480  void MaybeInvalidateRelativeSelectorIDDependency(
    481      const dom::Element&, nsAtom* aOldID, nsAtom* aNewID,
    482      const ServoElementSnapshotTable& aSnapshots);
    483 
    484  /**
    485   * Maybe invalidate if a modification to an attribute with the specified local
    486   * name might require us to restyle the relative selector it refers to.
    487   */
    488  void MaybeInvalidateRelativeSelectorClassDependency(
    489      const dom::Element&, const ServoElementSnapshotTable& aSnapshots);
    490 
    491  /**
    492   * Maybe invalidate if a modification to a Custom State might require us to
    493   * restyle the relative selector it refers to.
    494   */
    495  void MaybeInvalidateRelativeSelectorCustomStateDependency(
    496      const dom::Element&, nsAtom* state,
    497      const ServoElementSnapshotTable& aSnapshots);
    498 
    499  /**
    500   * Maybe invalidate if a modification to an ID might require us to restyle
    501   * the relative selector it refers to.
    502   */
    503  void MaybeInvalidateRelativeSelectorAttributeDependency(
    504      const dom::Element&, nsAtom* aAttribute,
    505      const ServoElementSnapshotTable& aSnapshots);
    506 
    507  /**
    508   * Maybe invalidate if a change in event state on an element might require us
    509   * to restyle the relative selector it refers to.
    510   */
    511  void MaybeInvalidateRelativeSelectorStateDependency(
    512      const dom::Element&, dom::ElementState,
    513      const ServoElementSnapshotTable& aSnapshots);
    514 
    515  /**
    516   * Maybe invalidate if a change on an element that might be selected by :empty
    517   * that might require us to restyle the relative selector it refers to.
    518   */
    519  void MaybeInvalidateRelativeSelectorForEmptyDependency(const dom::Element&);
    520 
    521  /**
    522   * Maybe invalidate if a state change on an element that might be selected
    523   * by a selector that can only selector first/last child, that
    524   * might require us to restyle the relative selector it refers to.
    525   */
    526  void MaybeInvalidateRelativeSelectorForNthEdgeDependency(
    527      const dom::Element&, StyleRelativeSelectorNthEdgeInvalidateFor);
    528 
    529  /**
    530   * Maybe invalidate if a state change on an element that might be selected by
    531   * :nth-* (Or :nth-like) selectors that might require us to restyle the
    532   * relative selector it refers to.
    533   */
    534  void MaybeInvalidateRelativeSelectorForNthDependencyFromSibling(
    535      const dom::Element*, bool aForceRestyleSiblings);
    536 
    537  /**
    538   * Maybe invalidate if a DOM element insertion might require us to restyle
    539   * the relative selector to ancestors/previous siblings.
    540   */
    541  void MaybeInvalidateForElementInsertion(const dom::Element&);
    542 
    543  /**
    544   * Maybe invalidate if a series of nodes is appended, among which may
    545   * be element(s) that might require us to restyle the relative selector
    546   * to ancestors/previous siblings.
    547   */
    548  void MaybeInvalidateForElementAppend(const nsIContent&);
    549 
    550  /**
    551   * Maybe invalidate if a DOM element removal might require us to restyle
    552   * the relative selector to ancestors/previous siblings.
    553   */
    554  void MaybeInvalidateForElementRemove(const dom::Element& aElement);
    555 
    556  /**
    557   * Returns true if a change in event state on an element might require
    558   * us to restyle the element.
    559   *
    560   * This function allows us to skip taking a state snapshot when
    561   * the changed state isn't depended upon by any pseudo-class selectors
    562   * in a style sheet.
    563   */
    564  bool HasStateDependency(const dom::Element&, dom::ElementState) const;
    565 
    566  /**
    567   * Returns true if a change in event state on an element might require
    568   * us to restyle the element's siblings.
    569   */
    570  bool HasNthOfStateDependency(const dom::Element&, dom::ElementState) const;
    571 
    572  /**
    573   * Returns true if a change in Custom State on an element might require
    574   * us to restyle the element's siblings.
    575   */
    576  bool HasNthOfCustomStateDependency(const dom::Element&, nsAtom*) const;
    577 
    578  /**
    579   * Restyle this element's siblings in order to propagate any potential change
    580   * in :nth-child(of) styling.
    581   */
    582  void RestyleSiblingsForNthOf(const dom::Element&, uint32_t) const;
    583 
    584  /**
    585   * Returns true if a change in document state might require us to restyle the
    586   * document.
    587   */
    588  bool HasDocumentStateDependency(dom::DocumentState) const;
    589 
    590  /**
    591   * Get a new ComputedStyle that uses the same rules as the given ComputedStyle
    592   * but has a different parent.
    593   *
    594   * aElement is non-null if this is a ComputedStyle for a frame whose mContent
    595   * is an element and which has no pseudo on its ComputedStyle (so it's the
    596   * actual style for the element being passed).
    597   */
    598  already_AddRefed<ComputedStyle> ReparentComputedStyle(
    599      ComputedStyle* aComputedStyle, ComputedStyle* aNewParent,
    600      ComputedStyle* aNewLayoutParent, dom::Element* aElement);
    601 
    602  /**
    603   * Invalidate styles where there's any viewport units dependent style.
    604   */
    605  enum class OnlyDynamic : bool { No, Yes };
    606  void InvalidateForViewportUnits(OnlyDynamic);
    607 
    608 private:
    609  friend class AutoSetInServoTraversal;
    610  friend class AutoPrepareTraversal;
    611  friend class PostTraversalTask;
    612 
    613  bool ShouldTraverseInParallel() const;
    614 
    615  void RuleChangedInternal(StyleSheet&, css::Rule&, const StyleRuleChange&);
    616 
    617  /**
    618   * Forces all the ShadowRoot styles to be dirty.
    619   *
    620   * Only to be used for:
    621   *
    622   *  * Devtools (dealing with sheet cloning).
    623   *  * Compatibility-mode changes.
    624   *
    625   * Try to do something more incremental for other callers that are exposed to
    626   * the web.
    627   */
    628  void ForceDirtyAllShadowStyles();
    629 
    630  /**
    631   * Gets the pending snapshots to handle from the restyle manager.
    632   */
    633  const SnapshotTable& Snapshots();
    634 
    635  /**
    636   * Clear our cached mNonInheritingComputedStyles.
    637   *
    638   * We do this when we want to make sure those ComputedStyles won't live too
    639   * long (e.g. when rebuilding all style data or when shutting down the style
    640   * set).
    641   */
    642  void ClearNonInheritingComputedStyles();
    643 
    644  /**
    645   * Perform processes that we should do before traversing.
    646   *
    647   * When aRoot is null, the entire document is pre-traversed.  Otherwise,
    648   * only the subtree rooted at aRoot is pre-traversed.
    649   */
    650  void PreTraverse(ServoTraversalFlags aFlags, dom::Element* aRoot = nullptr);
    651 
    652  // Subset of the pre-traverse steps that involve syncing up data
    653  void PreTraverseSync();
    654 
    655  /**
    656   * Records that the contents of style sheets at the specified origin have
    657   * changed since the last.  Calling this will ensure that the Stylist
    658   * rebuilds its selector maps.
    659   */
    660  void MarkOriginsDirty(OriginFlags aChangedOrigins);
    661 
    662  /**
    663   * Note that the stylist needs a style flush due to style sheet changes.
    664   */
    665  void SetStylistStyleSheetsDirty();
    666 
    667  void SetStylistShadowDOMStyleSheetsDirty();
    668 
    669  bool StylistNeedsUpdate() const {
    670    return mStylistState != StylistState::NotDirty;
    671  }
    672 
    673  /**
    674   * Update the stylist as needed to ensure style data is up-to-date.
    675   *
    676   * This should only be called if StylistNeedsUpdate returns true.
    677   */
    678  void UpdateStylist();
    679 
    680  void RunPostTraversalTasks();
    681 
    682  void PrependSheetOfType(Origin, StyleSheet*);
    683  void AppendSheetOfType(Origin, StyleSheet*);
    684  void InsertSheetOfType(Origin, StyleSheet*, StyleSheet* aBeforeSheet);
    685  void RemoveSheetOfType(Origin, StyleSheet*);
    686 
    687  const nsPresContext* GetPresContext() const {
    688    return const_cast<ServoStyleSet*>(this)->GetPresContext();
    689  }
    690 
    691  /**
    692   * Return the associated pres context if we're the master style set and we
    693   * have an associated pres shell.
    694   */
    695  nsPresContext* GetPresContext();
    696 
    697  // The owner document of this style set. Never null, and always outlives the
    698  // StyleSet.
    699  dom::Document* mDocument;
    700  UniquePtr<StylePerDocumentStyleData> mRawData;
    701 
    702  // Map from raw Servo style rule to Gecko's wrapper object.
    703  // Constructed lazily when requested by devtools.
    704  UniquePtr<ServoStyleRuleMap> mStyleRuleMap;
    705  uint64_t mUserFontSetUpdateGeneration = 0;
    706 
    707  // Tasks to perform after a traversal, back on the main thread.
    708  //
    709  // These are similar to Servo's SequentialTasks, except that they are
    710  // posted by C++ code running on style worker threads.
    711  nsTArray<PostTraversalTask> mPostTraversalTasks;
    712 
    713  // Stores pointers to our cached ComputedStyles for non-inheriting anonymous
    714  // boxes.
    715  EnumeratedArray<nsCSSAnonBoxes::NonInheriting, RefPtr<ComputedStyle>,
    716                  size_t(nsCSSAnonBoxes::NonInheriting::_Count)>
    717      mNonInheritingComputedStyles;
    718 
    719 public:
    720  void PutCachedAnonymousContentStyles(
    721      AnonymousContentKey aKey, nsTArray<RefPtr<ComputedStyle>>&& aStyles) {
    722    auto index = static_cast<size_t>(aKey);
    723 
    724    MOZ_ASSERT(mCachedAnonymousContentStyles.Length() + aStyles.Length() < 256,
    725               "(index, length) pairs must be bigger");
    726    MOZ_ASSERT(mCachedAnonymousContentStyleIndexes[index].length == 0,
    727               "shouldn't need to overwrite existing cached styles");
    728    MOZ_ASSERT(!aStyles.IsEmpty(), "should have some styles to cache");
    729 
    730    mCachedAnonymousContentStyleIndexes[index] = {
    731        (uint8_t)mCachedAnonymousContentStyles.Length(),
    732        (uint8_t)aStyles.Length()};
    733    mCachedAnonymousContentStyles.AppendElements(std::move(aStyles));
    734  }
    735 
    736  void GetCachedAnonymousContentStyles(
    737      AnonymousContentKey aKey, nsTArray<RefPtr<ComputedStyle>>& aStyles) {
    738    auto index = static_cast<size_t>(aKey);
    739    auto loc = mCachedAnonymousContentStyleIndexes[index];
    740    aStyles.AppendElements(mCachedAnonymousContentStyles.Elements() + loc.index,
    741                           loc.length);
    742  }
    743 
    744  void RegisterProperty(const dom::PropertyDefinition&, ErrorResult&);
    745 
    746 private:
    747  struct Location {
    748    uint8_t index, length;
    749  };
    750  // Map of AnonymousContentKey values to an (index, length) pair pointing into
    751  // mCachedAnonymousContentStyles.
    752  //
    753  // We assert that the index and length values fit into uint8_ts.
    754  Array<Location, 1 << sizeof(AnonymousContentKey) * 8>
    755      mCachedAnonymousContentStyleIndexes;
    756 
    757  // Stores cached ComputedStyles for certain native anonymous content.
    758  nsTArray<RefPtr<ComputedStyle>> mCachedAnonymousContentStyles;
    759 
    760  StylistState mStylistState = StylistState::NotDirty;
    761  bool mAuthorStyleDisabled = false;
    762  bool mNeedsRestyleAfterEnsureUniqueInner = false;
    763 };
    764 
    765 class UACacheReporter final : public nsIMemoryReporter {
    766  NS_DECL_ISUPPORTS
    767  NS_DECL_NSIMEMORYREPORTER
    768 
    769 private:
    770  ~UACacheReporter() = default;
    771 };
    772 
    773 }  // namespace mozilla
    774 
    775 #endif  // mozilla_ServoStyleSet_h