Bug 1445794 Part 2 - Disallow flushing layout in reflow and scroll related callbacks. r=emilio
authorTing-Yu Lin <aethanyc@gmail.com>
Thu, 03 Jan 2019 10:52:51 +0000
changeset 509574 267a452439f57efafc138d7a03effa73c23adf0d
parent 509573 34151b0c56e9cdd7c8df1b613fca55900f3274e1
child 509575 43e54d35e5211330e99db33b1e265b70b1c8eb6f
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1445794
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1445794 Part 2 - Disallow flushing layout in reflow and scroll related callbacks. r=emilio By disallowing flushing layout in AccessibleCaret's callbacks, we don't need to worry about dead PresShell affect other callbacks in the system. Differential Revision: https://phabricator.services.mozilla.com/D15537
layout/base/AccessibleCaretManager.cpp
layout/base/AccessibleCaretManager.h
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -574,30 +574,36 @@ nsresult AccessibleCaretManager::SelectW
   ProvideHapticFeedback();
 
   return rv;
 }
 
 void AccessibleCaretManager::OnScrollStart() {
   AC_LOG("%s", __FUNCTION__);
 
+  AutoRestore<bool> saveAllowFlushingLayout(mAllowFlushingLayout);
+  mAllowFlushingLayout = false;
+
   mIsScrollStarted = true;
 
   if (mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible()) {
     // Dispatch the event only if one of the carets is logically visible like in
     // HideCarets().
     DispatchCaretStateChangedEvent(CaretChangedReason::Scroll);
   }
 }
 
 void AccessibleCaretManager::OnScrollEnd() {
   if (mLastUpdateCaretMode != GetCaretMode()) {
     return;
   }
 
+  AutoRestore<bool> saveAllowFlushingLayout(mAllowFlushingLayout);
+  mAllowFlushingLayout = false;
+
   mIsScrollStarted = false;
 
   if (GetCaretMode() == CaretMode::Cursor) {
     if (!mFirstCaret->IsLogicallyVisible()) {
       // If the caret is hidden (Appearance::None) due to blur, no
       // need to update it.
       return;
     }
@@ -615,16 +621,19 @@ void AccessibleCaretManager::OnScrollEnd
   UpdateCarets();
 }
 
 void AccessibleCaretManager::OnScrollPositionChanged() {
   if (mLastUpdateCaretMode != GetCaretMode()) {
     return;
   }
 
+  AutoRestore<bool> saveAllowFlushingLayout(mAllowFlushingLayout);
+  mAllowFlushingLayout = false;
+
   if (mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible()) {
     if (mIsScrollStarted) {
       // We don't want extra CaretStateChangedEvents dispatched when user is
       // scrolling the page.
       AC_LOG("%s: UpdateCarets(RespectOldAppearance | DispatchNoEvent)",
              __FUNCTION__);
       UpdateCarets({UpdateCaretsHint::RespectOldAppearance,
                     UpdateCaretsHint::DispatchNoEvent});
@@ -635,16 +644,19 @@ void AccessibleCaretManager::OnScrollPos
   }
 }
 
 void AccessibleCaretManager::OnReflow() {
   if (mLastUpdateCaretMode != GetCaretMode()) {
     return;
   }
 
+  AutoRestore<bool> saveAllowFlushingLayout(mAllowFlushingLayout);
+  mAllowFlushingLayout = false;
+
   if (mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible()) {
     AC_LOG("%s: UpdateCarets(RespectOldAppearance)", __FUNCTION__);
     UpdateCarets(UpdateCaretsHint::RespectOldAppearance);
   }
 }
 
 void AccessibleCaretManager::OnBlur() {
   AC_LOG("%s: HideCarets()", __FUNCTION__);
@@ -890,17 +902,17 @@ void AccessibleCaretManager::ClearMainta
   // word selection. We should clear it so that we can drag caret freely.
   RefPtr<nsFrameSelection> fs = GetFrameSelection();
   if (fs) {
     fs->MaintainSelection(eSelectNoAmount);
   }
 }
 
 bool AccessibleCaretManager::FlushLayout() {
-  if (mPresShell) {
+  if (mPresShell && mAllowFlushingLayout) {
     AutoRestore<bool> flushing(mFlushingLayout);
     mFlushingLayout = true;
 
     if (nsIDocument* doc = mPresShell->GetDocument()) {
       doc->FlushPendingNotifications(FlushType::Layout);
     }
   }
 
--- a/layout/base/AccessibleCaretManager.h
+++ b/layout/base/AccessibleCaretManager.h
@@ -313,16 +313,20 @@ class AccessibleCaretManager {
   uint16_t mLastInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_UNKNOWN;
 
   // Set to true in OnScrollStart() and set to false in OnScrollEnd().
   bool mIsScrollStarted = false;
 
   // Whether we're flushing layout, used for sanity-checking.
   bool mFlushingLayout = false;
 
+  // Set to false to disallow flushing layout in some callbacks such as
+  // OnReflow(), OnScrollStart(), OnScrollStart(), or OnScrollPositionChanged().
+  bool mAllowFlushingLayout = true;
+
   static const int32_t kAutoScrollTimerDelay = 30;
 
   // Clicking on the boundary of input or textarea will move the caret to the
   // front or end of the content. To avoid this, we need to deflate the content
   // boundary by 61 app units, which is 1 pixel + 1 app unit as defined in
   // AppUnit.h.
   static const int32_t kBoundaryAppUnits = 61;