Bug 1516022 - promiseDocumentFlushed should ensure no subframes need flushing before running the callback. r=bzbarsky
☠☠ backed out by 0b3a6c7175ca ☠ ☠
authorMike Conley <mconley@mozilla.com>
Wed, 16 Jan 2019 18:37:44 +0000
changeset 514115 c683fbe0b9842988bbc6bff192072448d0e2fe14
parent 514114 7133682529a0cc924e72d3fcaa729c0e9585de5d
child 514116 4fae3add610fe59fec7d7a59faaca897409ac078
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1516022
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 1516022 - promiseDocumentFlushed should ensure no subframes need flushing before running the callback. r=bzbarsky Differential Revision: https://phabricator.services.mozilla.com/D16092
dom/base/nsGlobalWindowInner.cpp
dom/webidl/Window.webidl
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -6630,16 +6630,30 @@ void nsGlobalWindowInner::BeginWindowMov
   if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   aError = widget->BeginMoveDrag(mouseEvent);
 }
 
+static bool CheckSubframesNeedLayoutOrStyleFlush(Document* aDoc, void* aData) {
+  nsIPresShell* shell = aDoc->GetShell();
+  if (shell) {
+    bool* needFlush = static_cast<bool*>(aData);
+
+    if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
+      *needFlush = true;
+      return false;
+    }
+  }
+  aDoc->EnumerateSubDocuments(CheckSubframesNeedLayoutOrStyleFlush, aData);
+  return true;
+}
+
 already_AddRefed<Promise> nsGlobalWindowInner::PromiseDocumentFlushed(
     PromiseDocumentFlushedCallback& aCallback, ErrorResult& aError) {
   MOZ_RELEASE_ASSERT(IsChromeWindow());
 
   if (!IsCurrentInnerWindow()) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
@@ -6673,17 +6687,24 @@ already_AddRefed<Promise> nsGlobalWindow
   RefPtr<Promise> resultPromise = Promise::Create(global, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
       new PromiseDocumentFlushedResolver(resultPromise, aCallback));
 
-  if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
+  // Check to see if any of the subdocuments need a style or
+  // layout flush too.
+  bool subframeNeedsFlush = false;
+  mDoc->EnumerateSubDocuments(CheckSubframesNeedLayoutOrStyleFlush,
+                              &subframeNeedsFlush);
+
+  if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush() &&
+      !subframeNeedsFlush) {
     flushResolver->Call();
     return resultPromise.forget();
   }
 
   if (!mObservingDidRefresh) {
     bool success = shell->AddPostRefreshObserver(this);
     if (!success) {
       aError.Throw(NS_ERROR_FAILURE);
@@ -6760,17 +6781,24 @@ void nsGlobalWindowInner::DidRefresh() {
     mObservingDidRefresh = false;
   });
 
   MOZ_ASSERT(mDoc);
 
   nsIPresShell* shell = mDoc->GetShell();
   MOZ_ASSERT(shell);
 
-  if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
+  // Check to see if any of the subdocuments need a style or
+  // layout flush too.
+  bool subframeNeedsFlush = false;
+  mDoc->EnumerateSubDocuments(CheckSubframesNeedLayoutOrStyleFlush,
+                              &subframeNeedsFlush);
+
+  if (shell->NeedStyleFlush() || shell->NeedLayoutFlush() ||
+      subframeNeedsFlush) {
     // By the time our observer fired, something has already invalidated
     // style or layout - or perhaps we're still in the middle of a flush that
     // was interrupted. In either case, we'll wait until the next refresh driver
     // tick instead and try again.
     rejectionGuard.release();
     return;
   }
 
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -462,18 +462,19 @@ partial interface Window {
    *
    * Throws NS_ERROR_NOT_IMPLEMENTED if the OS doesn't support this.
    */
   [Throws, Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
   void beginWindowMove(Event mouseDownEvent);
 
   /**
    * Calls the given function as soon as a style or layout flush for the
-   * top-level document is not necessary, and returns a Promise which
-   * resolves to the callback's return value after it executes.
+   * top-level document (and all subframe descendants of it) are not
+   * necessary, and returns a Promise which resolves to the callback's
+   * return value after it executes.
    *
    * In the event that the window goes away before a flush can occur, the
    * callback will still be called and the Promise resolved as the window
    * tears itself down.
    *
    * Note that the callback can be called either synchronously or asynchronously
    * depending on whether or not flushes are pending:
    *