Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/RestyleManager.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_RestyleManager_h
8
#define mozilla_RestyleManager_h
9
10
#include "mozilla/AutoRestore.h"
11
#include "mozilla/EventStates.h"
12
#include "mozilla/Maybe.h"
13
#include "mozilla/OverflowChangedTracker.h"
14
#include "mozilla/ServoElementSnapshot.h"
15
#include "mozilla/ServoElementSnapshotTable.h"
16
#include "nsChangeHint.h"
17
#include "nsPresContext.h"
18
#include "nsStringFwd.h"
19
20
class nsAttrValue;
21
class nsCSSFrameConstructor;
22
class nsAtom;
23
class nsIContent;
24
class nsIFrame;
25
class nsStyleChangeList;
26
class nsStyleChangeList;
27
28
namespace mozilla {
29
30
class EventStates;
31
class ServoStyleSet;
32
33
namespace dom {
34
class Element;
35
}
36
37
/**
38
 * A stack class used to pass some common restyle state in a slightly more
39
 * comfortable way than a bunch of individual arguments, and that also checks
40
 * that the change hint used for optimization is correctly used in debug mode.
41
 */
42
class ServoRestyleState
43
{
44
public:
45
  ServoRestyleState(ServoStyleSet& aStyleSet,
46
                    nsStyleChangeList& aChangeList,
47
                    nsTArray<nsIFrame*>& aPendingWrapperRestyles)
48
    : mStyleSet(aStyleSet)
49
    , mChangeList(aChangeList)
50
    , mPendingWrapperRestyles(aPendingWrapperRestyles)
51
    , mPendingWrapperRestyleOffset(aPendingWrapperRestyles.Length())
52
    , mChangesHandled(nsChangeHint(0))
53
#ifdef DEBUG
54
    // If !mOwner, then we wouldn't have processed our wrapper restyles, because
55
    // we only process those when handling an element with a frame.  But that's
56
    // OK, because if we started our traversal at an element with no frame
57
    // (e.g. it's display:contents), that means the wrapper frames in our list
58
    // actually inherit from one of its ancestors, not from it, and hence not
59
    // restyling them is OK.
60
    , mAssertWrapperRestyleLength(false)
61
#endif // DEBUG
62
0
  {}
63
64
  // We shouldn't assume that changes handled from our parent are handled for
65
  // our children too if we're out of flow since they aren't necessarily
66
  // parented in DOM order, and thus a change handled by a DOM ancestor doesn't
67
  // necessarily mean that it's handled for an ancestor frame.
68
  enum class Type
69
  {
70
    InFlow,
71
    OutOfFlow,
72
  };
73
74
  ServoRestyleState(const nsIFrame& aOwner,
75
                    ServoRestyleState& aParentState,
76
                    nsChangeHint aHintForThisFrame,
77
                    Type aType,
78
                    bool aAssertWrapperRestyleLength = true)
79
    : mStyleSet(aParentState.mStyleSet)
80
    , mChangeList(aParentState.mChangeList)
81
    , mPendingWrapperRestyles(aParentState.mPendingWrapperRestyles)
82
    , mPendingWrapperRestyleOffset(aParentState.mPendingWrapperRestyles.Length())
83
    , mChangesHandled(
84
        aType == Type::InFlow
85
          ? aParentState.mChangesHandled | aHintForThisFrame
86
          : aHintForThisFrame)
87
#ifdef DEBUG
88
    , mOwner(&aOwner)
89
    , mAssertWrapperRestyleLength(aAssertWrapperRestyleLength)
90
#endif
91
0
  {
92
0
    if (aType == Type::InFlow) {
93
0
      AssertOwner(aParentState);
94
0
    }
95
0
  }
96
97
0
  ~ServoRestyleState() {
98
0
    MOZ_ASSERT(!mAssertWrapperRestyleLength ||
99
0
               mPendingWrapperRestyles.Length() == mPendingWrapperRestyleOffset,
100
0
               "Someone forgot to call ProcessWrapperRestyles!");
101
0
  }
102
103
0
  nsStyleChangeList& ChangeList() { return mChangeList; }
104
0
  ServoStyleSet& StyleSet() { return mStyleSet; }
105
106
#ifdef DEBUG
107
  void AssertOwner(const ServoRestyleState& aParentState) const;
108
  nsChangeHint ChangesHandledFor(const nsIFrame*) const;
109
#else
110
0
  void AssertOwner(const ServoRestyleState&) const {}
111
  nsChangeHint ChangesHandledFor(const nsIFrame*) const
112
0
  {
113
0
    return mChangesHandled;
114
0
  }
115
#endif
116
117
  // Add a pending wrapper restyle.  We don't have to do anything if the thing
118
  // being added is already last in the list, but otherwise we do want to add
119
  // it, in order for ProcessWrapperRestyles to work correctly.
120
  void AddPendingWrapperRestyle(nsIFrame* aWrapperFrame);
121
122
  // Process wrapper restyles for this restyle state.  This should be done
123
  // before it comes off the stack.
124
  void ProcessWrapperRestyles(nsIFrame* aParentFrame);
125
126
  // Get the table-aware parent for the given child.  This will walk through
127
  // outer table and cellcontent frames.
128
  static nsIFrame* TableAwareParentFor(const nsIFrame* aChild);
129
130
private:
131
  // Process a wrapper restyle at the given index, and restyles for any
132
  // wrappers nested in it.  Returns the number of entries from
133
  // mPendingWrapperRestyles that we processed.  The return value is always at
134
  // least 1.
135
  size_t ProcessMaybeNestedWrapperRestyle(nsIFrame* aParent, size_t aIndex);
136
137
  ServoStyleSet& mStyleSet;
138
  nsStyleChangeList& mChangeList;
139
140
  // A list of pending wrapper restyles.  Anonymous box wrapper frames that need
141
  // restyling are added to this list when their non-anonymous kids are
142
  // restyled.  This avoids us having to do linear searches along the frame tree
143
  // for these anonymous boxes.  The problem then becomes that we can have
144
  // multiple kids all with the same anonymous parent, and we don't want to
145
  // restyle it more than once.  We use mPendingWrapperRestyles to track which
146
  // anonymous wrapper boxes we've requested be restyled and which of them have
147
  // already been restyled.  We use a single array propagated through
148
  // ServoRestyleStates by reference, because in a situation like this:
149
  //
150
  //  <div style="display: table"><span></span></div>
151
  //
152
  // We have multiple wrappers to restyle (cell, row, table-row-group) and we
153
  // want to add them in to the list all at once but restyle them using
154
  // different ServoRestyleStates with different owners.  When this situation
155
  // occurs, the relevant frames will be placed in the array with ancestors
156
  // before descendants.
157
  nsTArray<nsIFrame*>& mPendingWrapperRestyles;
158
159
  // Since we're given a possibly-nonempty mPendingWrapperRestyles to start
160
  // with, we need to keep track of where the part of it we're responsible for
161
  // starts.
162
  size_t mPendingWrapperRestyleOffset;
163
164
  const nsChangeHint mChangesHandled;
165
166
  // We track the "owner" frame of this restyle state, that is, the frame that
167
  // generated the last change that is stored in mChangesHandled, in order to
168
  // verify that we only use mChangesHandled for actual descendants of that
169
  // frame (given DOM order isn't always frame order, and that there are a few
170
  // special cases for stuff like wrapper frames, ::backdrop, and so on).
171
#ifdef DEBUG
172
  const nsIFrame* mOwner { nullptr };
173
#endif
174
175
  // Whether we should assert in our destructor that we've processed all of the
176
  // relevant wrapper restyles.
177
#ifdef DEBUG
178
  const bool mAssertWrapperRestyleLength;
179
#endif // DEBUG
180
};
181
182
enum class ServoPostTraversalFlags : uint32_t;
183
184
class RestyleManager
185
{
186
  friend class ServoStyleSet;
187
188
public:
189
  typedef ServoElementSnapshotTable SnapshotTable;
190
  typedef mozilla::dom::Element Element;
191
192
  // Get an integer that increments every time we process pending restyles.
193
  // The value is never 0.
194
0
  uint64_t GetRestyleGeneration() const { return mRestyleGeneration; }
195
  // Unlike GetRestyleGeneration, which means the actual restyling count,
196
  // GetUndisplayedRestyleGeneration represents any possible DOM changes that
197
  // can cause restyling. This is needed for getComputedStyle to work with
198
  // non-styled (e.g. display: none) elements.
199
0
  uint64_t GetUndisplayedRestyleGeneration() const {
200
0
    return mUndisplayedRestyleGeneration;
201
0
  }
202
203
0
  void Disconnect() { mPresContext = nullptr; }
204
205
  ~RestyleManager()
206
0
  {
207
0
    MOZ_ASSERT(!mAnimationsWithDestroyedFrame,
208
0
               "leaving dangling pointers from AnimationsWithDestroyedFrame");
209
0
    MOZ_ASSERT(!mReentrantChanges);
210
0
  }
211
212
  static nsCString RestyleHintToString(nsRestyleHint aHint);
213
214
#ifdef DEBUG
215
  static nsCString ChangeHintToString(nsChangeHint aHint);
216
217
  /**
218
   * DEBUG ONLY method to verify integrity of style tree versus frame tree
219
   */
220
  void DebugVerifyStyleTree(nsIFrame* aFrame);
221
#endif
222
223
0
  void FlushOverflowChangedTracker() {
224
0
    mOverflowChangedTracker.Flush();
225
0
  }
226
227
  // Should be called when a frame is going to be destroyed and
228
  // WillDestroyFrameTree hasn't been called yet.
229
0
  void NotifyDestroyingFrame(nsIFrame* aFrame) {
230
0
    mOverflowChangedTracker.RemoveFrame(aFrame);
231
0
    // If ProcessRestyledFrames is tracking frames which have been
232
0
    // destroyed (to avoid re-visiting them), add this one to its set.
233
0
    if (mDestroyedFrames) {
234
0
      mDestroyedFrames->PutEntry(aFrame);
235
0
    }
236
0
  }
237
238
  // Note: It's the caller's responsibility to make sure to wrap a
239
  // ProcessRestyledFrames call in a view update batch and a script blocker.
240
  // This function does not call ProcessAttachedQueue() on the binding manager.
241
  // If the caller wants that to happen synchronously, it needs to handle that
242
  // itself.
243
  void ProcessRestyledFrames(nsStyleChangeList& aChangeList);
244
245
0
  bool IsInStyleRefresh() const { return mInStyleRefresh; }
246
247
  // AnimationsWithDestroyedFrame is used to stop animations and transitions
248
  // on elements that have no frame at the end of the restyling process.
249
  // It only lives during the restyling process.
250
  class MOZ_STACK_CLASS AnimationsWithDestroyedFrame final {
251
  public:
252
    // Construct a AnimationsWithDestroyedFrame object.  The caller must
253
    // ensure that aRestyleManager lives at least as long as the
254
    // object.  (This is generally easy since the caller is typically a
255
    // method of RestyleManager.)
256
    explicit AnimationsWithDestroyedFrame(RestyleManager* aRestyleManager);
257
258
    // This method takes the content node for the generated content for
259
    // animation/transition on ::before and ::after, rather than the
260
    // content node for the real element.
261
0
    void Put(nsIContent* aContent, ComputedStyle* aComputedStyle) {
262
0
      MOZ_ASSERT(aContent);
263
0
      CSSPseudoElementType pseudoType = aComputedStyle->GetPseudoType();
264
0
      if (pseudoType == CSSPseudoElementType::NotPseudo) {
265
0
        mContents.AppendElement(aContent);
266
0
      } else if (pseudoType == CSSPseudoElementType::before) {
267
0
        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
268
0
                     nsGkAtoms::mozgeneratedcontentbefore);
269
0
        mBeforeContents.AppendElement(aContent->GetParent());
270
0
      } else if (pseudoType == CSSPseudoElementType::after) {
271
0
        MOZ_ASSERT(aContent->NodeInfo()->NameAtom() ==
272
0
                     nsGkAtoms::mozgeneratedcontentafter);
273
0
        mAfterContents.AppendElement(aContent->GetParent());
274
0
      }
275
0
    }
276
277
    void StopAnimationsForElementsWithoutFrames();
278
279
  private:
280
    void StopAnimationsWithoutFrame(nsTArray<RefPtr<nsIContent>>& aArray,
281
                                    CSSPseudoElementType aPseudoType);
282
283
    RestyleManager* mRestyleManager;
284
    AutoRestore<AnimationsWithDestroyedFrame*> mRestorePointer;
285
286
    // Below three arrays might include elements that have already had their
287
    // animations or transitions stopped.
288
    //
289
    // mBeforeContents and mAfterContents hold the real element rather than
290
    // the content node for the generated content (which might change during
291
    // a reframe)
292
    nsTArray<RefPtr<nsIContent>> mContents;
293
    nsTArray<RefPtr<nsIContent>> mBeforeContents;
294
    nsTArray<RefPtr<nsIContent>> mAfterContents;
295
  };
296
297
  /**
298
   * Return the current AnimationsWithDestroyedFrame struct, or null if we're
299
   * not currently in a restyling operation.
300
   */
301
0
  AnimationsWithDestroyedFrame* GetAnimationsWithDestroyedFrame() {
302
0
    return mAnimationsWithDestroyedFrame;
303
0
  }
304
305
  void ContentInserted(nsIContent* aChild);
306
  void ContentAppended(nsIContent* aFirstNewContent);
307
308
  // This would be have the same logic as RestyleForInsertOrChange if we got the
309
  // notification before the removal.  However, we get it after, so we need the
310
  // following sibling in addition to the old child.
311
  //
312
  // aFollowingSibling is the sibling that used to come after aOldChild before
313
  // the removal.
314
  void ContentRemoved(nsIContent* aOldChild, nsIContent* aFollowingSibling);
315
316
  // Restyling for a ContentInserted (notification after insertion) or
317
  // for some CharacterDataChanged.
318
  void RestyleForInsertOrChange(nsIContent* aChild);
319
320
  // Restyle for a CharacterDataChanged notification. In practice this can only
321
  // affect :empty / :-moz-only-whitespace / :-moz-first-node / :-moz-last-node.
322
  void CharacterDataChanged(nsIContent*, const CharacterDataChangeInfo&);
323
324
  void PostRestyleEvent(dom::Element*, nsRestyleHint, nsChangeHint aMinChangeHint);
325
326
  /**
327
   * Posts restyle hints for animations.
328
   * This is only called for the second traversal for CSS animations during
329
   * updating CSS animations in a SequentialTask.
330
   * This function does neither register a refresh observer nor flag that a
331
   * style flush is needed since this function is supposed to be called during
332
   * restyling process and this restyle event will be processed in the second
333
   * traversal of the same restyling process.
334
   */
335
  void PostRestyleEventForAnimations(dom::Element*,
336
                                     CSSPseudoElementType,
337
                                     nsRestyleHint);
338
339
  void NextRestyleIsForCSSRuleChanges()
340
0
  {
341
0
    mRestyleForCSSRuleChanges = true;
342
0
  }
343
344
  void RebuildAllStyleData(nsChangeHint aExtraHint, nsRestyleHint aRestyleHint);
345
  void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
346
                                    nsRestyleHint aRestyleHint);
347
348
  void ProcessPendingRestyles();
349
  void ProcessAllPendingAttributeAndStateInvalidations();
350
351
  void ContentStateChanged(nsIContent* aContent, EventStates aStateMask);
352
  void AttributeWillChange(Element* aElement,
353
                           int32_t aNameSpaceID,
354
                           nsAtom* aAttribute,
355
                           int32_t aModType,
356
                           const nsAttrValue* aNewValue);
357
  void ClassAttributeWillBeChangedBySMIL(dom::Element* aElement);
358
  void AttributeChanged(dom::Element* aElement,
359
                        int32_t aNameSpaceID,
360
                        nsAtom* aAttribute,
361
                        int32_t aModType,
362
                        const nsAttrValue* aOldValue);
363
364
  // This is only used to reparent things when moving them in/out of the
365
  // ::first-line.
366
  void ReparentComputedStyleForFirstLine(nsIFrame*);
367
368
  bool HasPendingRestyleAncestor(dom::Element* aElement) const;
369
370
371
  /**
372
   * Performs a Servo animation-only traversal to compute style for all nodes
373
   * with the animation-only dirty bit in the document.
374
   *
375
   * This processes just the traversal for animation-only restyles and skips the
376
   * normal traversal for other restyles unrelated to animations.
377
   * This is used to bring throttled animations up-to-date such as when we need
378
   * to get correct position for transform animations that are throttled because
379
   * they are running on the compositor.
380
   *
381
   * This will traverse all of the document's style roots (that is, its document
382
   * element, and the roots of the document-level native anonymous content).
383
   */
384
  void UpdateOnlyAnimationStyles();
385
386
  // Get a counter that increments on every style change, that we use to
387
  // track whether off-main-thread animations are up-to-date.
388
0
  uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
389
390
  static uint64_t GetAnimationGenerationForFrame(nsIFrame* aFrame);
391
392
  // Update the animation generation count to mark that animation state
393
  // has changed.
394
  //
395
  // This is normally performed automatically by ProcessPendingRestyles
396
  // but it is also called when we have out-of-band changes to animations
397
  // such as changes made through the Web Animations API.
398
  void IncrementAnimationGeneration();
399
400
  // Apply change hints for animations on the compositor.
401
  //
402
  // There are some cases where we forcibly apply change hints for animations
403
  // even if there is no change hint produced in order to synchronize with
404
  // animations running on the compositor.
405
  //
406
  // For example:
407
  //
408
  // a) Pausing animations via the Web Animations API
409
  // b) When the style before sending the animation to the compositor exactly
410
  // the same as the current style
411
  static void AddLayerChangesForAnimation(nsIFrame* aFrame,
412
                                          nsIContent* aContent,
413
                                          nsChangeHint aHintForThisFrame,
414
                                          nsStyleChangeList&
415
                                            aChangeListToProcess);
416
417
  /**
418
   * Whether to clear all the style data (including the element itself), or just
419
   * the descendants' data.
420
   */
421
  enum class IncludeRoot {
422
    Yes,
423
    No,
424
  };
425
426
  /**
427
   * Clears the ServoElementData and HasDirtyDescendants from all elements
428
   * in the subtree rooted at aElement.
429
   */
430
  static void ClearServoDataFromSubtree(Element*, IncludeRoot = IncludeRoot::Yes);
431
432
  /**
433
   * Clears HasDirtyDescendants and RestyleData from all elements in the
434
   * subtree rooted at aElement.
435
   */
436
  static void ClearRestyleStateFromSubtree(Element* aElement);
437
438
  explicit RestyleManager(nsPresContext* aPresContext);
439
440
protected:
441
  /**
442
   * Reparent the descendants of aFrame.  This is used by ReparentComputedStyle
443
   * and shouldn't be called by anyone else.  aProviderChild, if non-null, is a
444
   * child that was the style parent for aFrame and hence shouldn't be
445
   * reparented.
446
   */
447
  void ReparentFrameDescendants(nsIFrame* aFrame, nsIFrame* aProviderChild,
448
                                ServoStyleSet& aStyleSet);
449
450
  /**
451
   * Performs post-Servo-traversal processing on this element and its
452
   * descendants.
453
   *
454
   * Returns whether any style did actually change. There may be cases where we
455
   * didn't need to change any style after all, for example, when a content
456
   * attribute changes that happens not to have any effect on the style of that
457
   * element or any descendant or sibling.
458
   */
459
  bool ProcessPostTraversal(Element* aElement,
460
                            ComputedStyle* aParentContext,
461
                            ServoRestyleState& aRestyleState,
462
                            ServoPostTraversalFlags aFlags);
463
464
  struct TextPostTraversalState;
465
  bool ProcessPostTraversalForText(nsIContent* aTextNode,
466
                                   TextPostTraversalState& aState,
467
                                   ServoRestyleState& aRestyleState,
468
                                   ServoPostTraversalFlags aFlags);
469
470
0
  ServoStyleSet* StyleSet() const { return PresContext()->StyleSet(); }
471
472
  void RestyleForEmptyChange(Element* aContainer);
473
  void MaybeRestyleForEdgeChildChange(Element* aContainer, nsIContent* aChangedChild);
474
475
  // TODO(emilio): there's no good reason this isn't part of ContentStateChanged
476
  // now, or the change hint isn't returned instead of via an out-param, really.
477
  void ContentStateChangedInternal(const Element&,
478
                                   EventStates aStateMask,
479
                                   nsChangeHint* aOutChangeHint);
480
481
0
  bool IsDisconnected() const { return !mPresContext; }
482
483
0
  void IncrementRestyleGeneration() {
484
0
    if (++mRestyleGeneration == 0) {
485
0
      // Keep mRestyleGeneration from being 0, since that's what
486
0
      // nsPresContext::GetRestyleGeneration returns when it no
487
0
      // longer has a RestyleManager.
488
0
      ++mRestyleGeneration;
489
0
    }
490
0
    IncrementUndisplayedRestyleGeneration();
491
0
  }
492
493
0
  void IncrementUndisplayedRestyleGeneration() {
494
0
    if (++mUndisplayedRestyleGeneration == 0) {
495
0
      // Ensure mUndisplayedRestyleGeneration > 0, for the same reason as
496
0
      // IncrementRestyleGeneration.
497
0
      ++mUndisplayedRestyleGeneration;
498
0
    }
499
0
  }
500
501
0
  nsPresContext* PresContext() const {
502
0
    MOZ_ASSERT(mPresContext);
503
0
    return mPresContext;
504
0
  }
505
506
0
  nsCSSFrameConstructor* FrameConstructor() const {
507
0
    return PresContext()->FrameConstructor();
508
0
  }
509
510
private:
511
  nsPresContext* mPresContext; // weak, can be null after Disconnect().
512
  uint64_t mRestyleGeneration;
513
  uint64_t mUndisplayedRestyleGeneration;
514
515
  // Used to keep track of frames that have been destroyed during
516
  // ProcessRestyledFrames, so we don't try to touch them again even if
517
  // they're referenced again later in the changelist.
518
  mozilla::UniquePtr<nsTHashtable<nsPtrHashKey<const nsIFrame>>> mDestroyedFrames;
519
520
protected:
521
  // True if we're in the middle of a nsRefreshDriver refresh
522
  bool mInStyleRefresh;
523
524
  // The total number of animation flushes by this frame constructor.
525
  // Used to keep the layer and animation manager in sync.
526
  uint64_t mAnimationGeneration;
527
528
  OverflowChangedTracker mOverflowChangedTracker;
529
530
  AnimationsWithDestroyedFrame* mAnimationsWithDestroyedFrame = nullptr;
531
532
0
  const SnapshotTable& Snapshots() const { return mSnapshots; }
533
  void ClearSnapshots();
534
  ServoElementSnapshot& SnapshotFor(Element&);
535
  void TakeSnapshotForAttributeChange(Element&,
536
                                      int32_t aNameSpaceID,
537
                                      nsAtom* aAttribute);
538
539
  void DoProcessPendingRestyles(ServoTraversalFlags aFlags);
540
541
  // Function to do the actual (recursive) work of
542
  // ReparentComputedStyleForFirstLine, once we have asserted the invariants
543
  // that only hold on the initial call.
544
  void DoReparentComputedStyleForFirstLine(nsIFrame*, ServoStyleSet&);
545
546
  // We use a separate data structure from nsStyleChangeList because we need a
547
  // frame to create nsStyleChangeList entries, and the primary frame may not be
548
  // attached yet.
549
  struct ReentrantChange {
550
    nsCOMPtr<nsIContent> mContent;
551
    nsChangeHint mHint;
552
  };
553
  typedef AutoTArray<ReentrantChange, 10> ReentrantChangeList;
554
555
  // Only non-null while processing change hints. See the comment in
556
  // ProcessPendingRestyles.
557
  ReentrantChangeList* mReentrantChanges = nullptr;
558
559
  // We use this flag to track if the current restyle contains any non-animation
560
  // update, which triggers a normal restyle, and so there might be any new
561
  // transition created later. Therefore, if this flag is true, we need to
562
  // increase mAnimationGeneration before creating new transitions, so their
563
  // creation sequence will be correct.
564
  bool mHaveNonAnimationRestyles = false;
565
566
  // Set to true when posting restyle events triggered by CSS rule changes.
567
  // This flag is cleared once ProcessPendingRestyles has completed.
568
  // When we process a traversal all descendants elements of the document
569
  // triggered by CSS rule changes, we will need to update all elements with
570
  // CSS animations.  We propagate TraversalRestyleBehavior::ForCSSRuleChanges
571
  // to traversal function if this flag is set.
572
  bool mRestyleForCSSRuleChanges = false;
573
574
  // A hashtable with the elements that have changed state or attributes, in
575
  // order to calculate restyle hints during the traversal.
576
  SnapshotTable mSnapshots;
577
578
};
579
580
} // namespace mozilla
581
582
#endif