Bug 1396097 Part 1: Detect synchronous layout requests when stylesheets are still loading, and output a console warning.
MozReview-Commit-ID: CSsXkPHRQuH
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -30,16 +30,17 @@
#include "nsIAtom.h"
#include "nsGkAtoms.h"
#include "nsNetCID.h"
#include "nsIOfflineCacheUpdate.h"
#include "nsIApplicationCache.h"
#include "nsIApplicationCacheContainer.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIScriptSecurityManager.h"
+#include "nsIScriptError.h"
#include "nsICookieService.h"
#include "nsContentUtils.h"
#include "nsNodeInfoManager.h"
#include "nsIAppShell.h"
#include "nsIWidget.h"
#include "nsWidgetsCID.h"
#include "nsIDOMNode.h"
#include "mozAutoDocUpdate.h"
@@ -1250,18 +1251,33 @@ nsContentSink::StartLayout(bool aIgnoreP
{
if (mLayoutStarted) {
// Nothing to do here
return;
}
mDeferredLayoutStart = true;
- if (!aIgnorePendingSheets && WaitForPendingSheets()) {
- // Bail out; we'll start layout when the sheets load
+ if (aIgnorePendingSheets) {
+ // This is a Flash of Unstyled Content (FOUC) situation. Layout is being
+ // synchronously requested before stylesheets are loaded. This will cause
+ // layout and paint to occur, only to be quickly replaced by a more complete
+ // and probably very different layout and paint.
+ //
+ // This is possible when an early-running script requests a property that
+ // triggers layout. We output a console warning to assist site developers
+ // in diagnosing the problem.
+ nsContentUtils::ReportToConsoleNonLocalized(
+ NS_LITERAL_STRING("Synchronous layout requested before stylesheets are loaded."),
+ nsIScriptError::warningFlag,
+ NS_LITERAL_CSTRING("layout"),
+ mDocument);
+ } else if (WaitForPendingSheets()) {
+ // If we can't ignore pending sheets, and we have some pending then we
+ // need to bail out; we'll start layout when the sheets load.
return;
}
mDeferredLayoutStart = false;
// Notify on all our content. If none of our presshells have started layout
// yet it'll be a no-op except for updating our data structures, a la
// UpdateChildCounts() (because we don't want to double-notify on whatever we
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -101,18 +101,19 @@ ExpectedOwnerForChild(const nsIFrame& aF
void
ServoRestyleState::AssertOwner(const ServoRestyleState& aParent) const
{
MOZ_ASSERT(mOwner);
MOZ_ASSERT(!mOwner->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
// We allow aParent.mOwner to be null, for cases when we're not starting at
// the root of the tree.
+ const nsIFrame* ownersOwner = ExpectedOwnerForChild(*mOwner);
MOZ_ASSERT_IF(aParent.mOwner,
- ExpectedOwnerForChild(*mOwner) == aParent.mOwner);
+ ownersOwner == aParent.mOwner);
}
nsChangeHint
ServoRestyleState::ChangesHandledFor(const nsIFrame& aFrame) const
{
if (!mOwner) {
MOZ_ASSERT(!mChangesHandled);
return mChangesHandled;