diff --git a/mozilla/content/base/public/nsIScriptLoader.idl b/mozilla/content/base/public/nsIScriptLoader.idl index bb48a08dfb4..3779847dd44 100644 --- a/mozilla/content/base/public/nsIScriptLoader.idl +++ b/mozilla/content/base/public/nsIScriptLoader.idl @@ -73,4 +73,20 @@ interface nsIScriptLoader : nsISupports { */ void processScriptElement(in nsIDOMHTMLScriptElement aElement, in nsIScriptLoaderObserver aObserver); + + /** + * Suspend processing of new script elements. Any call to + * processScriptElement() will fail with a return code of + * NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT suspend + * currently loading or executing scripts. All calls to + * suspend() must be matched with an equal number of calls + * to resume() before processing of new script elements + * continues. + */ + void suspend(); + + /** + * Resume processing of new script elements. + */ + void resume(); }; diff --git a/mozilla/content/base/src/nsScriptLoader.cpp b/mozilla/content/base/src/nsScriptLoader.cpp index 89fe9b2ce3f..12fd2de5b9e 100644 --- a/mozilla/content/base/src/nsScriptLoader.cpp +++ b/mozilla/content/base/src/nsScriptLoader.cpp @@ -118,7 +118,7 @@ nsScriptLoadRequest::FireScriptEvaluated(nsresult aResult) ////////////////////////////////////////////////////////////// nsScriptLoader::nsScriptLoader() - : mDocument(nsnull) + : mDocument(nsnull), mSuspendCount(0) { NS_INIT_ISUPPORTS(); } @@ -261,7 +261,7 @@ nsScriptLoader::ProcessScriptElement(nsIDOMHTMLScriptElement *aElement, // Check to see that the element is not in a container that // suppresses script evaluation within it. - if (InNonScriptingContainer(aElement)) { + if (mSuspendCount || InNonScriptingContainer(aElement)) { return FireErrorNotification(NS_ERROR_NOT_AVAILABLE, aElement, aObserver); } @@ -757,3 +757,20 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader, return NS_OK; } + +NS_IMETHODIMP +nsScriptLoader::Suspend() +{ + mSuspendCount++; + + return NS_OK; +} + +NS_IMETHODIMP +nsScriptLoader::Resume() +{ + NS_ASSERTION((mSuspendCount > 0), "nsScriptLoader call to resume() unbalanced"); + mSuspendCount--; + + return NS_OK; +} diff --git a/mozilla/content/base/src/nsScriptLoader.h b/mozilla/content/base/src/nsScriptLoader.h index 11ce865dad2..80e967162e7 100644 --- a/mozilla/content/base/src/nsScriptLoader.h +++ b/mozilla/content/base/src/nsScriptLoader.h @@ -68,6 +68,7 @@ protected: nsIDocument* mDocument; // [WEAK] nsSupportsArray mObservers; nsSupportsArray mPendingRequests; + PRInt32 mSuspendCount; }; #endif //__nsScriptLoader_h__ diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 2409c71ddcb..29f1254daf1 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -1582,6 +1582,16 @@ SinkContext::DemoteContainer(const nsIParserNode& aNode) } } + // Suspend script processing while we move children around. + // We don't want to re-evaluate scripts as a result of the move. + nsCOMPtr loader; + if (mSink && mSink->mDocument) { + mSink->mDocument->GetScriptLoader(getter_AddRefs(loader)); + if (loader) { + loader->Suspend(); + } + } + if (NS_SUCCEEDED(result)) { // Move all of the demoted containers children to its parent PRInt32 i, count; @@ -1639,6 +1649,10 @@ SinkContext::DemoteContainer(const nsIParserNode& aNode) mStackPos--; } + if (loader) { + loader->Resume(); + } + // Restore frames state after adding it to new parent if (frameManager && presContext && tempFrameState && frame) { presShell->GetPrimaryFrameFor(parent, &frame);