Bug 489050. Make sure to not notify on our content once we've disconnected from the document. r=bent, sr=sicking

This commit is contained in:
Boris Zbarsky 2009-05-17 10:22:55 -04:00
parent 6f4f48e0e7
commit 0f6dae2977
3 changed files with 31 additions and 11 deletions

View File

@ -350,6 +350,10 @@ protected:
PRUint8 mDeferredFlushTags : 1;
// If true, we did get a ReadyToCallDidBuildModel call
PRUint8 mDidGetReadyToCallDidBuildModelCall : 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.
PRUint8 mIsDocumentObserver : 1;
// -- Can interrupt parsing members --
PRUint32 mDelayTimerStart;

View File

@ -1647,6 +1647,7 @@ HTMLContentSink::Init(nsIDocument* aDoc,
}
aDoc->AddObserver(this);
mIsDocumentObserver = PR_TRUE;
CallQueryInterface(aDoc, &mHTMLDocument);
mObservers = nsnull;
@ -1828,8 +1829,10 @@ HTMLContentSink::DidBuildModel(void)
// our notifications out, so there's no need to do anything else here.
// XXXbz I wonder whether we could End() our contexts here too, or something,
// just to make sure we no longer notify...
// just to make sure we no longer notify... Or is the mIsDocumentObserver
// thing sufficient?
mDocument->RemoveObserver(this);
mIsDocumentObserver = PR_FALSE;
mDocument->EndLoad();
@ -3194,11 +3197,15 @@ HTMLContentSink::FlushPendingNotifications(mozFlushType aType)
// Only flush tags if we're not doing the notification ourselves
// (since we aren't reentrant)
if (!mInNotification) {
if (aType >= Flush_ContentAndNotify) {
FlushTags();
}
else if (mCurrentContext) {
mCurrentContext->FlushText();
// Only flush if we're still a document observer (so that our child counts
// should be correct).
if (mIsDocumentObserver) {
if (aType >= Flush_ContentAndNotify) {
FlushTags();
}
else if (mCurrentContext) {
mCurrentContext->FlushText();
}
}
if (aType >= Flush_InterruptibleLayout) {
// Make sure that layout has started so that the reflow flush

View File

@ -167,6 +167,7 @@ nsXMLContentSink::Init(nsIDocument* aDoc,
NS_ENSURE_SUCCESS(rv, rv);
aDoc->AddObserver(this);
mIsDocumentObserver = PR_TRUE;
if (!mDocShell) {
mPrettyPrintXML = PR_FALSE;
@ -247,6 +248,7 @@ nsXMLContentSink::MaybePrettyPrint()
// stop observing in order to avoid crashing when replacing content
mDocument->RemoveObserver(this);
mIsDocumentObserver = PR_FALSE;
// Reenable the CSSLoader so that the prettyprinting stylesheets can load
if (mCSSLoader) {
@ -315,6 +317,7 @@ nsXMLContentSink::DidBuildModel()
if (mXSLTProcessor) {
// stop observing in order to avoid crashing when replacing content
mDocument->RemoveObserver(this);
mIsDocumentObserver = PR_FALSE;
// Check for xslt-param and xslt-param-namespace PIs
PRUint32 i;
@ -373,6 +376,7 @@ nsXMLContentSink::DidBuildModel()
}
mDocument->RemoveObserver(this);
mIsDocumentObserver = PR_FALSE;
mDocument->EndLoad();
}
@ -1485,6 +1489,7 @@ nsXMLContentSink::ReportError(const PRUnichar* aErrorText,
// stop observing in order to avoid crashing when removing content
mDocument->RemoveObserver(this);
mIsDocumentObserver = PR_FALSE;
// Clear the current content and
// prepare to set <parsererror> as the document root
@ -1647,11 +1652,15 @@ nsXMLContentSink::FlushPendingNotifications(mozFlushType aType)
// Only flush tags if we're not doing the notification ourselves
// (since we aren't reentrant)
if (!mInNotification) {
if (aType >= Flush_ContentAndNotify) {
FlushTags();
}
else {
FlushText(PR_FALSE);
if (mIsDocumentObserver) {
// Only flush if we're still a document observer (so that our child
// counts should be correct).
if (aType >= Flush_ContentAndNotify) {
FlushTags();
}
else {
FlushText(PR_FALSE);
}
}
if (aType >= Flush_InterruptibleLayout) {
// Make sure that layout has started so that the reflow flush