diff --git a/mozilla/content/base/src/nsContentSink.cpp b/mozilla/content/base/src/nsContentSink.cpp index 6a986128499..d9c010ebe8b 100644 --- a/mozilla/content/base/src/nsContentSink.cpp +++ b/mozilla/content/base/src/nsContentSink.cpp @@ -80,6 +80,7 @@ const PRBool kBlockByDefault = PR_TRUE; #endif +#if 0 class nsScriptLoaderObserverProxy : public nsIScriptLoaderObserver { public: @@ -132,11 +133,11 @@ nsScriptLoaderObserverProxy::ScriptEvaluated(nsresult aResult, return NS_OK; } +#endif -NS_IMPL_ISUPPORTS3(nsContentSink, +NS_IMPL_ISUPPORTS2(nsContentSink, nsICSSLoaderObserver, - nsISupportsWeakReference, nsIScriptLoaderObserver) nsContentSink::nsContentSink() @@ -166,6 +167,7 @@ nsContentSink::Init(nsIDocument* aDoc, mDocumentBaseURL = aURL; mDocShell = do_QueryInterface(aContainer); +#if 0 // use this to avoid a circular reference sink->document->scriptloader->sink nsCOMPtr proxy = new nsScriptLoaderObserverProxy(this); @@ -176,6 +178,7 @@ nsContentSink::Init(nsIDocument* aDoc, NS_ENSURE_SUCCESS(rv, rv); rv = loader->AddObserver(proxy); NS_ENSURE_SUCCESS(rv, rv); +#endif nsCOMPtr htmlContainer(do_QueryInterface(aDoc)); if (htmlContainer) { diff --git a/mozilla/content/base/src/nsContentSink.h b/mozilla/content/base/src/nsContentSink.h index b3e91fcbf84..7f3079fe925 100644 --- a/mozilla/content/base/src/nsContentSink.h +++ b/mozilla/content/base/src/nsContentSink.h @@ -60,8 +60,7 @@ class nsIContent; class nsIViewManager; class nsContentSink : public nsICSSLoaderObserver, - public nsIScriptLoaderObserver, - public nsSupportsWeakReference + public nsIScriptLoaderObserver { NS_DECL_ISUPPORTS NS_DECL_NSISCRIPTLOADEROBSERVER diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 9753fc588b7..31e938dcdbb 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -50,6 +50,7 @@ #include "nsIParser.h" #include "nsParserUtils.h" #include "nsIScriptLoader.h" +#include "nsIScriptLoaderObserver.h" #include "nsIHTMLContent.h" #include "nsIURL.h" #include "nsNetUtil.h" @@ -232,6 +233,7 @@ public: // nsISupports NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSISCRIPTLOADEROBSERVER // nsIContentSink NS_IMETHOD WillBuildModel(void); @@ -429,8 +431,8 @@ protected: nsresult ResumeParsing(); // nsContentSink overrides - virtual void PreEvaluateScript(); - virtual void PostEvaluateScript(); + void PreEvaluateScript(); + void PostEvaluateScript(); void UpdateAllContexts(); void NotifyAppend(nsIContent* aContent, @@ -2160,6 +2162,11 @@ HTMLContentSink::Init(nsIDocument* aDoc, service->GetTopicObservers(NS_LITERAL_STRING("text/html"), getter_AddRefs(mObservers)); + nsCOMPtr loader; + rv = mDocument->GetScriptLoader(getter_AddRefs(loader)); + NS_ENSURE_SUCCESS(rv, rv); + loader->AddObserver(this); + NS_WARN_IF_FALSE(mDocShell, "oops no docshell!"); // Find out if subframes are enabled @@ -4488,6 +4495,79 @@ HTMLContentSink::PostEvaluateScript() mCurrentContext->SetPreAppend(PR_FALSE); } +NS_IMETHODIMP +HTMLContentSink::ScriptAvailable(nsresult aResult, + nsIDOMHTMLScriptElement *aElement, + PRBool aIsInline, + PRBool aWasPending, + nsIURI *aURI, + PRInt32 aLineNo, + const nsAString& aScript) +{ + // Check if this is the element we were waiting for + PRUint32 count = mScriptElements.Count(); + + nsCOMPtr scriptElement = mScriptElements[count - 1]; + if (aElement != scriptElement) { + return NS_OK; + } + + if (mParser && !mParser->IsParserEnabled()) { + // make sure to unblock the parser before evaluating the script, + // we must unblock the parser even if loading the script failed or + // if the script was empty, if we don't, the parser will never be + // unblocked. + mParser->UnblockParser(); + } + + // Mark the current script as loaded + mNeedToBlockParser = PR_FALSE; + + if (NS_SUCCEEDED(aResult) && aResult != NS_CONTENT_SCRIPT_IS_EVENTHANDLER) { + PreEvaluateScript(); + } else { + mScriptElements.RemoveObjectAt(count - 1); + + if (mParser && aWasPending) { + // Loading external script failed!. So, resume + // parsing since the parser got blocked when loading + // external script. - Ref. Bug: 94903 + mParser->ContinueParsing(); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +HTMLContentSink::ScriptEvaluated(nsresult aResult, + nsIDOMHTMLScriptElement *aElement, + PRBool aIsInline, + PRBool aWasPending) +{ + // Check if this is the element we were waiting for + PRUint32 count = mScriptElements.Count(); + + nsCOMPtr scriptElement = mScriptElements[count - 1]; + if (aElement != scriptElement) { + return NS_OK; + } + + // Pop the script element stack + mScriptElements.RemoveObjectAt(count - 1); + + if (NS_SUCCEEDED(aResult)) { + PostEvaluateScript(); + } + + if (mParser && mParser->IsParserEnabled() && aWasPending) { + mParser->ContinueParsing(); + } + + return NS_OK; +} + + nsresult HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) { diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 85d51367218..b47075019fa 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -110,7 +110,58 @@ static const char kNameSpaceSeparator = ':'; static const char kLoadAsData[] = "loadAsData"; +class nsScriptLoaderObserverProxy : public nsIScriptLoaderObserver +{ +public: + nsScriptLoaderObserverProxy(nsIScriptLoaderObserver* aInner) + : mInner(do_GetWeakReference(aInner)) + { + } + virtual ~nsScriptLoaderObserverProxy() + { + } + + NS_DECL_ISUPPORTS + NS_DECL_NSISCRIPTLOADEROBSERVER + nsWeakPtr mInner; +}; + +NS_IMPL_ISUPPORTS1(nsScriptLoaderObserverProxy, nsIScriptLoaderObserver) + +NS_IMETHODIMP +nsScriptLoaderObserverProxy::ScriptAvailable(nsresult aResult, + nsIDOMHTMLScriptElement *aElement, + PRBool aIsInline, + PRBool aWasPending, + nsIURI *aURI, + PRInt32 aLineNo, + const nsAString & aScript) +{ + nsCOMPtr inner = do_QueryReferent(mInner); + + if (inner) { + return inner->ScriptAvailable(aResult, aElement, aIsInline, aWasPending, + aURI, aLineNo, aScript); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsScriptLoaderObserverProxy::ScriptEvaluated(nsresult aResult, + nsIDOMHTMLScriptElement *aElement, + PRBool aIsInline, + PRBool aWasPending) +{ + nsCOMPtr inner = do_QueryReferent(mInner); + + if (inner) { + return inner->ScriptEvaluated(aResult, aElement, aIsInline, aWasPending); + } + + return NS_OK; +} // XXX Open Issues: // 1) what's not allowed - We need to figure out which HTML tags @@ -192,17 +243,29 @@ nsXMLContentSink::Init(nsIDocument* aDoc, mPrettyPrintXML = PR_FALSE; } + // use this to avoid a circular reference sink->document->scriptloader->sink + nsCOMPtr proxy = + new nsScriptLoaderObserverProxy(this); + NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY); + + nsCOMPtr loader; + rv = mDocument->GetScriptLoader(getter_AddRefs(loader)); + NS_ENSURE_SUCCESS(rv, rv); + loader->AddObserver(proxy); + mState = eXMLContentSinkState_InProlog; mDocElement = nsnull; return NS_OK; } -NS_IMPL_ISUPPORTS_INHERITED4(nsXMLContentSink, +NS_IMPL_ISUPPORTS_INHERITED5(nsXMLContentSink, nsContentSink, nsIContentSink, nsIXMLContentSink, nsIExpatSink, - nsITransformObserver) + nsITransformObserver, + nsISupportsWeakReference) + // nsIContentSink NS_IMETHODIMP diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.h b/mozilla/content/xml/document/src/nsXMLContentSink.h index bf93be0172d..c760b2a0b69 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.h +++ b/mozilla/content/xml/document/src/nsXMLContentSink.h @@ -46,7 +46,6 @@ #include "nsCOMArray.h" #include "nsCOMPtr.h" - class nsIDocument; class nsIURI; class nsIContent; @@ -64,7 +63,8 @@ typedef enum { class nsXMLContentSink : public nsContentSink, public nsIXMLContentSink, public nsITransformObserver, - public nsIExpatSink + public nsIExpatSink, + public nsSupportsWeakReference { public: nsXMLContentSink();