Bug 1698238 return default dictionary from GetUserMediaRequest#getConstraints() if...
[gecko.git] / layout / style / ServoStyleSet.h
bloba30cee54b6fad790717fb2bd1e5bd3cf5c888b5a
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/. */
7 #ifndef mozilla_ServoStyleSet_h
8 #define mozilla_ServoStyleSet_h
10 #include "mozilla/AnonymousContentKey.h"
11 #include "mozilla/AtomArray.h"
12 #include "mozilla/EnumeratedArray.h"
13 #include "mozilla/EventStates.h"
14 #include "mozilla/PostTraversalTask.h"
15 #include "mozilla/ServoBindingTypes.h"
16 #include "mozilla/ServoUtils.h"
17 #include "mozilla/UniquePtr.h"
18 #include "MainThreadUtils.h"
19 #include "nsCSSPseudoElements.h"
20 #include "nsCSSAnonBoxes.h"
21 #include "nsChangeHint.h"
22 #include "nsCoord.h"
23 #include "nsAtom.h"
24 #include "nsIMemoryReporter.h"
25 #include "nsTArray.h"
26 #include "nsIMemoryReporter.h"
28 namespace mozilla {
29 enum class MediaFeatureChangeReason : uint16_t;
30 enum class StyleRuleChangeKind : uint32_t;
31 namespace css {
32 class Rule;
33 } // namespace css
34 namespace dom {
35 class CSSImportRule;
36 class Element;
37 class ShadowRoot;
38 } // namespace dom
39 class StyleSheet;
40 struct Keyframe;
41 class ServoElementSnapshotTable;
42 class ComputedStyle;
43 class ServoStyleRuleMap;
44 class StyleSheet;
45 } // namespace mozilla
46 class gfxFontFeatureValueSet;
47 class nsIContent;
49 class nsPresContext;
50 class nsWindowSizes;
51 struct nsTimingFunction;
52 struct TreeMatchContext;
54 namespace mozilla {
56 // A few flags used to track which kind of stylist state we may need to
57 // update.
58 enum class StylistState : uint8_t {
59 // The stylist is not dirty, we should do nothing.
60 NotDirty = 0,
62 // The style sheets have changed, so we need to update the style data.
63 StyleSheetsDirty = 1 << 0,
65 // Some of the style sheets of the shadow trees in the document have
66 // changed.
67 ShadowDOMStyleSheetsDirty = 1 << 1,
70 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StylistState)
72 enum class StyleOrigin : uint8_t;
74 // Bitfield type to represent Servo stylesheet origins.
75 enum class OriginFlags : uint8_t {
76 UserAgent = 0x01,
77 User = 0x02,
78 Author = 0x04,
79 All = 0x07,
82 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OriginFlags)
84 /**
85 * The set of style sheets that apply to a document, backed by a Servo
86 * Stylist. A ServoStyleSet contains StyleSheets.
88 class ServoStyleSet {
89 friend class RestyleManager;
90 using SnapshotTable = ServoElementSnapshotTable;
91 using Origin = StyleOrigin;
93 // We assert that these match the Servo ones in the definition of this array.
94 static constexpr Origin kOrigins[] = {
95 Origin(static_cast<uint8_t>(OriginFlags::UserAgent)),
96 Origin(static_cast<uint8_t>(OriginFlags::User)),
97 Origin(static_cast<uint8_t>(OriginFlags::Author)),
100 public:
101 static bool IsInServoTraversal() { return mozilla::IsInServoTraversal(); }
103 #ifdef DEBUG
104 // Used for debug assertions. We make this debug-only to prevent callers from
105 // accidentally using it instead of IsInServoTraversal, which is cheaper. We
106 // can change this if a use-case arises.
107 static bool IsCurrentThreadInServoTraversal();
108 #endif
110 static ServoStyleSet* Current() { return sInServoTraversal; }
112 explicit ServoStyleSet(dom::Document&);
113 ~ServoStyleSet();
115 void ShellDetachedFromDocument();
117 // Called when a rules in a stylesheet in this set, or a child sheet of that,
118 // are mutated from CSSOM.
119 void RuleAdded(StyleSheet&, css::Rule&);
120 void RuleRemoved(StyleSheet&, css::Rule&);
121 void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
122 void SheetCloned(StyleSheet&) { mNeedsRestyleAfterEnsureUniqueInner = true; }
123 void ImportRuleLoaded(dom::CSSImportRule&, StyleSheet&);
125 // Runs style invalidation due to document state changes.
126 void InvalidateStyleForDocumentStateChanges(EventStates aStatesChanged);
128 void RecordShadowStyleChange(dom::ShadowRoot&);
130 bool StyleSheetsHaveChanged() const { return StylistNeedsUpdate(); }
132 RestyleHint MediumFeaturesChanged(MediaFeatureChangeReason);
134 // Evaluates a given SourceSizeList, returning the optimal viewport width in
135 // app units.
137 // The SourceSizeList parameter can be null, in which case it will return
138 // 100vw.
139 inline nscoord EvaluateSourceSizeList(
140 const RawServoSourceSizeList* aSourceSizeList) const;
142 void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
143 const RawServoStyleSet* RawSet() const { return mRawSet.get(); }
145 bool GetAuthorStyleDisabled() const { return mAuthorStyleDisabled; }
147 void SetAuthorStyleDisabled(bool aStyleDisabled);
149 // Get a CopmutedStyle for a text node (which no rules will match).
151 // The returned ComputedStyle will have nsCSSAnonBoxes::mozText() as its
152 // pseudo.
154 // (Perhaps mozText should go away and we shouldn't even create style
155 // contexts for such content nodes, when text-combine-upright is not
156 // present. However, not doing any rule matching for them is a first step.)
157 already_AddRefed<ComputedStyle> ResolveStyleForText(
158 nsIContent* aTextNode, ComputedStyle* aParentStyle);
160 // Get a ComputedStyle for a first-letter continuation (which no rules will
161 // match).
163 // The returned ComputedStyle will have
164 // nsCSSAnonBoxes::firstLetterContinuation() as its pseudo.
166 // (Perhaps nsCSSAnonBoxes::firstLetterContinuation() should go away and we
167 // shouldn't even create ComputedStyles for such frames. However, not doing
168 // any rule matching for them is a first step. And right now we do use this
169 // ComputedStyle for some things)
170 already_AddRefed<ComputedStyle> ResolveStyleForFirstLetterContinuation(
171 ComputedStyle* aParentStyle);
173 // Get a ComputedStyle for a placeholder frame (which no rules will match).
175 // The returned ComputedStyle will have nsCSSAnonBoxes::oofPlaceholder() as
176 // its pseudo.
178 // (Perhaps nsCSSAnonBoxes::oofPaceholder() should go away and we shouldn't
179 // even create ComputedStyle for placeholders. However, not doing any rule
180 // matching for them is a first step.)
181 already_AddRefed<ComputedStyle> ResolveStyleForPlaceholder();
183 // Returns whether a given pseudo-element should exist or not.
184 static bool GeneratedContentPseudoExists(const ComputedStyle& aParentStyle,
185 const ComputedStyle& aPseudoStyle);
187 enum class IsProbe {
189 Yes,
192 // Get a style for a pseudo-element.
194 // If IsProbe is Yes, then no style is returned if there are no rules matching
195 // for the pseudo-element, or GeneratedContentPseudoExists returns false.
197 // If IsProbe is No, then the style is guaranteed to be non-null.
198 already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
199 const dom::Element& aOriginatingElement, PseudoStyleType,
200 ComputedStyle* aParentStyle, IsProbe = IsProbe::No);
202 already_AddRefed<ComputedStyle> ProbePseudoElementStyle(
203 const dom::Element& aOriginatingElement, PseudoStyleType aType,
204 ComputedStyle* aParentStyle) {
205 return ResolvePseudoElementStyle(aOriginatingElement, aType, aParentStyle,
206 IsProbe::Yes);
209 // Resolves style for a (possibly-pseudo) Element without assuming that the
210 // style has been resolved. If the element was unstyled and a new style
211 // was resolved, it is not stored in the DOM. (That is, the element remains
212 // unstyled.)
213 already_AddRefed<ComputedStyle> ResolveStyleLazily(
214 const dom::Element&, PseudoStyleType = PseudoStyleType::NotPseudo,
215 StyleRuleInclusion = StyleRuleInclusion::All);
217 // Get a ComputedStyle for an anonymous box. The pseudo type must be an
218 // inheriting anon box.
219 already_AddRefed<ComputedStyle> ResolveInheritingAnonymousBoxStyle(
220 PseudoStyleType, ComputedStyle* aParentStyle);
222 // Get a ComputedStyle for an anonymous box. The pseudo type must be
223 // a non-inheriting anon box.
224 already_AddRefed<ComputedStyle> ResolveNonInheritingAnonymousBoxStyle(
225 PseudoStyleType);
227 #ifdef MOZ_XUL
228 already_AddRefed<ComputedStyle> ResolveXULTreePseudoStyle(
229 dom::Element* aParentElement, nsCSSAnonBoxPseudoStaticAtom* aPseudoTag,
230 ComputedStyle* aParentStyle, const AtomArray& aInputWord);
231 #endif
233 size_t SheetCount(Origin) const;
234 StyleSheet* SheetAt(Origin, size_t aIndex) const;
236 void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const;
238 // Manage the set of style sheets in the style set
239 void AppendStyleSheet(StyleSheet&);
240 void InsertStyleSheetBefore(StyleSheet&, StyleSheet& aReferenceSheet);
241 void RemoveStyleSheet(StyleSheet&);
242 void AddDocStyleSheet(StyleSheet&);
245 * Performs a Servo traversal to compute style for all dirty nodes in the
246 * document.
248 * This will traverse all of the document's style roots (that is, its document
249 * element, and the roots of the document-level native anonymous content).
251 * We specify |ForCSSRuleChanges| to try to update all CSS animations
252 * when we call this function due to CSS rule changes since @keyframes rules
253 * may have changed.
255 * Returns true if a post-traversal is required.
257 bool StyleDocument(ServoTraversalFlags aFlags);
260 * Eagerly styles a subtree of unstyled nodes that was just appended to the
261 * tree. This is used in situations where we need the style immediately and
262 * cannot wait for a future batch restyle.
264 void StyleNewSubtree(dom::Element* aRoot);
267 * Helper for correctly calling UpdateStylist without paying the cost of an
268 * extra function call in the common no-rebuild-needed case.
270 void UpdateStylistIfNeeded() {
271 if (StylistNeedsUpdate()) {
272 UpdateStylist();
277 * Checks whether the rule tree has crossed its threshold for unused nodes,
278 * and if so, frees them.
280 void MaybeGCRuleTree();
283 * Returns true if the given element may be used as the root of a style
284 * traversal. Reasons for false include having an unstyled parent, or having
285 * a parent that is display:none.
287 * Most traversal callsites don't need to check this, but some do.
289 static bool MayTraverseFrom(const dom::Element* aElement);
291 #ifdef DEBUG
292 void AssertTreeIsClean();
293 #else
294 void AssertTreeIsClean() {}
295 #endif
298 * Clears any cached style data that may depend on all sorts of computed
299 * values.
301 * Right now this clears the non-inheriting ComputedStyle cache, resets the
302 * default computed values, and clears cached anonymous content style.
304 * This does _not_, however, clear the stylist.
306 void ClearCachedStyleData();
309 * Notifies the Servo stylesheet that the document's compatibility mode has
310 * changed.
312 void CompatibilityModeChanged();
314 template <typename T>
315 void EnumerateStyleSheets(T aCb) {
316 for (auto origin : kOrigins) {
317 for (size_t i = 0, count = SheetCount(origin); i < count; ++i) {
318 aCb(*SheetAt(origin, i));
324 * Resolve style for the given element, and return it as a
325 * ComputedStyle.
327 * FIXME(emilio): Is there a point in this after bug 1367904?
329 static inline already_AddRefed<ComputedStyle> ResolveServoStyle(
330 const dom::Element&);
332 bool GetKeyframesForName(const dom::Element&, const ComputedStyle&,
333 nsAtom* aName,
334 const nsTimingFunction& aTimingFunction,
335 nsTArray<Keyframe>& aKeyframes);
337 nsTArray<ComputedKeyframeValues> GetComputedKeyframeValuesFor(
338 const nsTArray<Keyframe>& aKeyframes, dom::Element* aElement,
339 PseudoStyleType aPseudoType, const ComputedStyle* aStyle);
341 void GetAnimationValues(
342 RawServoDeclarationBlock* aDeclarations, dom::Element* aElement,
343 const mozilla::ComputedStyle* aStyle,
344 nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues);
346 void AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
348 const RawServoCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
350 // Get all the currently-active font feature values set.
351 already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
353 already_AddRefed<ComputedStyle> GetBaseContextForElement(
354 dom::Element* aElement, const ComputedStyle* aStyle);
356 // Get a ComputedStyle that represents |aStyle|, but as though it additionally
357 // matched the rules of the newly added |aAnimaitonaValue|.
359 // We use this function to temporarily generate a ComputedStyle for
360 // calculating the cumulative change hints.
362 // This must hold:
363 // The additional rules must be appropriate for the transition
364 // level of the cascade, which is the highest level of the cascade.
365 // (This is the case for one current caller, the cover rule used
366 // for CSS transitions.)
367 // Note: |aElement| should be the generated element if it is pseudo.
368 already_AddRefed<ComputedStyle> ResolveServoStyleByAddingAnimation(
369 dom::Element* aElement, const ComputedStyle* aStyle,
370 RawServoAnimationValue* aAnimationValue);
372 * Resolve style for a given declaration block with/without the parent style.
373 * If the parent style is not specified, the document default computed values
374 * is used.
376 already_AddRefed<ComputedStyle> ResolveForDeclarations(
377 const ComputedStyle* aParentOrNull,
378 const RawServoDeclarationBlock* aDeclarations);
380 already_AddRefed<RawServoAnimationValue> ComputeAnimationValue(
381 dom::Element* aElement, RawServoDeclarationBlock* aDeclaration,
382 const mozilla::ComputedStyle* aStyle);
384 void AppendTask(PostTraversalTask aTask) {
385 MOZ_ASSERT(IsInServoTraversal());
387 // We currently only use PostTraversalTasks while the Servo font metrics
388 // mutex is locked. If we need to use them in other situations during
389 // a traversal, we should assert that we've taken appropriate
390 // synchronization measures.
391 AssertIsMainThreadOrServoFontMetricsLocked();
393 mPostTraversalTasks.AppendElement(aTask);
396 // Returns true if a restyle of the document is needed due to cloning
397 // sheet inners.
398 bool EnsureUniqueInnerOnCSSSheets();
400 // Returns the style rule map.
401 ServoStyleRuleMap* StyleRuleMap();
404 * Returns true if a modification to an an attribute with the specified
405 * local name might require us to restyle the element.
407 * This function allows us to skip taking a an attribute snapshot when
408 * the modified attribute doesn't appear in an attribute selector in
409 * a style sheet.
411 bool MightHaveAttributeDependency(const dom::Element&,
412 nsAtom* aAttribute) const;
415 * Returns true if a change in event state on an element might require
416 * us to restyle the element.
418 * This function allows us to skip taking a state snapshot when
419 * the changed state isn't depended upon by any pseudo-class selectors
420 * in a style sheet.
422 bool HasStateDependency(const dom::Element&, EventStates) const;
425 * Returns true if a change in document state might require us to restyle the
426 * document.
428 bool HasDocumentStateDependency(EventStates aState) const;
431 * Get a new ComputedStyle that uses the same rules as the given ComputedStyle
432 * but has a different parent.
434 * aElement is non-null if this is a ComputedStyle for a frame whose mContent
435 * is an element and which has no pseudo on its ComputedStyle (so it's the
436 * actual style for the element being passed).
438 already_AddRefed<ComputedStyle> ReparentComputedStyle(
439 ComputedStyle* aComputedStyle, ComputedStyle* aNewParent,
440 ComputedStyle* aNewParentIgnoringFirstLine,
441 ComputedStyle* aNewLayoutParent, dom::Element* aElement);
443 private:
444 friend class AutoSetInServoTraversal;
445 friend class AutoPrepareTraversal;
446 friend class PostTraversalTask;
448 bool ShouldTraverseInParallel() const;
450 void RuleChangedInternal(StyleSheet&, css::Rule&, StyleRuleChangeKind);
453 * Forces all the ShadowRoot styles to be dirty.
455 * Only to be used for:
457 * * Devtools (dealing with sheet cloning).
458 * * Compatibility-mode changes.
460 * Try to do something more incremental for other callers that are exposed to
461 * the web.
463 void ForceDirtyAllShadowStyles();
466 * Gets the pending snapshots to handle from the restyle manager.
468 const SnapshotTable& Snapshots();
471 * Resolve all DeclarationBlocks attached to mapped
472 * presentation attributes cached on the document.
474 * Call this before jumping into Servo's style system.
476 void ResolveMappedAttrDeclarationBlocks();
479 * Clear our cached mNonInheritingComputedStyles.
481 * We do this when we want to make sure those ComputedStyles won't live too
482 * long (e.g. when rebuilding all style data or when shutting down the style
483 * set).
485 void ClearNonInheritingComputedStyles();
488 * Perform processes that we should do before traversing.
490 * When aRoot is null, the entire document is pre-traversed. Otherwise,
491 * only the subtree rooted at aRoot is pre-traversed.
493 void PreTraverse(ServoTraversalFlags aFlags, dom::Element* aRoot = nullptr);
495 // Subset of the pre-traverse steps that involve syncing up data
496 void PreTraverseSync();
499 * Records that the contents of style sheets at the specified origin have
500 * changed since the last. Calling this will ensure that the Stylist
501 * rebuilds its selector maps.
503 void MarkOriginsDirty(OriginFlags aChangedOrigins);
506 * Note that the stylist needs a style flush due to style sheet changes.
508 void SetStylistStyleSheetsDirty();
510 void SetStylistShadowDOMStyleSheetsDirty();
512 bool StylistNeedsUpdate() const {
513 return mStylistState != StylistState::NotDirty;
517 * Update the stylist as needed to ensure style data is up-to-date.
519 * This should only be called if StylistNeedsUpdate returns true.
521 void UpdateStylist();
523 void RunPostTraversalTasks();
525 void PrependSheetOfType(Origin, StyleSheet*);
526 void AppendSheetOfType(Origin, StyleSheet*);
527 void InsertSheetOfType(Origin, StyleSheet*, StyleSheet* aBeforeSheet);
528 void RemoveSheetOfType(Origin, StyleSheet*);
530 const nsPresContext* GetPresContext() const {
531 return const_cast<ServoStyleSet*>(this)->GetPresContext();
535 * Return the associated pres context if we're the master style set and we
536 * have an associated pres shell.
538 nsPresContext* GetPresContext();
540 // The owner document of this style set. Never null, and always outlives the
541 // StyleSet.
542 dom::Document* mDocument;
543 UniquePtr<RawServoStyleSet> mRawSet;
545 // Map from raw Servo style rule to Gecko's wrapper object.
546 // Constructed lazily when requested by devtools.
547 UniquePtr<ServoStyleRuleMap> mStyleRuleMap;
548 uint64_t mUserFontSetUpdateGeneration = 0;
550 // Tasks to perform after a traversal, back on the main thread.
552 // These are similar to Servo's SequentialTasks, except that they are
553 // posted by C++ code running on style worker threads.
554 nsTArray<PostTraversalTask> mPostTraversalTasks;
556 // Stores pointers to our cached ComputedStyles for non-inheriting anonymous
557 // boxes.
558 EnumeratedArray<nsCSSAnonBoxes::NonInheriting,
559 nsCSSAnonBoxes::NonInheriting::_Count, RefPtr<ComputedStyle>>
560 mNonInheritingComputedStyles;
562 public:
563 void PutCachedAnonymousContentStyles(
564 AnonymousContentKey aKey, nsTArray<RefPtr<ComputedStyle>>&& aStyles) {
565 auto index = static_cast<size_t>(aKey);
567 MOZ_ASSERT(mCachedAnonymousContentStyles.Length() + aStyles.Length() < 256,
568 "(index, length) pairs must be bigger");
569 MOZ_ASSERT(mCachedAnonymousContentStyleIndexes[index].second == 0,
570 "shouldn't need to overwrite existing cached styles");
571 MOZ_ASSERT(!aStyles.IsEmpty(), "should have some styles to cache");
573 mCachedAnonymousContentStyleIndexes[index] = std::make_pair(
574 mCachedAnonymousContentStyles.Length(), aStyles.Length());
575 mCachedAnonymousContentStyles.AppendElements(std::move(aStyles));
578 void GetCachedAnonymousContentStyles(
579 AnonymousContentKey aKey, nsTArray<RefPtr<ComputedStyle>>& aStyles) {
580 auto index = static_cast<size_t>(aKey);
581 auto loc = mCachedAnonymousContentStyleIndexes[index];
582 aStyles.AppendElements(mCachedAnonymousContentStyles.Elements() + loc.first,
583 loc.second);
586 private:
587 // Map of AnonymousContentKey values to an (index, length) pair pointing into
588 // mCachedAnonymousContentStyles.
590 // We assert that the index and length values fit into uint8_ts.
591 Array<std::pair<uint8_t, uint8_t>, 1 << sizeof(AnonymousContentKey) * 8>
592 mCachedAnonymousContentStyleIndexes;
594 // Stores cached ComputedStyles for certain native anonymous content.
595 nsTArray<RefPtr<ComputedStyle>> mCachedAnonymousContentStyles;
597 StylistState mStylistState = StylistState::NotDirty;
598 bool mAuthorStyleDisabled = false;
599 bool mNeedsRestyleAfterEnsureUniqueInner = false;
602 class UACacheReporter final : public nsIMemoryReporter {
603 NS_DECL_ISUPPORTS
604 NS_DECL_NSIMEMORYREPORTER
606 private:
607 ~UACacheReporter() = default;
610 } // namespace mozilla
612 #endif // mozilla_ServoStyleSet_h