Bug 1432396 - Call UnblockOnload only if we've already blocked load event. r=bz
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 16 Feb 2018 06:15:01 +0900
changeset 404122 62c3218a09210f8e867bfa8de20c83775a232068
parent 404121 f1487d25e019dd13454840e29b416ca441e79344
child 404123 9a74a8c4a8c05ca6968d90594b86ec8b7d0706d8
push id99938
push usercbrindusan@mozilla.com
push dateFri, 16 Feb 2018 09:57:26 +0000
treeherdermozilla-inbound@5f2344531e28 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1432396
milestone60.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 1432396 - Call UnblockOnload only if we've already blocked load event. r=bz When the window is destroyed in unload event callbacks for the previous document, we haven't started loading, i.e. we haven't called BlockOnload() for the new document in nsContentSink::WillBuildModelImpl, so if we called nsDocument::StopDocumentLoad() in such cases, UnblockOnload calls will mismatch BlockOnload calls. MozReview-Commit-ID: HjLtmGGvXKS
dom/base/nsContentSink.cpp
dom/base/nsContentSink.h
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -102,16 +102,17 @@ nsContentSink::nsContentSink()
   , mLayoutStarted(0)
   , mDynamicLowerValue(0)
   , mParsing(0)
   , mDroppedTimer(0)
   , mDeferredLayoutStart(0)
   , mDeferredFlushTags(0)
   , mIsDocumentObserver(0)
   , mRunsToCompletion(0)
+  , mIsBlockingOnload(false)
   , mDeflectedCount(0)
   , mHasPendingEvent(false)
   , mCurrentParseEndTime(0)
   , mBeginLoadTime(0)
   , mLastSampledUserEventTime(0)
   , mInMonolithicContainer(0)
   , mInNotification(0)
   , mUpdatesInNotification(0)
@@ -1561,18 +1562,24 @@ nsContentSink::DropParserAndPerfHint(voi
   RefPtr<nsParserBase> kungFuDeathGrip(mParser.forget());
 
   if (mDynamicLowerValue) {
     // Reset the performance hint which was set to FALSE
     // when mDynamicLowerValue was set.
     FavorPerformanceHint(true, 0);
   }
 
-  if (!mRunsToCompletion) {
+  // Call UnblockOnload only if mRunsToComletion is false and if
+  // we have already started loading because it's possible that this function
+  // is called (i.e. the parser is terminated) before we start loading due to
+  // destroying the window inside unload event callbacks for the previous
+  // document.
+  if (!mRunsToCompletion && mIsBlockingOnload) {
     mDocument->UnblockOnload(true);
+    mIsBlockingOnload = false;
   }
 }
 
 bool
 nsContentSink::IsScriptExecutingImpl()
 {
   return !!mScriptLoader->GetCurrentScript();
 }
@@ -1617,16 +1624,17 @@ nsContentSink::WillParseImpl(void)
   return NS_OK;
 }
 
 void
 nsContentSink::WillBuildModelImpl()
 {
   if (!mRunsToCompletion) {
     mDocument->BlockOnload();
+    mIsBlockingOnload = true;
 
     mBeginLoadTime = PR_IntervalToMicroseconds(PR_IntervalNow());
   }
 
   mDocument->ResetScrolledToRefAlready();
 
   if (mProcessLinkHeaderEvent.get()) {
     mProcessLinkHeaderEvent.Revoke();
--- a/dom/base/nsContentSink.h
+++ b/dom/base/nsContentSink.h
@@ -305,16 +305,18 @@ protected:
   uint8_t mDeferredFlushTags : 1;
   // If false, we're not ourselves a document observer; that means we
   // shouldn't be performing any more content model notifications,
   // since we're not longer updating our child counts.
   uint8_t mIsDocumentObserver : 1;
   // True if this is parser is a fragment parser or an HTML DOMParser.
   // XML DOMParser leaves this to false for now!
   uint8_t mRunsToCompletion : 1;
+  // True if we are blocking load event.
+  bool mIsBlockingOnload : 1;
 
   //
   // -- Can interrupt parsing members --
   //
 
   // The number of tokens that have been processed since we measured
   // if it's time to return to the main event loop.
   uint32_t mDeflectedCount;