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
--- 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;