diff --git a/content/base/public/nsIScriptLoaderObserver.idl b/content/base/public/nsIScriptLoaderObserver.idl index f07cde36502e..7c2874c055c9 100644 --- a/content/base/public/nsIScriptLoaderObserver.idl +++ b/content/base/public/nsIScriptLoaderObserver.idl @@ -41,7 +41,7 @@ interface nsIScriptElement; interface nsIURI; -[scriptable, uuid(501209d3-7edf-437d-9948-3c6d1c08ef7f)] +[scriptable, uuid(7b787204-76fb-4764-96f1-fb7a666db4f4)] interface nsIScriptLoaderObserver : nsISupports { /** @@ -54,10 +54,6 @@ interface nsIScriptLoaderObserver : nsISupports { * will not occur. * @param aElement The element being processed. * @param aIsInline Is this an inline script or externally loaded? - * @param aWasPending Did script processing have to be delayed, - * either for loading of an external script or - * because processing of an earlier scheduled - * script was delayed? * @param aURI What is the URI of the script (the document URI if * it is inline). * @param aLineNo At what line does the script appear (generally 1 @@ -66,7 +62,6 @@ interface nsIScriptLoaderObserver : nsISupports { void scriptAvailable(in nsresult aResult, in nsIScriptElement aElement, in boolean aIsInline, - in boolean aWasPending, in nsIURI aURI, in PRInt32 aLineNo); @@ -77,14 +72,9 @@ interface nsIScriptLoaderObserver : nsISupports { * the script evaluation. * @param aElement The element being processed. * @param aIsInline Is this an inline script or externally loaded? - * @param aWasPending Did script processing have to be delayed, - * either for loading of an external script or - * because processing of an earlier scheduled - * script was delayed? */ void scriptEvaluated(in nsresult aResult, in nsIScriptElement aElement, - in boolean aIsInline, - in boolean aWasPending); + in boolean aIsInline); }; diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index f6839b9ee983..f9bcb2da1c77 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -85,6 +85,7 @@ #include "nsIRequest.h" #include "nsNodeUtils.h" #include "nsIDOMNode.h" +#include "nsThreadUtils.h" PRLogModuleInfo* gContentSinkLogModuleInfo; @@ -117,15 +118,14 @@ NS_IMETHODIMP nsScriptLoaderObserverProxy::ScriptAvailable(nsresult aResult, nsIScriptElement *aElement, PRBool aIsInline, - PRBool aWasPending, nsIURI *aURI, PRInt32 aLineNo) { nsCOMPtr inner = do_QueryReferent(mInner); if (inner) { - return inner->ScriptAvailable(aResult, aElement, aIsInline, aWasPending, - aURI, aLineNo); + return inner->ScriptAvailable(aResult, aElement, aIsInline, aURI, + aLineNo); } return NS_OK; @@ -134,13 +134,12 @@ nsScriptLoaderObserverProxy::ScriptAvailable(nsresult aResult, NS_IMETHODIMP nsScriptLoaderObserverProxy::ScriptEvaluated(nsresult aResult, nsIScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending) + PRBool aIsInline) { nsCOMPtr inner = do_QueryReferent(mInner); if (inner) { - return inner->ScriptEvaluated(aResult, aElement, aIsInline, aWasPending); + return inner->ScriptEvaluated(aResult, aElement, aIsInline); } return NS_OK; @@ -273,7 +272,6 @@ NS_IMETHODIMP nsContentSink::ScriptAvailable(nsresult aResult, nsIScriptElement *aElement, PRBool aIsInline, - PRBool aWasPending, nsIURI *aURI, PRInt32 aLineNo) { @@ -308,7 +306,7 @@ nsContentSink::ScriptAvailable(nsresult aResult, } else { mScriptElements.RemoveObjectAt(count - 1); - if (mParser && aWasPending && aResult != NS_BINDING_ABORTED) { + if (mParser && aResult != NS_BINDING_ABORTED) { // Loading external script failed!. So, resume parsing since the parser // got blocked when loading external script. See // http://bugzilla.mozilla.org/show_bug.cgi?id=94903. @@ -317,7 +315,7 @@ nsContentSink::ScriptAvailable(nsresult aResult, // script load, assuming that that error code means that the user // stopped the load through some action (like clicking a link). See // http://bugzilla.mozilla.org/show_bug.cgi?id=243392. - mParser->ContinueInterruptedParsing(); + ContinueInterruptedParsingAsync(); } } @@ -327,8 +325,7 @@ nsContentSink::ScriptAvailable(nsresult aResult, NS_IMETHODIMP nsContentSink::ScriptEvaluated(nsresult aResult, nsIScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending) + PRBool aIsInline) { // Check if this is the element we were waiting for PRInt32 count = mScriptElements.Count(); @@ -347,8 +344,8 @@ nsContentSink::ScriptEvaluated(nsresult aResult, PostEvaluateScript(aElement); } - if (mParser && mParser->IsParserEnabled() && aWasPending) { - mParser->ContinueInterruptedParsing(); + if (mParser && mParser->IsParserEnabled()) { + ContinueInterruptedParsingAsync(); } return NS_OK; @@ -1350,3 +1347,20 @@ nsContentSink::WillBuildModelImpl() mScrolledToRefAlready = PR_FALSE; } + +void +nsContentSink::ContinueInterruptedParsing() +{ + if (mParser) { + mParser->ContinueInterruptedParsing(); + } +} + +void +nsContentSink::ContinueInterruptedParsingAsync() +{ + nsCOMPtr ev = new nsRunnableMethod(this, + &nsContentSink::ContinueInterruptedParsing); + + NS_DispatchToCurrentThread(ev); +} diff --git a/content/base/src/nsContentSink.h b/content/base/src/nsContentSink.h index c5e8460a1610..b5cdbe76d0b3 100644 --- a/content/base/src/nsContentSink.h +++ b/content/base/src/nsContentSink.h @@ -209,6 +209,9 @@ private: protected: + void ContinueInterruptedParsingAsync(); + void ContinueInterruptedParsing(); + nsCOMPtr mDocument; nsCOMPtr mParser; nsCOMPtr mDocumentURI; diff --git a/content/base/src/nsScriptElement.cpp b/content/base/src/nsScriptElement.cpp index e5e04991a345..bb1feb85ddd9 100755 --- a/content/base/src/nsScriptElement.cpp +++ b/content/base/src/nsScriptElement.cpp @@ -66,7 +66,6 @@ NS_IMETHODIMP nsScriptElement::ScriptAvailable(nsresult aResult, nsIScriptElement *aElement, PRBool aIsInline, - PRBool aWasPending, nsIURI *aURI, PRInt32 aLineNo) { @@ -99,8 +98,7 @@ nsScriptElement::ScriptAvailable(nsresult aResult, NS_IMETHODIMP nsScriptElement::ScriptEvaluated(nsresult aResult, nsIScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending) + PRBool aIsInline) { nsresult rv = NS_OK; if (!aIsInline) { diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 8f25a2241d8b..45d8129eb7ae 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -121,7 +121,7 @@ public: nsScriptLoadRequest(nsIScriptElement* aElement, PRUint32 aVersion) : mElement(aElement), - mLoading(PR_TRUE), mWasPending(PR_FALSE), + mLoading(PR_TRUE), mIsInline(PR_TRUE), mJSVersion(aVersion), mLineNo(1) { @@ -131,17 +131,15 @@ public: void FireScriptAvailable(nsresult aResult) { - mElement->ScriptAvailable(aResult, mElement, mIsInline, mWasPending, - mURI, mLineNo); + mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo); } void FireScriptEvaluated(nsresult aResult) { - mElement->ScriptEvaluated(aResult, mElement, mIsInline, mWasPending); + mElement->ScriptEvaluated(aResult, mElement, mIsInline); } nsCOMPtr mElement; PRPackedBool mLoading; // Are we still waiting for a load to complete? - PRPackedBool mWasPending; // Processed immediately or pending PRPackedBool mIsInline; // Is the script inline or loaded? nsString mScriptText; // Holds script for loaded scripts PRUint32 mJSVersion; @@ -161,7 +159,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLoadRequest) nsScriptLoader::nsScriptLoader(nsIDocument *aDocument) : mDocument(aDocument), mBlockerCount(0), - mEnabled(PR_TRUE) + mEnabled(PR_TRUE), + mHadPendingScripts(PR_FALSE) { } @@ -226,7 +225,6 @@ IsScriptEventHandler(nsIScriptElement *aScriptElement) return PR_FALSE; } -/* void processScriptElement (in nsIScriptElement aElement, in nsIScriptLoaderObserver aObserver); */ nsresult nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) { @@ -445,7 +443,6 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) request->mURI = scriptURI; request->mIsInline = PR_FALSE; - request->mWasPending = PR_TRUE; request->mLoading = PR_TRUE; nsCOMPtr loadGroup = mDocument->GetDocumentLoadGroup(); @@ -487,11 +484,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // If we've got existing pending requests, add ourselves // to this list. if (ReadyToExecuteScripts() && mPendingRequests.Count() == 0) { - NS_ASSERTION(!request->mWasPending, "should not be pending"); return ProcessRequest(request); } - - request->mWasPending = PR_TRUE; } // Add the request to our pending requests list @@ -538,8 +532,8 @@ nsScriptLoader::FireScriptAvailable(nsresult aResult, for (PRInt32 i = 0; i < mObservers.Count(); i++) { nsCOMPtr obs = mObservers[i]; obs->ScriptAvailable(aResult, aRequest->mElement, - aRequest->mIsInline, aRequest->mWasPending, - aRequest->mURI, aRequest->mLineNo); + aRequest->mIsInline, aRequest->mURI, + aRequest->mLineNo); } aRequest->FireScriptAvailable(aResult); @@ -552,7 +546,7 @@ nsScriptLoader::FireScriptEvaluated(nsresult aResult, for (PRInt32 i = 0; i < mObservers.Count(); i++) { nsCOMPtr obs = mObservers[i]; obs->ScriptEvaluated(aResult, aRequest->mElement, - aRequest->mIsInline, aRequest->mWasPending); + aRequest->mIsInline); } aRequest->FireScriptEvaluated(aResult); diff --git a/content/base/src/nsScriptLoader.h b/content/base/src/nsScriptLoader.h index 78620ad08032..9e7b8678c5d6 100644 --- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -151,12 +151,25 @@ public: */ void AddExecuteBlocker() { - ++mBlockerCount; + if (!mBlockerCount++) { + mHadPendingScripts = mPendingRequests.Count() != 0; + } } void RemoveExecuteBlocker() { if (!--mBlockerCount) { - ProcessPendingRequestsAsync(); + // If there were pending scripts then the newly added scripts will + // execute once whatever event triggers the pending scripts fires. + // However, due to syncronous loads and pushed event queues it's + // possible that the requests that were there have already been processed + // if so we need to process any new requests asyncronously. + // Ideally that should be fixed such that it can't happen. + if (mHadPendingScripts) { + ProcessPendingRequestsAsync(); + } + else { + ProcessPendingRequests(); + } } } @@ -214,6 +227,7 @@ protected: nsCOMPtr mCurrentScript; PRUint32 mBlockerCount; PRPackedBool mEnabled; + PRPackedBool mHadPendingScripts; }; #endif //__nsScriptLoader_h__ diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 607c8d8e167a..cab56aae659a 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -849,6 +849,10 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) nsresult nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML) { + // This BeginUpdate/EndUpdate pair is important to make us reenable the + // scriptloader before the last EndUpdate call. + mozAutoDocUpdate updateBatch(GetCurrentDoc(), UPDATE_CONTENT_MODEL, PR_TRUE); + // Remove childnodes nsContentUtils::SetNodeTextContent(this, EmptyString(), PR_FALSE); diff --git a/content/html/content/test/test_bug300691-2.html b/content/html/content/test/test_bug300691-2.html index e2a4e4986dd8..3497b8b29edf 100644 --- a/content/html/content/test/test_bug300691-2.html +++ b/content/html/content/test/test_bug300691-2.html @@ -18,8 +18,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=300691
 
 
 
 
diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.cpp b/content/xslt/src/xslt/txMozillaXMLOutput.cpp index ea17bf14a866..d3e9fa655799 100644 --- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -1020,7 +1020,6 @@ NS_IMETHODIMP txTransformNotifier::ScriptAvailable(nsresult aResult, nsIScriptElement *aElement, PRBool aIsInline, - PRBool aWasPending, nsIURI *aURI, PRInt32 aLineNo) { @@ -1035,8 +1034,7 @@ txTransformNotifier::ScriptAvailable(nsresult aResult, NS_IMETHODIMP txTransformNotifier::ScriptEvaluated(nsresult aResult, nsIScriptElement *aElement, - PRBool aIsInline, - PRBool aWasPending) + PRBool aIsInline) { if (mScriptElements.RemoveObject(aElement)) { SignalTransformEnd();