Bug 471166, r+sr=sicking

This commit is contained in:
Olli Pettay 2009-01-31 14:53:01 +02:00
parent 2474f75151
commit b9593d2535
6 changed files with 92 additions and 34 deletions

View File

@ -3668,10 +3668,27 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
return mObservers.Contains(aObserver);
}
void
nsDocument::MaybeEndOutermostXBLUpdate()
{
// Only call BindingManager()->EndOutermostUpdate() when
// we're not in an update and it is safe to run scripts.
if (mUpdateNestLevel == 0 && mInXBLUpdate) {
if (nsContentUtils::IsSafeToRunScript()) {
mInXBLUpdate = PR_FALSE;
BindingManager()->EndOutermostUpdate();
} else if (!mInDestructor) {
nsContentUtils::AddScriptRunner(
NS_NEW_RUNNABLE_METHOD(nsDocument, this, MaybeEndOutermostXBLUpdate));
}
}
}
void
nsDocument::BeginUpdate(nsUpdateType aUpdateType)
{
if (mUpdateNestLevel == 0) {
if (mUpdateNestLevel == 0 && !mInXBLUpdate) {
mInXBLUpdate = PR_TRUE;
BindingManager()->BeginOutermostUpdate();
}
@ -3698,15 +3715,12 @@ nsDocument::EndUpdate(nsUpdateType aUpdateType)
NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this, aUpdateType));
--mUpdateNestLevel;
if (mUpdateNestLevel == 0) {
// This set of updates may have created XBL bindings. Let the
// binding manager know we're done.
BindingManager()->EndOutermostUpdate();
}
if (mUpdateNestLevel == 0 && !mDelayFrameLoaderInitialization) {
InitializeFinalizeFrameLoaders();
}
// This set of updates may have created XBL bindings. Let the
// binding manager know we're done.
MaybeEndOutermostXBLUpdate();
MaybeInitializeFinalizeFrameLoaders();
}
void
@ -5135,18 +5149,6 @@ nsDocument::FlushSkinBindings()
BindingManager()->FlushSkinBindings();
}
class nsFrameLoaderRunner : public nsRunnable
{
public:
nsFrameLoaderRunner(nsDocument* aDoc) : mDoc(aDoc) {}
NS_IMETHOD Run() {
mDoc->InitializeFinalizeFrameLoaders();
return NS_OK;
}
private:
nsRefPtr<nsDocument> mDoc;
};
nsresult
nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
{
@ -5160,7 +5162,9 @@ nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
mInitializableFrameLoaders.AppendElement(aLoader);
if (!mFrameLoaderRunner) {
mFrameLoaderRunner = new nsFrameLoaderRunner(this);
mFrameLoaderRunner =
NS_NEW_RUNNABLE_METHOD(nsDocument, this,
MaybeInitializeFinalizeFrameLoaders);
NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
}
@ -5177,7 +5181,9 @@ nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader)
mFinalizableFrameLoaders.AppendElement(aLoader);
if (!mFrameLoaderRunner) {
mFrameLoaderRunner = new nsFrameLoaderRunner(this);
mFrameLoaderRunner =
NS_NEW_RUNNABLE_METHOD(nsDocument, this,
MaybeInitializeFinalizeFrameLoaders);
NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
}
@ -5185,13 +5191,30 @@ nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader)
}
void
nsDocument::InitializeFinalizeFrameLoaders()
nsDocument::MaybeInitializeFinalizeFrameLoaders()
{
mFrameLoaderRunner = nsnull;
if (mDelayFrameLoaderInitialization || mUpdateNestLevel != 0) {
// This method will be recalled when mUpdateNestLevel drops to 0,
// or when !mDelayFrameLoaderInitialization.
mFrameLoaderRunner = nsnull;
return;
}
// We're not in an update, but it is not safe to run scripts, so
// postpone frameloader initialization and finalization.
if (!nsContentUtils::IsSafeToRunScript()) {
if (!mInDestructor && !mFrameLoaderRunner &&
(mInitializableFrameLoaders.Length() ||
mFinalizableFrameLoaders.Length())) {
mFrameLoaderRunner =
NS_NEW_RUNNABLE_METHOD(nsDocument, this,
MaybeInitializeFinalizeFrameLoaders);
nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
}
return;
}
mFrameLoaderRunner = nsnull;
// Don't use a temporary array for mInitializableFrameLoaders, because
// loading a frame may cause some other frameloader to be removed from the
// array. But be careful to keep the loader alive when starting the load!

View File

@ -1007,7 +1007,9 @@ public:
nsresult CloneDocHelper(nsDocument* clone) const;
void InitializeFinalizeFrameLoaders();
void MaybeInitializeFinalizeFrameLoaders();
void MaybeEndOutermostXBLUpdate();
protected:
void RegisterNamedItems(nsIContent *aContent);
@ -1188,6 +1190,8 @@ protected:
// document was created entirely in memory
PRPackedBool mHaveInputEncoding:1;
PRPackedBool mInXBLUpdate:1;
PRUint8 mXMLDeclarationBits;
PRUint8 mDefaultElementType;
@ -1272,7 +1276,7 @@ private:
nsTArray<nsRefPtr<nsFrameLoader> > mInitializableFrameLoaders;
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
nsCOMPtr<nsIRunnable> mFrameLoaderRunner;
nsRefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner;
nsRevocableEventPtr<nsRunnableMethod<nsDocument> > mPendingTitleChangeEvent;

View File

@ -3077,14 +3077,25 @@ nsHTMLDocument::GetDesignMode(nsAString & aDesignMode)
return NS_OK;
}
void
nsHTMLDocument::MaybeEditingStateChanged()
{
if (mUpdateNestLevel == 0 && mContentEditableCount > 0 != IsEditingOn()) {
if (nsContentUtils::IsSafeToRunScript()) {
EditingStateChanged();
} else if (!mInDestructor) {
nsContentUtils::AddScriptRunner(
NS_NEW_RUNNABLE_METHOD(nsHTMLDocument, this, MaybeEditingStateChanged));
}
}
}
void
nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
{
nsDocument::EndUpdate(aUpdateType);
if (mUpdateNestLevel == 0 && mContentEditableCount > 0 != IsEditingOn()) {
EditingStateChanged();
}
MaybeEditingStateChanged();
}
nsresult

View File

@ -358,6 +358,7 @@ protected:
nsresult TurnEditingOff();
nsresult EditingStateChanged();
void MaybeEditingStateChanged();
PRUint32 mContentEditableCount;
EditingState mEditingState;

View File

@ -3216,7 +3216,7 @@ nsXULDocument::DoneWalking()
NS_WARN_IF_FALSE(mUpdateNestLevel == 0,
"Constructing XUL document in middle of an update?");
if (mUpdateNestLevel == 0) {
InitializeFinalizeFrameLoaders();
MaybeInitializeFinalizeFrameLoaders();
}
NS_DOCUMENT_NOTIFY_OBSERVERS(EndLoad, (this));
@ -3299,10 +3299,19 @@ nsXULDocument::StyleSheetLoaded(nsICSSStyleSheet* aSheet,
}
void
nsXULDocument::EndUpdate(nsUpdateType aUpdateType)
nsXULDocument::MaybeBroadcast()
{
nsXMLDocument::EndUpdate(aUpdateType);
if (mUpdateNestLevel == 0) {
// Only broadcast when not in an update and when safe to run scripts.
if (mUpdateNestLevel == 0 &&
(mDelayedAttrChangeBroadcasts.Length() ||
mDelayedBroadcasters.Length())) {
if (!nsContentUtils::IsSafeToRunScript()) {
if (!mInDestructor) {
nsContentUtils::AddScriptRunner(
NS_NEW_RUNNABLE_METHOD(nsXULDocument, this, MaybeBroadcast));
}
return;
}
if (!mHandlingDelayedAttrChange) {
mHandlingDelayedAttrChange = PR_TRUE;
for (PRUint32 i = 0; i < mDelayedAttrChangeBroadcasts.Length(); ++i) {
@ -3342,6 +3351,14 @@ nsXULDocument::EndUpdate(nsUpdateType aUpdateType)
}
}
void
nsXULDocument::EndUpdate(nsUpdateType aUpdateType)
{
nsXMLDocument::EndUpdate(aUpdateType);
MaybeBroadcast();
}
void
nsXULDocument::ReportMissingOverlay(nsIURI* aURI)
{

View File

@ -735,6 +735,8 @@ protected:
nsTArray<nsDelayedBroadcastUpdate> mDelayedBroadcasters;
nsTArray<nsDelayedBroadcastUpdate> mDelayedAttrChangeBroadcasts;
PRBool mHandlingDelayedAttrChange;
void MaybeBroadcast();
private:
// helpers