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