Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/ServoStyleSet.h
Line
Count
Source (jump to first uncovered line)
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 "mozilla/AtomArray.h"
11
#include "mozilla/EnumeratedArray.h"
12
#include "mozilla/EventStates.h"
13
#include "mozilla/MediaFeatureChange.h"
14
#include "mozilla/PostTraversalTask.h"
15
#include "mozilla/ServoBindingTypes.h"
16
#include "mozilla/ServoUtils.h"
17
#include "mozilla/SheetType.h"
18
#include "mozilla/UniquePtr.h"
19
#include "MainThreadUtils.h"
20
#include "nsCSSPseudoElements.h"
21
#include "nsCSSAnonBoxes.h"
22
#include "nsChangeHint.h"
23
#include "nsCoord.h"
24
#include "nsAtom.h"
25
#include "nsIMemoryReporter.h"
26
#include "nsTArray.h"
27
28
namespace mozilla {
29
namespace css {
30
class Rule;
31
} // namespace css
32
namespace dom {
33
class Element;
34
class ShadowRoot;
35
} // namespace dom
36
class StyleSheet;
37
struct Keyframe;
38
class ServoElementSnapshotTable;
39
class ComputedStyle;
40
class ServoStyleRuleMap;
41
class StyleSheet;
42
} // namespace mozilla
43
class gfxFontFeatureValueSet;
44
class nsIContent;
45
class nsIDocument;
46
class nsPresContext;
47
struct nsTimingFunction;
48
struct RawServoRuleNode;
49
struct TreeMatchContext;
50
51
namespace mozilla {
52
53
// A few flags used to track which kind of stylist state we may need to
54
// update.
55
enum class StylistState : uint8_t {
56
  // The stylist is not dirty, we should do nothing.
57
  NotDirty = 0,
58
59
  // The style sheets have changed, so we need to update the style data.
60
  StyleSheetsDirty = 1 << 0,
61
62
  // Some of the style sheets of the bound elements in binding manager have
63
  // changed, so we need to tell the binding manager to update style data.
64
  XBLStyleSheetsDirty = 1 << 1,
65
};
66
67
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StylistState)
68
69
// Bitfield type to represent Servo stylesheet origins.
70
enum class OriginFlags : uint8_t {
71
  UserAgent = 0x01,
72
  User      = 0x02,
73
  Author    = 0x04,
74
  All       = 0x07,
75
};
76
77
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OriginFlags)
78
79
/**
80
 * The set of style sheets that apply to a document, backed by a Servo
81
 * Stylist.  A ServoStyleSet contains StyleSheets.
82
 */
83
class ServoStyleSet
84
{
85
  friend class RestyleManager;
86
  typedef ServoElementSnapshotTable SnapshotTable;
87
88
public:
89
0
  static bool IsInServoTraversal() { return mozilla::IsInServoTraversal(); }
90
91
#ifdef DEBUG
92
  // Used for debug assertions. We make this debug-only to prevent callers from
93
  // accidentally using it instead of IsInServoTraversal, which is cheaper. We
94
  // can change this if a use-case arises.
95
  static bool IsCurrentThreadInServoTraversal();
96
#endif
97
98
  static ServoStyleSet* Current()
99
0
  {
100
0
    return sInServoTraversal;
101
0
  }
102
103
  ServoStyleSet();
104
  ~ServoStyleSet();
105
106
  void Init(nsPresContext* aPresContext);
107
0
  void BeginShutdown() {}
108
  void Shutdown();
109
110
  // Called when a rules in a stylesheet in this set, or a child sheet of that,
111
  // are mutated from CSSOM.
112
  void RuleAdded(StyleSheet&, css::Rule&);
113
  void RuleRemoved(StyleSheet&, css::Rule&);
114
  void RuleChanged(StyleSheet& aSheet, css::Rule* aRule);
115
116
  // Runs style invalidation due to document state changes.
117
  void InvalidateStyleForDocumentStateChanges(EventStates aStatesChanged);
118
119
  void RecordShadowStyleChange(dom::ShadowRoot&);
120
121
  bool StyleSheetsHaveChanged() const
122
0
  {
123
0
    return StylistNeedsUpdate();
124
0
  }
125
126
  nsRestyleHint MediumFeaturesChanged(MediaFeatureChangeReason);
127
128
  // Evaluates a given SourceSizeList, returning the optimal viewport width in
129
  // app units.
130
  //
131
  // The SourceSizeList parameter can be null, in which case it will return
132
  // 100vw.
133
  inline nscoord EvaluateSourceSizeList(
134
      const RawServoSourceSizeList* aSourceSizeList) const;
135
136
  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
137
0
  const RawServoStyleSet* RawSet() const {
138
0
    return mRawSet.get();
139
0
  }
140
141
  bool GetAuthorStyleDisabled() const
142
0
  {
143
0
    return mAuthorStyleDisabled;
144
0
  }
145
146
  void SetAuthorStyleDisabled(bool aStyleDisabled);
147
148
  // FIXME(emilio): All the callers pass Allow here
149
  already_AddRefed<ComputedStyle>
150
  ResolveStyleFor(dom::Element* aElement,
151
                  LazyComputeBehavior aMayCompute);
152
153
  // Get a CopmutedStyle for a text node (which no rules will match).
154
  //
155
  // The returned ComputedStyle will have nsCSSAnonBoxes::mozText() as its pseudo.
156
  //
157
  // (Perhaps mozText should go away and we shouldn't even create style
158
  // contexts for such content nodes, when text-combine-upright is not
159
  // present.  However, not doing any rule matching for them is a first step.)
160
  already_AddRefed<ComputedStyle>
161
  ResolveStyleForText(nsIContent* aTextNode, ComputedStyle* aParentContext);
162
163
  // Get a ComputedStyle for a first-letter continuation (which no rules will
164
  // match).
165
  //
166
  // The returned ComputedStyle will have
167
  // nsCSSAnonBoxes::firstLetterContinuation() as its pseudo.
168
  //
169
  // (Perhaps nsCSSAnonBoxes::firstLetterContinuation() should go away and we
170
  // shouldn't even create ComputedStyles for such frames.  However, not doing
171
  // any rule matching for them is a first step.  And right now we do use this
172
  // ComputedStyle for some things)
173
  already_AddRefed<ComputedStyle>
174
  ResolveStyleForFirstLetterContinuation(ComputedStyle* aParentContext);
175
176
  // Get a ComputedStyle for a placeholder frame (which no rules will match).
177
  //
178
  // The returned ComputedStyle will have nsCSSAnonBoxes::oofPlaceholder() as
179
  // its pseudo.
180
  //
181
  // (Perhaps nsCSSAnonBoxes::oofPaceholder() should go away and we shouldn't even
182
  // create ComputedStyle for placeholders.  However, not doing any rule
183
  // matching for them is a first step.)
184
  already_AddRefed<ComputedStyle>
185
  ResolveStyleForPlaceholder();
186
187
  // Get a ComputedStyle for a pseudo-element.  aParentElement must be
188
  // non-null.  aPseudoID is the CSSPseudoElementType for the
189
  // pseudo-element.  aPseudoElement must be non-null if the pseudo-element
190
  // type is one that allows user action pseudo-classes after it or allows
191
  // style attributes; otherwise, it is ignored.
192
  already_AddRefed<ComputedStyle>
193
  ResolvePseudoElementStyle(dom::Element* aOriginatingElement,
194
                            CSSPseudoElementType aType,
195
                            ComputedStyle* aParentContext,
196
                            dom::Element* aPseudoElement);
197
198
  // Resolves style for a (possibly-pseudo) Element without assuming that the
199
  // style has been resolved. If the element was unstyled and a new style
200
  // context was resolved, it is not stored in the DOM. (That is, the element
201
  // remains unstyled.)
202
  already_AddRefed<ComputedStyle>
203
  ResolveStyleLazily(dom::Element* aElement,
204
                     CSSPseudoElementType aPseudoType,
205
                     StyleRuleInclusion aRules =
206
                       StyleRuleInclusion::All);
207
208
  // Get a ComputedStyle for an anonymous box.  aPseudoTag is the pseudo-tag to
209
  // use and must be non-null.  It must be an anon box, and must be one that
210
  // inherits style from the given aParentContext.
211
  already_AddRefed<ComputedStyle>
212
  ResolveInheritingAnonymousBoxStyle(nsAtom* aPseudoTag,
213
                                     ComputedStyle* aParentContext);
214
215
  // Get a ComputedStyle for an anonymous box that does not inherit style from
216
  // anything.  aPseudoTag is the pseudo-tag to use and must be non-null.  It
217
  // must be an anon box, and must be a non-inheriting one.
218
  already_AddRefed<ComputedStyle>
219
  ResolveNonInheritingAnonymousBoxStyle(nsAtom* aPseudoTag);
220
221
#ifdef MOZ_XUL
222
  already_AddRefed<ComputedStyle>
223
  ResolveXULTreePseudoStyle(dom::Element* aParentElement,
224
                            nsICSSAnonBoxPseudo* aPseudoTag,
225
                            ComputedStyle* aParentContext,
226
                            const AtomArray& aInputWord);
227
#endif
228
229
  // manage the set of style sheets in the style set
230
  nsresult AppendStyleSheet(SheetType aType, StyleSheet* aSheet);
231
  nsresult PrependStyleSheet(SheetType aType, StyleSheet* aSheet);
232
  nsresult RemoveStyleSheet(SheetType aType, StyleSheet* aSheet);
233
  nsresult ReplaceSheets(SheetType aType,
234
                         const nsTArray<RefPtr<StyleSheet>>& aNewSheets);
235
  nsresult InsertStyleSheetBefore(SheetType aType,
236
                                  StyleSheet* aNewSheet,
237
                                  StyleSheet* aReferenceSheet);
238
239
  int32_t SheetCount(SheetType aType) const;
240
  StyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
241
242
  void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const;
243
244
  template<typename Func>
245
0
  void EnumerateStyleSheetArrays(Func aCallback) const {
246
0
    for (const auto& sheetArray : mSheets) {
247
0
      aCallback(sheetArray);
248
0
    }
249
0
  }
250
251
  nsresult RemoveDocStyleSheet(StyleSheet* aSheet);
252
  nsresult AddDocStyleSheet(StyleSheet* aSheet, nsIDocument* aDocument);
253
254
  // check whether there is ::before/::after style for an element
255
  already_AddRefed<ComputedStyle>
256
  ProbePseudoElementStyle(const dom::Element& aOriginatingElement,
257
                          CSSPseudoElementType aType,
258
                          ComputedStyle* aParentStyle);
259
260
  /**
261
   * Performs a Servo traversal to compute style for all dirty nodes in the
262
   * document.
263
   *
264
   * This will traverse all of the document's style roots (that is, its document
265
   * element, and the roots of the document-level native anonymous content).
266
   *
267
   * We specify |ForCSSRuleChanges| to try to update all CSS animations
268
   * when we call this function due to CSS rule changes since @keyframes rules
269
   * may have changed.
270
   *
271
   * Returns true if a post-traversal is required.
272
   */
273
  bool StyleDocument(ServoTraversalFlags aFlags);
274
275
  /**
276
   * Eagerly styles a subtree of unstyled nodes that was just appended to the
277
   * tree. This is used in situations where we need the style immediately and
278
   * cannot wait for a future batch restyle.
279
   */
280
  void StyleNewSubtree(dom::Element* aRoot);
281
282
  /**
283
   * Helper for correctly calling UpdateStylist without paying the cost of an
284
   * extra function call in the common no-rebuild-needed case.
285
   */
286
  void UpdateStylistIfNeeded()
287
0
  {
288
0
    if (StylistNeedsUpdate()) {
289
0
      UpdateStylist();
290
0
    }
291
0
  }
292
293
  /**
294
   * Checks whether the rule tree has crossed its threshold for unused nodes,
295
   * and if so, frees them.
296
   */
297
  void MaybeGCRuleTree();
298
299
  /**
300
   * Returns true if the given element may be used as the root of a style
301
   * traversal. Reasons for false include having an unstyled parent, or having
302
   * a parent that is display:none.
303
   *
304
   * Most traversal callsites don't need to check this, but some do.
305
   */
306
  static bool MayTraverseFrom(const dom::Element* aElement);
307
308
#ifdef DEBUG
309
  void AssertTreeIsClean();
310
#else
311
0
  void AssertTreeIsClean() {}
312
#endif
313
314
  /**
315
   * Clears any cached style data that may depend on all sorts of computed
316
   * values.
317
   *
318
   * Right now this clears the non-inheriting ComputedStyle cache, and resets
319
   * the default computed values.
320
   *
321
   * This does _not_, however, clear the stylist.
322
   */
323
  void ClearCachedStyleData();
324
325
  /**
326
   * Notifies the Servo stylesheet that the document's compatibility mode has changed.
327
   */
328
  void CompatibilityModeChanged();
329
330
  /**
331
   * Resolve style for the given element, and return it as a
332
   * ComputedStyle.
333
   *
334
   * FIXME(emilio): Is there a point in this after bug 1367904?
335
   */
336
  inline already_AddRefed<ComputedStyle> ResolveServoStyle(const dom::Element&);
337
338
  bool GetKeyframesForName(const dom::Element&,
339
                           const ComputedStyle&,
340
                           nsAtom* aName,
341
                           const nsTimingFunction& aTimingFunction,
342
                           nsTArray<Keyframe>& aKeyframes);
343
344
  nsTArray<ComputedKeyframeValues>
345
  GetComputedKeyframeValuesFor(const nsTArray<Keyframe>& aKeyframes,
346
                               dom::Element* aElement,
347
                               const ComputedStyle* aStyle);
348
349
  void
350
  GetAnimationValues(RawServoDeclarationBlock* aDeclarations,
351
                     dom::Element* aElement,
352
                     const mozilla::ComputedStyle* aStyle,
353
                     nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues);
354
355
  bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
356
357
  const RawServoCounterStyleRule* CounterStyleRuleForName(nsAtom* aName);
358
359
  // Get all the currently-active font feature values set.
360
  already_AddRefed<gfxFontFeatureValueSet> BuildFontFeatureValueSet();
361
362
  already_AddRefed<ComputedStyle>
363
  GetBaseContextForElement(dom::Element* aElement,
364
                           const ComputedStyle* aStyle);
365
366
  // Get a ComputedStyle that represents |aStyle|, but as though it additionally
367
  // matched the rules of the newly added |aAnimaitonaValue|.
368
  //
369
  // We use this function to temporarily generate a ComputedStyle for
370
  // calculating the cumulative change hints.
371
  //
372
  // This must hold:
373
  //   The additional rules must be appropriate for the transition
374
  //   level of the cascade, which is the highest level of the cascade.
375
  //   (This is the case for one current caller, the cover rule used
376
  //   for CSS transitions.)
377
  // Note: |aElement| should be the generated element if it is pseudo.
378
  already_AddRefed<ComputedStyle>
379
  ResolveServoStyleByAddingAnimation(dom::Element* aElement,
380
                                     const ComputedStyle* aStyle,
381
                                     RawServoAnimationValue* aAnimationValue);
382
  /**
383
   * Resolve style for a given declaration block with/without the parent style.
384
   * If the parent style is not specified, the document default computed values
385
   * is used.
386
   */
387
  already_AddRefed<ComputedStyle>
388
  ResolveForDeclarations(const ComputedStyle* aParentOrNull,
389
                         RawServoDeclarationBlockBorrowed aDeclarations);
390
391
  already_AddRefed<RawServoAnimationValue>
392
  ComputeAnimationValue(dom::Element* aElement,
393
                        RawServoDeclarationBlock* aDeclaration,
394
                        const mozilla::ComputedStyle* aStyle);
395
396
  void AppendTask(PostTraversalTask aTask)
397
0
  {
398
0
    MOZ_ASSERT(IsInServoTraversal());
399
0
400
0
    // We currently only use PostTraversalTasks while the Servo font metrics
401
0
    // mutex is locked.  If we need to use them in other situations during
402
0
    // a traversal, we should assert that we've taken appropriate
403
0
    // synchronization measures.
404
0
    AssertIsMainThreadOrServoFontMetricsLocked();
405
0
406
0
    mPostTraversalTasks.AppendElement(aTask);
407
0
  }
408
409
  // Returns true if a restyle of the document is needed due to cloning
410
  // sheet inners.
411
  bool EnsureUniqueInnerOnCSSSheets();
412
413
  // Called by StyleSheet::EnsureUniqueInner to let us know it cloned
414
  // its inner.
415
0
  void SetNeedsRestyleAfterEnsureUniqueInner() {
416
0
    mNeedsRestyleAfterEnsureUniqueInner = true;
417
0
  }
418
419
  // Returns the style rule map.
420
  ServoStyleRuleMap* StyleRuleMap();
421
422
  /**
423
   * Returns true if a modification to an an attribute with the specified
424
   * local name might require us to restyle the element.
425
   *
426
   * This function allows us to skip taking a an attribute snapshot when
427
   * the modified attribute doesn't appear in an attribute selector in
428
   * a style sheet.
429
   */
430
  bool MightHaveAttributeDependency(const dom::Element&, nsAtom* aAttribute) const;
431
432
  /**
433
   * Returns true if a change in event state on an element might require
434
   * us to restyle the element.
435
   *
436
   * This function allows us to skip taking a state snapshot when
437
   * the changed state isn't depended upon by any pseudo-class selectors
438
   * in a style sheet.
439
   */
440
  bool HasStateDependency(const dom::Element&, EventStates) const;
441
442
  /**
443
   * Returns true if a change in document state might require us to restyle the
444
   * document.
445
   */
446
  bool HasDocumentStateDependency(EventStates aState) const;
447
448
  /**
449
   * Get a new ComputedStyle that uses the same rules as the given ComputedStyle
450
   * but has a different parent.
451
   *
452
   * aElement is non-null if this is a ComputedStyle for a frame whose mContent
453
   * is an element and which has no pseudo on its ComputedStyle (so it's the
454
   * actual style for the element being passed).
455
   */
456
  already_AddRefed<ComputedStyle>
457
  ReparentComputedStyle(ComputedStyle* aComputedStyle,
458
                        ComputedStyle* aNewParent,
459
                        ComputedStyle* aNewParentIgnoringFirstLine,
460
                        ComputedStyle* aNewLayoutParent,
461
                        dom::Element* aElement);
462
463
private:
464
  friend class AutoSetInServoTraversal;
465
  friend class AutoPrepareTraversal;
466
467
  bool ShouldTraverseInParallel() const;
468
469
  /**
470
   * Gets the pending snapshots to handle from the restyle manager.
471
   */
472
  const SnapshotTable& Snapshots();
473
474
  /**
475
   * Resolve all DeclarationBlocks attached to mapped
476
   * presentation attributes cached on the document.
477
   *
478
   * Call this before jumping into Servo's style system.
479
   */
480
  void ResolveMappedAttrDeclarationBlocks();
481
482
  /**
483
   * Clear our cached mNonInheritingComputedStyles.
484
   *
485
   * We do this when we want to make sure those ComputedStyles won't live too
486
   * long (e.g. when rebuilding all style data or when shutting down the style
487
   * set).
488
   */
489
  void ClearNonInheritingComputedStyles();
490
491
  /**
492
   * Perform processes that we should do before traversing.
493
   *
494
   * When aRoot is null, the entire document is pre-traversed.  Otherwise,
495
   * only the subtree rooted at aRoot is pre-traversed.
496
   */
497
  void PreTraverse(ServoTraversalFlags aFlags,
498
                   dom::Element* aRoot = nullptr);
499
500
  // Subset of the pre-traverse steps that involve syncing up data
501
  void PreTraverseSync();
502
503
  /**
504
   * Records that the contents of style sheets at the specified origin have
505
   * changed since the last.  Calling this will ensure that the Stylist
506
   * rebuilds its selector maps.
507
   */
508
  void MarkOriginsDirty(OriginFlags aChangedOrigins);
509
510
  /**
511
   * Note that the stylist needs a style flush due to style sheet changes.
512
   */
513
  void SetStylistStyleSheetsDirty();
514
515
  void SetStylistXBLStyleSheetsDirty();
516
517
  bool StylistNeedsUpdate() const
518
0
  {
519
0
    return mStylistState != StylistState::NotDirty;
520
0
  }
521
522
  /**
523
   * Update the stylist as needed to ensure style data is up-to-date.
524
   *
525
   * This should only be called if StylistNeedsUpdate returns true.
526
   */
527
  void UpdateStylist();
528
529
  already_AddRefed<ComputedStyle>
530
    ResolveStyleLazilyInternal(dom::Element* aElement,
531
                               CSSPseudoElementType aPseudoType,
532
                               StyleRuleInclusion aRules =
533
                                 StyleRuleInclusion::All);
534
535
  void RunPostTraversalTasks();
536
537
  void PrependSheetOfType(SheetType aType,
538
                          StyleSheet* aSheet);
539
540
  void AppendSheetOfType(SheetType aType,
541
                         StyleSheet* aSheet);
542
543
  void InsertSheetOfType(SheetType aType,
544
                         StyleSheet* aSheet,
545
                         StyleSheet* aBeforeSheet);
546
547
  void RemoveSheetOfType(SheetType aType,
548
                         StyleSheet* aSheet);
549
550
  // The owner document of this style set. Null if this is an XBL style set.
551
  //
552
  // TODO(emilio): This should become a DocumentOrShadowRoot, and be owned by it
553
  // directly instead of the shell, eventually.
554
  nsIDocument* mDocument;
555
556
0
  const nsPresContext* GetPresContext() const {
557
0
    return const_cast<ServoStyleSet*>(this)->GetPresContext();
558
0
  }
559
560
  /**
561
   * Return the associated pres context if we're the master style set and we
562
   * have an associated pres shell.
563
   */
564
  nsPresContext* GetPresContext();
565
566
  UniquePtr<RawServoStyleSet> mRawSet;
567
  EnumeratedArray<SheetType, SheetType::Count,
568
                  nsTArray<RefPtr<StyleSheet>>> mSheets;
569
  bool mAuthorStyleDisabled;
570
  StylistState mStylistState;
571
  uint64_t mUserFontSetUpdateGeneration;
572
573
  bool mNeedsRestyleAfterEnsureUniqueInner;
574
575
  // Stores pointers to our cached ComputedStyles for non-inheriting anonymous
576
  // boxes.
577
  EnumeratedArray<nsCSSAnonBoxes::NonInheriting,
578
                  nsCSSAnonBoxes::NonInheriting::_Count,
579
                  RefPtr<ComputedStyle>> mNonInheritingComputedStyles;
580
581
  // Tasks to perform after a traversal, back on the main thread.
582
  //
583
  // These are similar to Servo's SequentialTasks, except that they are
584
  // posted by C++ code running on style worker threads.
585
  nsTArray<PostTraversalTask> mPostTraversalTasks;
586
587
  // Map from raw Servo style rule to Gecko's wrapper object.
588
  // Constructed lazily when requested by devtools.
589
  UniquePtr<ServoStyleRuleMap> mStyleRuleMap;
590
};
591
592
class UACacheReporter final : public nsIMemoryReporter
593
{
594
  NS_DECL_ISUPPORTS
595
  NS_DECL_NSIMEMORYREPORTER
596
597
private:
598
0
  ~UACacheReporter() {}
599
};
600
601
} // namespace mozilla
602
603
#endif // mozilla_ServoStyleSet_h