Bug 1432396 - Call UnblockOnload only if we've already blocked load event. r?bz draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Fri, 16 Feb 2018 06:15:01 +0900
changeset 755923 472fd4931a6609a4ed543c30a171caa9e46535d8
parent 755833 994a8d6eccbcdc6106794705bd77e3ac5f031be2
child 755924 467431f76cc93a663551b3332edd332ee41a32cc
push id99325
push userhikezoe@mozilla.com
push dateThu, 15 Feb 2018 23:56:43 +0000
reviewersbz
bugs1432396
milestone60.0a1
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;