Bug 343730: Don't execute scripts synchronously from BindToTree. Instead we wait until the last EndUpdate has been called. r/sr=bz

This commit is contained in:
cvshook%sicking.cc 2006-11-04 05:45:02 +00:00
parent bdac3071e0
commit 17ded5692c
35 changed files with 798 additions and 950 deletions

View File

@ -95,7 +95,6 @@ XPIDLSRCS = \
nsISelectionDisplay.idl \
nsISelectionListener.idl \
nsISelectionPrivate.idl \
nsIScriptLoader.idl \
nsIScriptLoaderObserver.idl \
nsISyncLoadDOMService.idl \
nsIDragDropHandler.idl \

View File

@ -56,7 +56,7 @@
#define NS_XML_AUTOLINK_UNDEFINED \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 6)
/** Error codes for nsIScriptLoader */
/** Error codes for nsScriptLoader */
#define NS_CONTENT_SCRIPT_IS_EVENTHANDLER \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_CONTENT, 7)

View File

@ -62,8 +62,8 @@ class nsTextFragment;
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x7796e67b, 0xdc73, 0x4b3d, \
{ 0xb8, 0x34, 0xcc, 0x9f, 0x96, 0xf7, 0x25, 0x56 } }
{ 0x38cb1dfd, 0xeeac, 0x4f35, \
{ 0x93, 0x83, 0xc0, 0xb5, 0xe5, 0xf1, 0xcd, 0xa4 } }
// hack to make egcs / gcc 2.95.2 happy
class nsIContent_base : public nsINode {
@ -620,12 +620,22 @@ public:
* have the parser pass true. See nsHTMLInputElement.cpp and
* nsHTMLContentSink::MakeContentObject().
*
* It is ok to ignore an error returned from this function. However the
* following errors may be of interest to some callers:
*
* NS_ERROR_HTMLPARSER_BLOCK Returned by script elements to indicate
* that a script will be loaded asynchronously
*
* This means that implementations will have to deal with returned error
* codes being ignored.
*
* @param aHaveNotified Whether there has been a
* ContentInserted/ContentAppended notification for this content node
* yet.
*/
virtual void DoneAddingChildren(PRBool aHaveNotified)
virtual nsresult DoneAddingChildren(PRBool aHaveNotified)
{
return NS_OK;
}
/**

View File

@ -76,7 +76,7 @@ class nsIDOMDocument;
class nsIDOMDocumentType;
class nsIObserver;
class nsISupportsArray;
class nsIScriptLoader;
class nsScriptLoader;
class nsIContentSink;
class nsIScriptEventManager;
class nsNodeInfoManager;
@ -91,8 +91,8 @@ class nsIDocumentObserver;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x3a5ce97e, 0x4f41, 0x42ef, \
{ 0xa7, 0xc9, 0xcc, 0x3d, 0x4e, 0x7a, 0x3d, 0x00 } }
{ 0x1ae3a9cc, 0x3c05, 0x4215, \
{ 0xad, 0xed, 0xe7, 0x89, 0xc4, 0x08, 0x00, 0x91 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -522,7 +522,7 @@ public:
/**
* Get the script loader for this document
*/
virtual nsIScriptLoader* GetScriptLoader() = 0;
virtual nsScriptLoader* GetScriptLoader() = 0;
//----------------------------------------------------------------------

View File

@ -94,8 +94,8 @@ class nsIMutationObserver;
// IID for the nsINode interface
#define NS_INODE_IID \
{ 0x3d3a28b7, 0x6666, 0x4f93, \
{ 0xb7, 0xe7, 0xa9, 0x56, 0xd5, 0xaf, 0xf7, 0x57 } }
{ 0x98470c4b, 0xe988, 0x4abf, \
{ 0xa4, 0x00, 0x39, 0xbd, 0x00, 0x38, 0x51, 0x4d } }
// hack to make egcs / gcc 2.95.2 happy
class nsINode_base : public nsIDOMGCParticipant {
@ -571,6 +571,13 @@ public:
nsTObserverArray<nsIMutationObserver> mMutationObservers;
};
#ifdef DEBUG
nsSlots* DebugGetSlots()
{
return GetSlots();
}
#endif
protected:
/**
* Functions for managing flags and slots

View File

@ -42,18 +42,27 @@
#include "nsISupports.h"
#include "nsIURI.h"
#include "nsCOMPtr.h"
#include "nsIScriptLoaderObserver.h"
#define NS_ISCRIPTELEMENT_IID \
{ 0x0511fba1, 0x1b67, 0x4338, \
{ 0x98, 0xff, 0x42, 0xb9, 0x02, 0x0b, 0xeb, 0x92 } }
{ 0x4b916da5, 0x82c4, 0x45ab, \
{ 0x99, 0x15, 0xcc, 0xcd, 0x9e, 0x2c, 0xb1, 0xe6 } }
/**
* Internal interface implemented by script elements
*/
class nsIScriptElement : public nsISupports {
class nsIScriptElement : public nsIScriptLoaderObserver {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTELEMENT_IID)
nsIScriptElement()
: mLineNumber(0),
mIsEvaluated(PR_FALSE),
mMalformed(PR_FALSE),
mDoneAddingChildren(PR_TRUE)
{
}
/**
* Content type identifying the scripting language. Can be empty, in
* which case javascript will be assumed.
@ -73,10 +82,40 @@ public:
virtual void GetScriptCharset(nsAString& charset) = 0;
virtual void SetScriptLineNumber(PRUint32 aLineNumber) = 0;
virtual PRUint32 GetScriptLineNumber() = 0;
virtual void SetIsMalformed() = 0;
virtual PRBool IsMalformed() = 0;
void SetScriptLineNumber(PRUint32 aLineNumber)
{
mLineNumber = aLineNumber;
}
PRUint32 GetScriptLineNumber()
{
return mLineNumber;
}
void SetIsMalformed()
{
mMalformed = PR_TRUE;
}
PRBool IsMalformed()
{
return mMalformed;
}
void PreventExecution()
{
mIsEvaluated = PR_TRUE;
}
void WillCallDoneAddingChildren()
{
NS_ASSERTION(mDoneAddingChildren, "unexpected, but not fatal");
mDoneAddingChildren = PR_FALSE;
}
protected:
PRUint32 mLineNumber;
PRPackedBool mIsEvaluated;
PRPackedBool mMalformed;
PRPackedBool mDoneAddingChildren;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID)

View File

@ -62,15 +62,13 @@ interface nsIScriptLoaderObserver : nsISupports {
* it is inline).
* @param aLineNo At what line does the script appear (generally 1
* if it is a loaded script).
* @param aScript String representation of the string to be evaluated.
*/
void scriptAvailable(in nsresult aResult,
in nsIScriptElement aElement,
in boolean aIsInline,
in boolean aWasPending,
in nsIURI aURI,
in PRInt32 aLineNo,
in AString aScript);
in PRInt32 aLineNo);
/**
* The script has been evaluated.

View File

@ -85,6 +85,7 @@ EXPORTS = \
nsGkAtoms.h \
nsNodeInfoManager.h \
nsPropertyTable.h \
nsScriptLoader.h \
nsStubDocumentObserver.h \
nsStubImageDecoderObserver.h \
nsStubMutationObserver.h \
@ -135,6 +136,7 @@ CPPSRCS = \
nsPlainTextSerializer.cpp \
nsPropertyTable.cpp \
nsRange.cpp \
nsScriptElement.cpp \
nsScriptEventManager.cpp \
nsScriptLoader.cpp \
nsStubDocumentObserver.cpp \

View File

@ -41,7 +41,7 @@
*/
#include "nsContentSink.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsIDocument.h"
#include "nsICSSLoader.h"
#include "nsStyleConsts.h"
@ -112,14 +112,13 @@ nsScriptLoaderObserverProxy::ScriptAvailable(nsresult aResult,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString & aScript)
PRInt32 aLineNo)
{
nsCOMPtr<nsIScriptLoaderObserver> inner = do_QueryReferent(mInner);
if (inner) {
return inner->ScriptAvailable(aResult, aElement, aIsInline, aWasPending,
aURI, aLineNo, aScript);
aURI, aLineNo);
}
return NS_OK;
@ -147,7 +146,6 @@ NS_IMPL_ISUPPORTS3(nsContentSink,
nsIScriptLoaderObserver)
nsContentSink::nsContentSink()
: mNeedToBlockParser(PR_FALSE)
{
}
@ -179,10 +177,9 @@ nsContentSink::Init(nsIDocument* aDoc,
new nsScriptLoaderObserverProxy(this);
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
nsIScriptLoader *loader = mDocument->GetScriptLoader();
nsScriptLoader *loader = mDocument->GetScriptLoader();
NS_ENSURE_TRUE(loader, NS_ERROR_FAILURE);
nsresult rv = loader->AddObserver(proxy);
NS_ENSURE_SUCCESS(rv, rv);
loader->AddObserver(proxy);
mCSSLoader = aDoc->CSSLoader();
@ -207,8 +204,7 @@ nsContentSink::ScriptAvailable(nsresult aResult,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString& aScript)
PRInt32 aLineNo)
{
PRUint32 count = mScriptElements.Count();
@ -216,6 +212,13 @@ nsContentSink::ScriptAvailable(nsresult aResult,
return NS_OK;
}
// aElement will not be in mScriptElements if a <script> was added
// using the DOM during loading, or if the script was inline and thus
// never blocked.
NS_ASSERTION(mScriptElements.IndexOf(aElement) == count - 1 ||
mScriptElements.IndexOf(aElement) == -1,
"script found at unexpected position");
// Check if this is the element we were waiting for
if (aElement != mScriptElements[count - 1]) {
return NS_OK;
@ -229,10 +232,7 @@ nsContentSink::ScriptAvailable(nsresult aResult,
mParser->UnblockParser();
}
// Mark the current script as loaded
mNeedToBlockParser = PR_FALSE;
if (NS_SUCCEEDED(aResult) && aResult != NS_CONTENT_SCRIPT_IS_EVENTHANDLER) {
if (NS_SUCCEEDED(aResult)) {
PreEvaluateScript();
} else {
mScriptElements.RemoveObjectAt(count - 1);

View File

@ -125,7 +125,6 @@ protected:
nsCOMArray<nsIScriptElement> mScriptElements;
nsCString mRef; // ScrollTo #ref
PRBool mNeedToBlockParser;
};
// these two lists are used by the sanitizing fragment serializers

View File

@ -2229,15 +2229,11 @@ nsDocument::GetInnerWindow()
return win;
}
nsIScriptLoader *
nsScriptLoader*
nsDocument::GetScriptLoader()
{
if (!mScriptLoader) {
mScriptLoader = new nsScriptLoader();
if (!mScriptLoader) {
return nsnull;
}
mScriptLoader->Init(this);
mScriptLoader = new nsScriptLoader(this);
}
return mScriptLoader;
@ -2283,6 +2279,9 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
void
nsDocument::BeginUpdate(nsUpdateType aUpdateType)
{
if (mScriptLoader) {
mScriptLoader->AddExecuteBlocker();
}
NS_DOCUMENT_NOTIFY_OBSERVERS(BeginUpdate, (this, aUpdateType));
}
@ -2290,6 +2289,9 @@ void
nsDocument::EndUpdate(nsUpdateType aUpdateType)
{
NS_DOCUMENT_NOTIFY_OBSERVERS(EndUpdate, (this, aUpdateType));
if (mScriptLoader) {
mScriptLoader->RemoveExecuteBlocker();
}
}
void

View File

@ -451,7 +451,7 @@ public:
/**
* Get the script loader for this document
*/
virtual nsIScriptLoader* GetScriptLoader();
virtual nsScriptLoader* GetScriptLoader();
virtual void AddMutationObserver(nsIMutationObserver* aObserver);
virtual void RemoveMutationObserver(nsIMutationObserver* aMutationObserver);
@ -729,7 +729,7 @@ protected:
nsCOMPtr<nsIEventListenerManager> mListenerManager;
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
nsCOMPtr<nsIScriptLoader> mScriptLoader;
nsRefPtr<nsScriptLoader> mScriptLoader;
nsDocHeaderData* mHeaderData;
nsRefPtr<nsChildContentList> mChildNodes;

View File

@ -0,0 +1,218 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <jonas@sicking.cc> (original developer)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsScriptElement.h"
#include "nsIContent.h"
#include "nsIPresShell.h"
#include "nsIDocument.h"
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsPresContext.h"
#include "nsScriptLoader.h"
#include "nsGkAtoms.h"
#include "nsIParser.h"
#include "nsAutoPtr.h"
#include "nsGkAtoms.h"
static nsPresContext*
GetContextForContent(nsIContent* aContent)
{
nsIDocument* doc = aContent->GetCurrentDoc();
if (doc) {
nsIPresShell *presShell = doc->GetShellAt(0);
if (presShell) {
return presShell->GetPresContext();
}
}
return nsnull;
}
NS_IMETHODIMP
nsScriptElement::ScriptAvailable(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo)
{
if (!aIsInline && NS_FAILED(aResult)) {
nsCOMPtr<nsIContent> cont =
do_QueryInterface((nsIScriptElement*) this);
nsCOMPtr<nsPresContext> presContext = GetContextForContent(cont);
nsEventStatus status = nsEventStatus_eIgnore;
nsScriptErrorEvent event(PR_TRUE, NS_LOAD_ERROR);
event.lineNr = aLineNo;
NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
event.errorMsg = errorString.get();
nsCAutoString spec;
aURI->GetSpec(spec);
NS_ConvertUTF8toUTF16 fileName(spec);
event.fileName = fileName.get();
nsEventDispatcher::Dispatch(cont, presContext, &event, nsnull, &status);
}
return NS_OK;
}
NS_IMETHODIMP
nsScriptElement::ScriptEvaluated(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending)
{
nsresult rv = NS_OK;
if (!aIsInline) {
nsCOMPtr<nsIContent> cont =
do_QueryInterface((nsIScriptElement*) this);
nsCOMPtr<nsPresContext> presContext = GetContextForContent(cont);
nsEventStatus status = nsEventStatus_eIgnore;
PRUint32 type = NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR;
nsEvent event(PR_TRUE, type);
if (type == NS_LOAD) {
// Load event doesn't bubble.
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
}
nsEventDispatcher::Dispatch(cont, presContext, &event, nsnull, &status);
}
return rv;
}
void
nsScriptElement::CharacterDataChanged(nsIDocument *aDocument,
nsIContent* aContent,
PRBool aAppend)
{
MaybeProcessScript();
}
void
nsScriptElement::AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::src) {
MaybeProcessScript();
}
}
void
nsScriptElement::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
MaybeProcessScript();
}
void
nsScriptElement::ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
MaybeProcessScript();
}
static PRBool
InNonScriptingContainer(nsINode* aNode)
{
aNode = aNode->GetNodeParent();
while (aNode) {
// XXX noframes and noembed are currently unconditionally not
// displayed and processed. This might change if we support either
// prefs or per-document container settings for not allowing
// frames or plugins.
if (aNode->IsNodeOfType(nsINode::eHTML)) {
nsIAtom *localName = NS_STATIC_CAST(nsIContent*, aNode)->Tag();
if (localName == nsGkAtoms::iframe ||
localName == nsGkAtoms::noframes ||
localName == nsGkAtoms::noembed) {
return PR_TRUE;
}
}
aNode = aNode->GetNodeParent();
}
return PR_FALSE;
}
nsresult
nsScriptElement::MaybeProcessScript()
{
nsCOMPtr<nsIContent> cont =
do_QueryInterface((nsIScriptElement*) this);
NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this),
"You forgot to add self as observer");
if (mIsEvaluated || !mDoneAddingChildren || !cont->IsInDoc() ||
mMalformed || InNonScriptingContainer(cont) ||
!(cont->HasAttr(kNameSpaceID_None, nsGkAtoms::src) ||
cont->GetChildCount())) {
return NS_OK;
}
nsresult scriptresult = NS_OK;
nsRefPtr<nsScriptLoader> loader = cont->GetOwnerDoc()->GetScriptLoader();
if (loader) {
mIsEvaluated = PR_TRUE;
scriptresult = loader->ProcessScriptElement(this);
// The only error we don't ignore is NS_ERROR_HTMLPARSER_BLOCK
// However we don't want to override other success values
// (such as NS_CONTENT_SCRIPT_IS_EVENTHANDLER)
if (NS_FAILED(scriptresult) &&
scriptresult != NS_ERROR_HTMLPARSER_BLOCK) {
scriptresult = NS_OK;
}
}
return scriptresult;
}

View File

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jonas Sicking <jonas@sicking.cc> (original developer)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIScriptLoaderObserver.h"
#include "nsIScriptElement.h"
#include "nsStubMutationObserver.h"
#include "prtypes.h"
/**
* Baseclass useful for script elements (such as <xhtml:script> and
* <svg:script>). Currently the class assumes that only the 'src'
* attribute and the children of the class affect what script to execute.
*/
class nsScriptElement : public nsIScriptElement,
public nsStubMutationObserver
{
public:
// nsIScriptLoaderObserver
NS_DECL_NSISCRIPTLOADEROBSERVER
// nsIMutationObserver
virtual void CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRBool aAppend);
virtual void AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
virtual void ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
virtual void ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
protected:
// Internal methods
/**
* Processes the script if it's in the document-tree and links to or
* contains a script. Once it has been evaluated there is no way to make it
* reevaluate the script, you'll have to create a new element. This also means
* that when adding a src attribute to an element that already contains an
* inline script, the script referenced by the src attribute will not be
* loaded.
*
* In order to be able to use multiple childNodes, or to use the
* fallback mechanism of using both inline script and linked script you have
* to add all attributes and childNodes before adding the element to the
* document-tree.
*/
virtual nsresult MaybeProcessScript();
};

View File

@ -67,6 +67,7 @@
#include "nsAutoPtr.h"
#include "nsIXPConnect.h"
#include "nsContentErrors.h"
#include "nsIParser.h"
//////////////////////////////////////////////////////////////
//
@ -117,18 +118,27 @@ MaybeDowngradeToCodebase(nsIPrincipal *aMaybeCertPrincipal,
class nsScriptLoadRequest : public nsISupports {
public:
nsScriptLoadRequest(nsIScriptElement* aElement,
nsIScriptLoaderObserver* aObserver,
PRUint32 aVersion);
virtual ~nsScriptLoadRequest();
PRUint32 aVersion)
: mElement(aElement),
mLoading(PR_TRUE), mWasPending(PR_FALSE),
mIsInline(PR_TRUE),
mJSVersion(aVersion), mLineNo(1)
{
}
NS_DECL_ISUPPORTS
void FireScriptAvailable(nsresult aResult,
const nsAFlatString& aScript);
void FireScriptEvaluated(nsresult aResult);
void FireScriptAvailable(nsresult aResult)
{
mElement->ScriptAvailable(aResult, mElement, mIsInline, mWasPending,
mURI, mLineNo);
}
void FireScriptEvaluated(nsresult aResult)
{
mElement->ScriptEvaluated(aResult, mElement, mIsInline, mWasPending);
}
nsCOMPtr<nsIScriptElement> mElement;
nsCOMPtr<nsIScriptLoaderObserver> mObserver;
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?
@ -138,52 +148,19 @@ public:
PRInt32 mLineNo;
};
nsScriptLoadRequest::nsScriptLoadRequest(nsIScriptElement* aElement,
nsIScriptLoaderObserver* aObserver,
PRUint32 aVersion) :
mElement(aElement), mObserver(aObserver),
mLoading(PR_TRUE), mWasPending(PR_FALSE),
mIsInline(PR_TRUE),
mJSVersion(aVersion), mLineNo(1)
{
}
nsScriptLoadRequest::~nsScriptLoadRequest()
{
}
// The nsScriptLoadRequest is passed as the context to necko, and thus
// it needs to be threadsafe. Necko won't do anything with this
// context, but it will AddRef and Release it on other threads.
NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLoadRequest)
void
nsScriptLoadRequest::FireScriptAvailable(nsresult aResult,
const nsAFlatString& aScript)
{
if (mObserver) {
mObserver->ScriptAvailable(aResult, mElement, mIsInline, mWasPending,
mURI, mLineNo,
aScript);
}
}
void
nsScriptLoadRequest::FireScriptEvaluated(nsresult aResult)
{
if (mObserver) {
mObserver->ScriptEvaluated(aResult, mElement, mIsInline, mWasPending);
}
}
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
nsScriptLoader::nsScriptLoader()
: mDocument(nsnull), mEnabled(PR_TRUE)
nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
: mDocument(aDocument),
mBlockerCount(0),
mEnabled(PR_TRUE)
{
}
@ -191,98 +168,12 @@ nsScriptLoader::~nsScriptLoader()
{
mObservers.Clear();
PRInt32 count = mPendingRequests.Count();
for (PRInt32 i = 0; i < count; i++) {
nsScriptLoadRequest* req = mPendingRequests[i];
if (req) {
req->FireScriptAvailable(NS_ERROR_ABORT, EmptyString());
}
for (PRInt32 i = 0; i < mPendingRequests.Count(); i++) {
mPendingRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
}
mPendingRequests.Clear();
}
NS_INTERFACE_MAP_BEGIN(nsScriptLoader)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptLoader)
NS_INTERFACE_MAP_ENTRY(nsIScriptLoader)
NS_INTERFACE_MAP_ENTRY(nsIStreamLoaderObserver)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsScriptLoader)
NS_IMPL_RELEASE(nsScriptLoader)
/* void init (in nsIDocument aDocument); */
NS_IMETHODIMP
nsScriptLoader::Init(nsIDocument *aDocument)
{
mDocument = aDocument;
return NS_OK;
}
/* void dropDocumentReference (); */
NS_IMETHODIMP
nsScriptLoader::DropDocumentReference()
{
mDocument = nsnull;
return NS_OK;
}
/* void addObserver (in nsIScriptLoaderObserver aObserver); */
NS_IMETHODIMP
nsScriptLoader::AddObserver(nsIScriptLoaderObserver *aObserver)
{
NS_ENSURE_ARG(aObserver);
mObservers.AppendObject(aObserver);
return NS_OK;
}
/* void removeObserver (in nsIScriptLoaderObserver aObserver); */
NS_IMETHODIMP
nsScriptLoader::RemoveObserver(nsIScriptLoaderObserver *aObserver)
{
NS_ENSURE_ARG(aObserver);
mObservers.RemoveObject(aObserver);
return NS_OK;
}
PRBool
nsScriptLoader::InNonScriptingContainer(nsIScriptElement* aScriptElement)
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aScriptElement));
nsCOMPtr<nsIDOMNode> parent;
node->GetParentNode(getter_AddRefs(parent));
while (parent) {
nsCOMPtr<nsIContent> content(do_QueryInterface(parent));
if (!content) {
break;
}
nsIAtom *localName = content->Tag();
// XXX noframes and noembed are currently unconditionally not
// displayed and processed. This might change if we support either
// prefs or per-document container settings for not allowing
// frames or plugins.
if (content->IsNodeOfType(nsINode::eHTML) &&
(localName == nsHTMLAtoms::iframe ||
localName == nsHTMLAtoms::noframes ||
localName == nsHTMLAtoms::noembed)) {
return PR_TRUE;
}
node = parent;
node->GetParentNode(getter_AddRefs(parent));
}
return PR_FALSE;
}
NS_IMPL_ISUPPORTS1(nsScriptLoader, nsIStreamLoaderObserver)
// Helper method for checking if the script element is an event-handler
// This means that it has both a for-attribute and a event-attribute.
@ -292,8 +183,8 @@ nsScriptLoader::InNonScriptingContainer(nsIScriptElement* aScriptElement)
// This is how IE seems to filter out a window's onload handler from a
// <script for=... event=...> element.
PRBool
nsScriptLoader::IsScriptEventHandler(nsIScriptElement *aScriptElement)
static PRBool
IsScriptEventHandler(nsIScriptElement *aScriptElement)
{
nsCOMPtr<nsIContent> contElement = do_QueryInterface(aScriptElement);
NS_ASSERTION(contElement, "nsIScriptElement isn't nsIContent");
@ -335,44 +226,19 @@ nsScriptLoader::IsScriptEventHandler(nsIScriptElement *aScriptElement)
}
/* void processScriptElement (in nsIScriptElement aElement, in nsIScriptLoaderObserver aObserver); */
NS_IMETHODIMP
nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement,
nsIScriptLoaderObserver *aObserver)
{
PRBool fireErrorNotification;
nsresult rv = DoProcessScriptElement(aElement, aObserver,
&fireErrorNotification);
if (fireErrorNotification) {
// Note that rv _can_ be a success code here. It just can't be NS_OK.
NS_ASSERTION(rv != NS_OK, "Firing error notification for NS_OK?");
FireErrorNotification(rv, aElement, aObserver);
}
return rv;
}
nsresult
nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
nsIScriptLoaderObserver *aObserver,
PRBool* aFireErrorNotification)
nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
{
// Default to firing the error notification until we've actually gotten to
// loading or running the script.
*aFireErrorNotification = PR_TRUE;
NS_ENSURE_ARG(aElement);
// We need a document to evaluate scripts.
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
// Check to see that the element is not in a container that
// suppresses script evaluation within it and that we should be
// evaluating scripts for this document in the first place.
if (!mEnabled || !mDocument->IsScriptEnabled() ||
aElement->IsMalformed() || InNonScriptingContainer(aElement)) {
// Check to see if scripts has been turned off.
if (!mEnabled || !mDocument->IsScriptEnabled()) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ASSERTION(!aElement->IsMalformed(), "Executing malformed script");
// Check that the script is not an eventhandler
if (IsScriptEventHandler(aElement)) {
return NS_CONTENT_SCRIPT_IS_EVENTHANDLER;
@ -385,6 +251,7 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
// the attributes to locate the script-type?
// For now though, if JS is disabled we assume every language is
// disabled.
// XXX is this different from the mDocument->IsScriptEnabled() call?
nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject();
if (globalObject)
{
@ -540,13 +407,10 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
}
nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement));
if (eltContent)
eltContent->SetScriptTypeID(typeID);
else
NS_ERROR("Element is not nsIContent - can't set scripttype");
eltContent->SetScriptTypeID(typeID);
// Create a request object for this script
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, aObserver, version);
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version);
NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
// First check to see if this is an external script
@ -583,9 +447,6 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
request->mWasPending = PR_TRUE;
request->mLoading = PR_TRUE;
// Add the request to our pending requests list
mPendingRequests.AppendObject(request);
nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
nsCOMPtr<nsIStreamLoader> loader;
@ -598,27 +459,22 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
rv = NS_NewChannel(getter_AddRefs(channel),
scriptURI, nsnull, loadGroup,
prompter, nsIRequest::LOAD_NORMAL);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if (httpChannel) {
// HTTP content negotation has little value in this context.
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
NS_LITERAL_CSTRING("*/*"),
PR_FALSE);
httpChannel->SetReferrer(mDocument->GetDocumentURI());
}
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
if (NS_SUCCEEDED(rv))
rv = channel->AsyncOpen(loader, request);
}
if (NS_FAILED(rv)) {
mPendingRequests.RemoveObject(request);
return rv;
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if (httpChannel) {
// HTTP content negotation has little value in this context.
httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
NS_LITERAL_CSTRING("*/*"),
PR_FALSE);
httpChannel->SetReferrer(mDocument->GetDocumentURI());
}
// At this point we've successfully started the load, so we need not call
// FireErrorNotification anymore.
*aFireErrorNotification = PR_FALSE;
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->AsyncOpen(loader, request);
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
request->mLoading = PR_FALSE;
@ -629,63 +485,28 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
// If we've got existing pending requests, add ourselves
// to this list.
if (mPendingRequests.Count() > 0) {
request->mWasPending = PR_TRUE;
NS_ENSURE_TRUE(mPendingRequests.AppendObject(request),
NS_ERROR_OUT_OF_MEMORY);
}
else {
request->mWasPending = PR_FALSE;
rv = ProcessRequest(request);
if (ReadyToExecuteScripts() && mPendingRequests.Count() == 0) {
NS_ASSERTION(!request->mWasPending, "should not be pending");
return ProcessRequest(request);
}
// We're either going to, or have run this inline script, so we shouldn't
// call FireErrorNotification for it.
*aFireErrorNotification = PR_FALSE;
request->mWasPending = PR_TRUE;
}
return rv;
}
// Add the request to our pending requests list
NS_ENSURE_TRUE(mPendingRequests.AppendObject(request),
NS_ERROR_OUT_OF_MEMORY);
nsresult
nsScriptLoader::GetCurrentScript(nsIScriptElement **aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
*aElement = mCurrentScript;
NS_IF_ADDREF(*aElement);
return NS_OK;
}
void
nsScriptLoader::FireErrorNotification(nsresult aResult,
nsIScriptElement* aElement,
nsIScriptLoaderObserver* aObserver)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIScriptLoaderObserver> observer = mObservers[i];
if (observer) {
observer->ScriptAvailable(aResult, aElement,
PR_TRUE, PR_FALSE,
nsnull, 0,
EmptyString());
}
}
if (aObserver) {
aObserver->ScriptAvailable(aResult, aElement,
PR_TRUE, PR_FALSE,
nsnull, 0,
EmptyString());
}
// Added as pending request, now we can send blocking back
return NS_ERROR_HTMLPARSER_BLOCK;
}
nsresult
nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
{
NS_ASSERTION(ReadyToExecuteScripts(),
"Caller forgot to check ReadyToExecuteScripts()");
NS_ENSURE_ARG(aRequest);
nsAFlatString* script;
nsAutoString textData;
@ -702,7 +523,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
script = &aRequest->mScriptText;
}
FireScriptAvailable(NS_OK, aRequest, *script);
FireScriptAvailable(NS_OK, aRequest);
nsresult rv = EvaluateScript(aRequest, *script);
FireScriptEvaluated(rv, aRequest);
@ -711,36 +532,26 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest)
void
nsScriptLoader::FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript)
nsScriptLoadRequest* aRequest)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIScriptLoaderObserver> observer = mObservers[i];
if (observer) {
observer->ScriptAvailable(aResult, aRequest->mElement,
aRequest->mIsInline, aRequest->mWasPending,
aRequest->mURI, aRequest->mLineNo,
aScript);
}
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
obs->ScriptAvailable(aResult, aRequest->mElement,
aRequest->mIsInline, aRequest->mWasPending,
aRequest->mURI, aRequest->mLineNo);
}
aRequest->FireScriptAvailable(aResult, aScript);
aRequest->FireScriptAvailable(aResult);
}
void
nsScriptLoader::FireScriptEvaluated(nsresult aResult,
nsScriptLoadRequest* aRequest)
{
PRInt32 count = mObservers.Count();
for (PRInt32 i = 0; i < count; i++) {
nsCOMPtr<nsIScriptLoaderObserver> observer = mObservers[i];
if (observer) {
observer->ScriptEvaluated(aResult, aRequest->mElement,
aRequest->mIsInline, aRequest->mWasPending);
}
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
nsCOMPtr<nsIScriptLoaderObserver> obs = mObservers[i];
obs->ScriptEvaluated(aResult, aRequest->mElement,
aRequest->mIsInline, aRequest->mWasPending);
}
aRequest->FireScriptEvaluated(aResult);
@ -829,20 +640,13 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
}
void
nsScriptLoader::ProcessPendingReqests()
nsScriptLoader::ProcessPendingRequests()
{
if (mPendingRequests.Count() == 0) {
return;
}
nsRefPtr<nsScriptLoadRequest> request = mPendingRequests[0];
while (request && !request->mLoading) {
nsRefPtr<nsScriptLoadRequest> request;
while (ReadyToExecuteScripts() && mPendingRequests.Count() &&
!(request = mPendingRequests[0])->mLoading) {
mPendingRequests.RemoveObjectAt(0);
ProcessRequest(request);
if (mPendingRequests.Count() == 0) {
return;
}
request = mPendingRequests[0];
}
}
@ -975,67 +779,69 @@ NS_IMETHODIMP
nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
PRUint32 stringLen,
const PRUint8* string)
PRUint32 aStringLen,
const PRUint8* aString)
{
nsresult rv;
nsScriptLoadRequest* request = NS_STATIC_CAST(nsScriptLoadRequest*, aContext);
NS_ASSERTION(request, "null request in stream complete handler");
if (!request) {
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
nsresult rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen,
aString);
if (NS_FAILED(rv)) {
mPendingRequests.RemoveObject(request);
FireScriptAvailable(rv, request);
}
// Process our request and/or any pending ones
ProcessPendingRequests();
return NS_OK;
}
nsresult
nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
nsresult aStatus,
PRUint32 aStringLen,
const PRUint8* aString)
{
if (NS_FAILED(aStatus)) {
mPendingRequests.RemoveObject(request);
FireScriptAvailable(aStatus, request, EmptyString());
ProcessPendingReqests();
return NS_OK;
return aStatus;
}
// If we don't have a document, then we need to abort further
// evaluation.
if (!mDocument) {
mPendingRequests.RemoveObject(request);
FireScriptAvailable(NS_ERROR_NOT_AVAILABLE, request,
EmptyString());
ProcessPendingReqests();
return NS_OK;
return NS_ERROR_NOT_AVAILABLE;
}
// If the load returned an error page, then we need to abort
nsCOMPtr<nsIRequest> req;
rv = aLoader->GetRequest(getter_AddRefs(req));
nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
NS_ASSERTION(req, "StreamLoader's request went away prematurely");
if (NS_FAILED(rv)) return rv; // XXX Should this remove the pending request?
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(req));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(req);
if (httpChannel) {
PRBool requestSucceeded;
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
if (NS_SUCCEEDED(rv) && !requestSucceeded) {
mPendingRequests.RemoveObject(request);
FireScriptAvailable(NS_ERROR_NOT_AVAILABLE, request,
EmptyString());
ProcessPendingReqests();
return NS_OK;
return NS_ERROR_NOT_AVAILABLE;
}
}
nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
if (stringLen) {
if (aStringLen) {
// Check the charset attribute to determine script charset.
nsAutoString hintCharset;
request->mElement->GetScriptCharset(hintCharset);
rv = ConvertToUTF16(channel, string, stringLen, hintCharset, mDocument,
request->mScriptText);
aRequest->mElement->GetScriptCharset(hintCharset);
rv = ConvertToUTF16(channel, aString, aStringLen, hintCharset, mDocument,
aRequest->mScriptText);
NS_ASSERTION(NS_SUCCEEDED(rv),
"Could not convert external JavaScript to Unicode!");
if (NS_FAILED(rv)) {
mPendingRequests.RemoveObject(request);
FireScriptAvailable(rv, request, EmptyString());
ProcessPendingReqests();
return NS_OK;
}
NS_ENSURE_SUCCESS(rv, rv);
// -- Merge the principal of the script file with that of the document; if
// the script has a non-cert principal, the document's principal should be
@ -1054,35 +860,15 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
}
}
// This assertion could fire errorously if we ran out of memory when
// inserting the request in the array. However it's an unlikely case
// so if you see this assertion it is likely something else that is
// wrong, especially if you see it more than once.
NS_ASSERTION(mPendingRequests.IndexOf(aRequest) >= 0,
"aRequest should be pending!");
// If we're not the first in the pending list, we mark ourselves
// as loaded and just stay on the list.
NS_ASSERTION(mPendingRequests.Count() > 0, "aContext is a pending request!");
if (mPendingRequests[0] != request) {
request->mLoading = PR_FALSE;
return NS_OK;
}
mPendingRequests.RemoveObject(request);
ProcessRequest(request);
// Process any pending requests
ProcessPendingReqests();
// Mark this as loaded
aRequest->mLoading = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsScriptLoader::GetEnabled(PRBool *aEnabled)
{
NS_ENSURE_ARG_POINTER(aEnabled);
*aEnabled = mEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsScriptLoader::SetEnabled(PRBool aEnabled)
{
mEnabled = aEnabled;
return NS_OK;
}

View File

@ -44,9 +44,7 @@
#define __nsScriptLoader_h__
#include "nsCOMPtr.h"
#include "nsIScriptLoader.h"
#include "nsIScriptElement.h"
#include "nsIScriptLoaderObserver.h"
#include "nsIURI.h"
#include "nsCOMArray.h"
#include "nsIDocument.h"
@ -58,17 +56,107 @@ class nsScriptLoadRequest;
// Script loader implementation
//////////////////////////////////////////////////////////////
class nsScriptLoader : public nsIScriptLoader,
public nsIStreamLoaderObserver
class nsScriptLoader : public nsIStreamLoaderObserver
{
public:
nsScriptLoader();
nsScriptLoader(nsIDocument* aDocument);
virtual ~nsScriptLoader();
NS_DECL_ISUPPORTS
NS_DECL_NSISCRIPTLOADER
NS_DECL_NSISTREAMLOADEROBSERVER
/**
* The loader maintains a weak reference to the document with
* which it is initialized. This call forces the reference to
* be dropped.
*/
void DropDocumentReference()
{
mDocument = nsnull;
}
/**
* Add an observer for all scripts loaded through this loader.
*
* @param aObserver observer for all script processing.
*/
nsresult AddObserver(nsIScriptLoaderObserver* aObserver)
{
return mObservers.AppendObject(aObserver) ? NS_OK :
NS_ERROR_OUT_OF_MEMORY;
}
/**
* Remove an observer.
*
* @param aObserver observer to be removed
*/
void RemoveObserver(nsIScriptLoaderObserver* aObserver)
{
mObservers.RemoveObject(aObserver);
}
/**
* Process a script element. This will include both loading the
* source of the element if it is not inline and evaluating
* the script itself.
*
* If the script is an inline script that can be executed immediately
* (i.e. there are no other scripts pending) then ScriptAvailable
* and ScriptEvaluated will be called before the function returns.
*
* If NS_ERROR_HTMLPARSER_BLOCK is returned the script could not be
* executed immediately. In this case ScriptAvailable is guaranteed
* to be called at a later point (as well as possibly ScriptEvaluated).
*
* @param aElement The element representing the script to be loaded and
* evaluated.
*/
nsresult ProcessScriptElement(nsIScriptElement* aElement);
/**
* Gets the currently executing script. This is useful if you want to
* generate a unique key based on the currently executing script.
*/
nsIScriptElement* GetCurrentScript()
{
return mCurrentScript;
}
/**
* Whether the loader is enabled or not.
* When disabled, processing of new script elements is disabled.
* Any call to ProcessScriptElement() will fail with a return code of
* NS_ERROR_NOT_AVAILABLE. Note that this DOES NOT disable
* currently loading or executing scripts.
*/
PRBool GetEnabled()
{
return mEnabled;
}
void SetEnabled(PRBool aEnabled)
{
mEnabled = aEnabled;
}
/**
* Add/remove blocker. Blockers will stop scripts from executing, but not
* from loading.
* NOTE! Calling RemoveExecuteBlocker could potentially execute pending
* scripts synchronously. In other words, it should not be done at 'unsafe'
* times
*/
void AddExecuteBlocker()
{
++mBlockerCount;
}
void RemoveExecuteBlocker()
{
if (!--mBlockerCount) {
ProcessPendingRequests();
}
}
/**
* Convert the given buffer to a UTF-16 string.
* @param aChannel Channel corresponding to the data. May be null.
@ -86,33 +174,32 @@ public:
nsIDocument* aDocument, nsString& aString);
protected:
PRBool InNonScriptingContainer(nsIScriptElement* aScriptElement);
PRBool IsScriptEventHandler(nsIScriptElement* aScriptElement);
void FireErrorNotification(nsresult aResult,
nsIScriptElement* aElement,
nsIScriptLoaderObserver* aObserver);
PRBool ReadyToExecuteScripts()
{
return !mBlockerCount;
}
nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
void FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript);
nsScriptLoadRequest* aRequest);
void FireScriptEvaluated(nsresult aResult,
nsScriptLoadRequest* aRequest);
nsresult EvaluateScript(nsScriptLoadRequest* aRequest,
const nsAFlatString& aScript);
void ProcessPendingReqests();
void ProcessPendingRequests();
// The guts of ProcessScriptElement. If aFireErrorNotification is
// true, FireErrorNotification should be called with the return
// value of this method.
nsresult DoProcessScriptElement(nsIScriptElement *aElement,
nsIScriptLoaderObserver *aObserver,
PRBool* aFireErrorNotification);
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
nsresult aStatus,
PRUint32 aStringLen,
const PRUint8* aString);
nsIDocument* mDocument; // [WEAK]
nsCOMArray<nsIScriptLoaderObserver> mObservers;
nsCOMArray<nsScriptLoadRequest> mPendingRequests;
nsCOMPtr<nsIScriptElement> mCurrentScript;
PRBool mEnabled;
PRUint32 mBlockerCount;
PRPackedBool mEnabled;
};
#endif //__nsScriptLoader_h__

View File

@ -87,7 +87,7 @@
#include "nsIViewManager.h"
#include "nsINameSpaceManager.h"
#include "nsDOMError.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsRuleData.h"
#include "nsPresState.h"
@ -886,22 +886,17 @@ nsGenericHTMLElement::SetInnerHTML(const nsAString& aInnerHTML)
nsCOMPtr<nsIDocument> doc = GetOwnerDoc();
// Strong ref since appendChild can fire events
nsCOMPtr<nsIScriptLoader> loader;
nsRefPtr<nsScriptLoader> loader;
PRBool scripts_enabled = PR_FALSE;
if (doc) {
loader = doc->GetScriptLoader();
if (loader) {
loader->GetEnabled(&scripts_enabled);
scripts_enabled = loader->GetEnabled();
loader->SetEnabled(PR_FALSE);
}
}
if (scripts_enabled) {
// Don't let scripts execute while setting .innerHTML.
loader->SetEnabled(PR_FALSE);
}
nsCOMPtr<nsIDOMNode> thisNode(do_QueryInterface(NS_STATIC_CAST(nsIContent *,
this)));
nsresult rv = nsContentUtils::CreateContextualFragment(thisNode, aInnerHTML,

View File

@ -93,7 +93,7 @@ public:
NS_IMETHOD SubmitNamesValues(nsIFormSubmission *aFormSubmission,
nsIContent *aSubmitElement);
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
@ -140,7 +140,7 @@ nsHTMLObjectElement::IsDoneAddingChildren()
return mIsDoneAddingChildren;
}
void
nsresult
nsHTMLObjectElement::DoneAddingChildren(PRBool aHaveNotified)
{
mIsDoneAddingChildren = PR_TRUE;
@ -150,6 +150,7 @@ nsHTMLObjectElement::DoneAddingChildren(PRBool aHaveNotified)
if (IsInDoc()) {
StartObjectLoad(aHaveNotified);
}
return NS_OK;
}
NS_IMPL_ADDREF_INHERITED(nsHTMLObjectElement, nsGenericElement)

View File

@ -40,16 +40,12 @@
#include "nsGenericHTMLElement.h"
#include "nsHTMLAtoms.h"
#include "nsStyleConsts.h"
#include "nsPresContext.h"
#include "nsIDocument.h"
#include "nsIScriptLoader.h"
#include "nsIScriptLoaderObserver.h"
#include "nsIScriptElement.h"
#include "nsGUIEvent.h"
#include "nsScriptElement.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsUnicharUtils.h" // for nsCaseInsensitiveCaseComparator()
#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator()
#include "jsapi.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
@ -57,7 +53,6 @@
#include "nsServiceManagerUtils.h"
#include "nsIScriptEventHandler.h"
#include "nsIDOMDocument.h"
#include "nsEventDispatcher.h"
#include "nsContentErrors.h"
#include "nsIArray.h"
#include "nsDOMJSUtils.h"
@ -316,8 +311,7 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
class nsHTMLScriptElement : public nsGenericHTMLElement,
public nsIDOMHTMLScriptElement,
public nsIScriptLoaderObserver,
public nsIScriptElement
public nsScriptElement
{
public:
nsHTMLScriptElement(nsINodeInfo *aNodeInfo, PRBool aFromParser);
@ -338,38 +332,20 @@ public:
// nsIDOMHTMLScriptElement
NS_DECL_NSIDOMHTMLSCRIPTELEMENT
// nsIScriptLoaderObserver
NS_DECL_NSISCRIPTLOADEROBSERVER
// nsIScriptElement
virtual void GetScriptType(nsAString& type);
virtual already_AddRefed<nsIURI> GetScriptURI();
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual void SetScriptLineNumber(PRUint32 aLineNumber);
virtual PRUint32 GetScriptLineNumber();
virtual void SetIsMalformed();
virtual PRBool IsMalformed();
// nsIContent
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -377,11 +353,6 @@ public:
protected:
PRBool IsOnloadEventForWindow();
PRUint32 mLineNumber;
PRPackedBool mIsEvaluated;
PRPackedBool mEvaluating;
PRPackedBool mDoneAddingChildren;
PRPackedBool mMalformed;
// Pointer to the script handler helper object (OWNING reference)
nsCOMPtr<nsHTMLScriptEventHandler> mScriptEventHandler;
@ -399,7 +370,7 @@ protected:
* to add all attributes and childNodes before adding the element to the
* document-tree.
*/
void MaybeProcessScript();
virtual nsresult MaybeProcessScript();
};
@ -408,13 +379,10 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
nsHTMLScriptElement::nsHTMLScriptElement(nsINodeInfo *aNodeInfo,
PRBool aFromParser)
: nsGenericHTMLElement(aNodeInfo),
mLineNumber(0),
mIsEvaluated(PR_FALSE),
mEvaluating(PR_FALSE),
mDoneAddingChildren(!aFromParser),
mMalformed(PR_FALSE)
: nsGenericHTMLElement(aNodeInfo)
{
mDoneAddingChildren = !aFromParser;
AddMutationObserver(this);
}
nsHTMLScriptElement::~nsHTMLScriptElement()
@ -430,6 +398,7 @@ NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLScriptElement, nsGenericHTMLElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLScriptElement)
NS_INTERFACE_MAP_ENTRY(nsIScriptLoaderObserver)
NS_INTERFACE_MAP_ENTRY(nsIScriptElement)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
if (mScriptEventHandler && aIID.Equals(NS_GET_IID(nsIScriptEventHandler)))
foundInterface = NS_STATIC_CAST(nsIScriptEventHandler*,
mScriptEventHandler);
@ -438,26 +407,6 @@ NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLScriptElement, nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_MAP_END
nsresult
nsHTMLScriptElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
if (aNameSpaceID != kNameSpaceID_None) {
return rv;
}
if (aNotify && aName == nsHTMLAtoms::src) {
MaybeProcessScript();
}
return rv;
}
nsresult
nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
@ -472,19 +421,7 @@ nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
MaybeProcessScript();
}
return rv;
}
nsresult
nsHTMLScriptElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
if (NS_SUCCEEDED(rv) && aNotify) {
MaybeProcessScript();
}
return rv;
return NS_OK;
}
nsresult
@ -504,7 +441,7 @@ nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
// The clone should be marked evaluated if we are. It should also be marked
// evaluated if we're evaluating, to handle the case when this script node's
// script clones the node.
it->mIsEvaluated = mIsEvaluated || mEvaluating;
it->mIsEvaluated = mIsEvaluated;
it->mLineNumber = mLineNumber;
it->mMalformed = mMalformed;
@ -547,11 +484,11 @@ nsHTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML)
return nsContentUtils::SetNodeTextContent(this, aInnerHTML, PR_TRUE);
}
void
nsresult
nsHTMLScriptElement::DoneAddingChildren(PRBool aHaveNotified)
{
mDoneAddingChildren = PR_TRUE;
MaybeProcessScript();
return MaybeProcessScript();
}
PRBool
@ -563,67 +500,6 @@ nsHTMLScriptElement::IsDoneAddingChildren()
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying
/* void scriptAvailable (in nsresult aResult, in nsIScriptElement aElement , in nsIURI aURI, in PRInt32 aLineNo, in PRUint32 aScriptLength, [size_is (aScriptLength)] in wstring aScript); */
NS_IMETHODIMP
nsHTMLScriptElement::ScriptAvailable(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString& aScript)
{
if (!aIsInline && NS_FAILED(aResult)) {
nsEventStatus status = nsEventStatus_eIgnore;
nsScriptErrorEvent event(PR_TRUE, NS_LOAD_ERROR);
event.lineNr = aLineNo;
NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
event.errorMsg = errorString.get();
nsCAutoString spec;
aURI->GetSpec(spec);
NS_ConvertUTF8toUTF16 fileName(spec);
event.fileName = fileName.get();
nsCOMPtr<nsPresContext> presContext = GetPresContext();
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return NS_OK;
}
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying
/* void scriptEvaluated (in nsresult aResult, in nsIScriptElement aElement); */
NS_IMETHODIMP
nsHTMLScriptElement::ScriptEvaluated(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending)
{
nsresult rv = NS_OK;
if (!aIsInline) {
nsEventStatus status = nsEventStatus_eIgnore;
PRUint32 type = NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR;
nsEvent event(PR_TRUE, type);
if (type == NS_LOAD) {
// Load event doesn't bubble.
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
}
nsCOMPtr<nsPresContext> presContext = GetPresContext();
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return rv;
}
void
nsHTMLScriptElement::GetScriptType(nsAString& type)
{
@ -656,50 +532,10 @@ nsHTMLScriptElement::GetScriptCharset(nsAString& charset)
GetCharset(charset);
}
void
nsHTMLScriptElement::SetScriptLineNumber(PRUint32 aLineNumber)
{
mLineNumber = aLineNumber;
}
PRUint32
nsHTMLScriptElement::GetScriptLineNumber()
{
return mLineNumber;
}
void
nsHTMLScriptElement::SetIsMalformed()
{
mMalformed = PR_TRUE;
}
PRBool
nsHTMLScriptElement::IsMalformed()
{
return mMalformed;
}
// variation of this code in nsSVGScriptElement - check if changes
// need to be transfered when modifying
void
nsresult
nsHTMLScriptElement::MaybeProcessScript()
{
if (mIsEvaluated || mEvaluating || !mDoneAddingChildren || !IsInDoc()) {
return;
}
// We'll always call this to make sure that
// ScriptAvailable/ScriptEvaluated gets called. See bug 153600
nsresult rv = NS_OK;
nsCOMPtr<nsIScriptLoader> loader = GetOwnerDoc()->GetScriptLoader();
if (loader) {
mEvaluating = PR_TRUE;
rv = loader->ProcessScriptElement(this, this);
mEvaluating = PR_FALSE;
}
nsresult rv = nsScriptElement::MaybeProcessScript();
if (rv == NS_CONTENT_SCRIPT_IS_EVENTHANDLER) {
// If the script has NOT been executed yet then create a script
@ -710,9 +546,7 @@ nsHTMLScriptElement::MaybeProcessScript()
mIsEvaluated = PR_TRUE;
mScriptEventHandler = new nsHTMLScriptEventHandler(this);
if (!mScriptEventHandler) {
return;
}
NS_ENSURE_TRUE(mScriptEventHandler, NS_ERROR_OUT_OF_MEMORY);
// The script-loader will make sure that the script is not evaluated
// right away.
@ -725,10 +559,5 @@ nsHTMLScriptElement::MaybeProcessScript()
}
}
// But we'll only set mIsEvaluated if we did really load or evaluate
// something
if (HasAttr(kNameSpaceID_None, nsHTMLAtoms::src) ||
mAttrsAndChildren.ChildCount()) {
mIsEvaluated = PR_TRUE;
}
return rv;
}

View File

@ -271,7 +271,7 @@ public:
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
@ -1714,7 +1714,7 @@ nsHTMLSelectElement::IsDoneAddingChildren()
return mIsDoneAddingChildren;
}
void
nsresult
nsHTMLSelectElement::DoneAddingChildren(PRBool aHaveNotified)
{
mIsDoneAddingChildren = PR_TRUE;
@ -1739,6 +1739,8 @@ nsHTMLSelectElement::DoneAddingChildren(PRBool aHaveNotified)
// Now that we're done, select something (if it's a single select something
// must be selected)
CheckSelectSomething();
return NS_OK;
}
PRBool

View File

@ -112,7 +112,7 @@ public:
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
virtual PRUint32 GetDesiredIMEState();
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
@ -181,7 +181,7 @@ nsHTMLSharedObjectElement::IsDoneAddingChildren()
return mIsDoneAddingChildren;
}
void
nsresult
nsHTMLSharedObjectElement::DoneAddingChildren(PRBool aHaveNotified)
{
if (!mIsDoneAddingChildren) {
@ -193,6 +193,8 @@ nsHTMLSharedObjectElement::DoneAddingChildren(PRBool aHaveNotified)
StartObjectLoad(aHaveNotified);
}
}
return NS_OK;
}
NS_IMPL_ADDREF_INHERITED(nsHTMLSharedObjectElement, nsGenericElement)

View File

@ -138,7 +138,7 @@ public:
virtual void SetFocus(nsPresContext* aPresContext);
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual PRBool IsDoneAddingChildren();
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -641,7 +641,7 @@ nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
return NS_OK;
}
void
nsresult
nsHTMLTextAreaElement::DoneAddingChildren(PRBool aHaveNotified)
{
if (!mValueChanged) {
@ -655,6 +655,8 @@ nsHTMLTextAreaElement::DoneAddingChildren(PRBool aHaveNotified)
}
mDoneAddingChildren = PR_TRUE;
return NS_OK;
}
PRBool

View File

@ -48,7 +48,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIParser.h"
#include "nsParserUtils.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIPresShell.h"
@ -273,8 +273,10 @@ public:
NS_DECL_NSITIMERCALLBACK
// nsIDocumentObserver
virtual void BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType);
virtual void EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType);
virtual void BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType,
PRUint32 aNestingLevel);
virtual void EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType,
PRUint32 aNestingLevel);
#ifdef DEBUG
// nsIDebugDumpContent
@ -425,7 +427,6 @@ protected:
// Routines for tags that require special handling when we reach their end
// tag.
nsresult ProcessSCRIPTEndTag(nsGenericHTMLElement* content,
PRBool aHaveNotified,
PRBool aMalformed);
nsresult ProcessSTYLEEndTag(nsGenericHTMLElement* content);
@ -1249,7 +1250,6 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed)
case eHTMLTag_script:
result = mSink->ProcessSCRIPTEndTag(content,
HaveNotifiedForCurrentContent(),
aMalformed);
break;
@ -1588,6 +1588,10 @@ SinkContext::FlushTags(PRBool aNotify)
FlushText();
if (aNotify) {
++(mSink->mInNotification);
mozAutoDocUpdate updateBatch(mSink->mDocument, UPDATE_CONTENT_MODEL,
PR_TRUE);
// Start from the base of the stack (growing downward) and do
// a notification from the node that is closest to the root of
// tree for any content that has been added.
@ -1634,6 +1638,7 @@ SinkContext::FlushTags(PRBool aNotify)
stackPos++;
}
mNotifyLevel = mStackPos - 1;
--(mSink->mInNotification);
}
return NS_OK;
@ -2153,7 +2158,7 @@ HTMLContentSink::DidBuildModel(void)
}
}
nsIScriptLoader *loader = mDocument->GetScriptLoader();
nsScriptLoader *loader = mDocument->GetScriptLoader();
if (loader) {
loader->RemoveObserver(this);
}
@ -3685,7 +3690,8 @@ HTMLContentSink::UpdateAllContexts()
}
void
HTMLContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
HTMLContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType,
PRUint32 aNestingLevel)
{
// If we're in a script and we didn't do the notification,
// something else in the script processing caused the
@ -3711,7 +3717,8 @@ HTMLContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
}
void
HTMLContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
HTMLContentSink::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType,
PRUint32 aNestingLevel)
{
// If we're in a script and we didn't do the notification,
// something else in the script processing caused the
@ -3748,71 +3755,59 @@ HTMLContentSink::PostEvaluateScript(nsIScriptElement *aElement)
nsresult
HTMLContentSink::ProcessSCRIPTEndTag(nsGenericHTMLElement *content,
PRBool aHaveNotified,
PRBool aMalformed)
{
// Flush all tags up front so that we are in as stable state as possible
// when calling DoneAddingChildren. This may not be strictly needed since
// any ScriptAvailable calls will cause us to flush anyway. But it gives a
// warm fuzzy feeling to be in a stable state before even attempting to
// run scripts.
// It would however be needed if we properly called BeginUpdate and
// EndUpdate while we were inserting stuff into the DOM.
mCurrentContext->FlushTags(PR_FALSE);
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
NS_ASSERTION(sele, "Not really closing a script tag?");
nsRefPtr<nsGenericHTMLElement> parent =
mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
if (aMalformed) {
// Make sure to serialize this script correctly, for nice round tripping.
sele->SetIsMalformed();
}
nsCOMPtr<nsIScriptLoader> loader;
if (mFrameset) {
// Fix bug 82498
// We don't want to evaluate scripts in a frameset document.
if (mDocument) {
loader = mDocument->GetScriptLoader();
if (loader) {
loader->SetEnabled(PR_FALSE);
}
}
} else if (parent->GetCurrentDoc() == mDocument) {
// We test the current doc of |parent| because if it doesn't have one we
// won't actually try to evaluate the script, so we shouldn't be blocking
// or appending to mScriptElements or anything.
// Don't include script loading and evaluation in the stopwatch
// that is measuring content creation time
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::ProcessSCRIPTEndTag()\n"));
MOZ_TIMER_STOP(mWatch);
// Assume that we're going to block the parser with a script load.
// If it's an inline script, we'll be told otherwise in the call
// to our ScriptAvailable method.
mNeedToBlockParser = PR_TRUE;
mScriptElements.AppendObject(sele);
sele->PreventExecution();
}
// Notify our document that we're loading this script.
mHTMLDocument->ScriptLoading(sele);
// Now tell the script that it's ready to go. This will execute the script
// and call our ScriptAvailable method.
content->DoneAddingChildren(aHaveNotified);
// To prevent script evaluation in a frameset document we suspended the
// script loader. Now that the script content has been handled, let's resume
// the script loader.
if (loader) {
loader->SetEnabled(PR_TRUE);
}
// Now tell the script that it's ready to go. This may execute the script
// or return NS_ERROR_HTMLPARSER_BLOCK. Or neither if the script doesn't
// need executing.
nsresult rv = content->DoneAddingChildren(PR_TRUE);
// If the act of insertion evaluated the script, we're fine.
// Else, block the parser till the script has loaded.
// Note: If the script is malformed, we'll get a ScriptAvailable call to
// take care of this test.
if (mNeedToBlockParser || (mParser && !mParser->IsParserEnabled())) {
return NS_ERROR_HTMLPARSER_BLOCK;
if (rv == NS_ERROR_HTMLPARSER_BLOCK) {
// If this append fails we'll never unblock the parser, but the UI will
// still remain responsive. There are other ways to deal with this, but
// the end result is always that the page gets botched, so there is no
// real point in making it more complicated.
mScriptElements.AppendObject(sele);
}
else {
// This may have already happened if the script executed, but in case
// it didn't then remove the element so that it doesn't get stuck forever.
mHTMLDocument->ScriptExecuted(sele);
}
return NS_OK;
// If the parser got blocked, make sure to return the appropriate rv.
// I'm not sure if this is actually needed or not.
if (mParser && !mParser->IsParserEnabled()) {
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
return rv;
}
// 3 ways to load a style sheet: inline, style src=, link tag

View File

@ -3615,10 +3615,7 @@ nsHTMLDocument::GenerateParserKey(void)
// The script loader provides us with the currently executing script element,
// which is guaranteed to be unique per script.
nsCOMPtr<nsIScriptElement> key;
mScriptLoader->GetCurrentScript(getter_AddRefs(key));
return key;
return mScriptLoader->GetCurrentScript();
}
/* attribute DOMString designMode; */

View File

@ -46,22 +46,15 @@
#include "nsIDocument.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIScriptElement.h"
#include "nsIScriptLoader.h"
#include "nsIScriptLoaderObserver.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsGUIEvent.h"
#include "nsScriptElement.h"
#include "nsIDOMText.h"
#include "nsEventDispatcher.h"
typedef nsSVGElement nsSVGScriptElementBase;
class nsSVGScriptElement : public nsSVGScriptElementBase,
public nsIDOMSVGScriptElement,
public nsIDOMSVGURIReference,
public nsIScriptLoaderObserver,
public nsIScriptElement
public nsScriptElement
{
protected:
friend nsresult NS_NewSVGScriptElement(nsIContent **aResult,
@ -75,7 +68,6 @@ public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGSCRIPTELEMENT
NS_DECL_NSIDOMSVGURIREFERENCE
NS_DECL_NSISCRIPTLOADEROBSERVER
// xxx If xpcom allowed virtual inheritance we wouldn't need to
// forward here :-(
@ -88,10 +80,6 @@ public:
virtual already_AddRefed<nsIURI> GetScriptURI();
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual void SetScriptLineNumber(PRUint32 aLineNumber);
virtual PRUint32 GetScriptLineNumber();
virtual void SetIsMalformed();
virtual PRBool IsMalformed();
// nsISVGValueObserver specializations:
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
@ -101,27 +89,10 @@ public:
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
/**
* Processes the script if it's in the document-tree and links to or
* contains a script. Once it has been evaluated there is no way to make it
* reevaluate the script, you'll have to create a new element. This also means
* that when adding a href attribute to an element that already contains an
* inline script, the script referenced by the src attribute will not be
* loaded.
*
* In order to be able to use multiple childNodes, or to use the
* fallback-mechanism of using both inline script and linked script you have
* to add all attributes and childNodes before adding the element to the
* document-tree.
*/
void MaybeProcessScript();
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
PRUint32 mLineNumber;
PRPackedBool mIsEvaluated;
@ -144,6 +115,7 @@ NS_INTERFACE_MAP_BEGIN(nsSVGScriptElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGURIReference)
NS_INTERFACE_MAP_ENTRY(nsIScriptLoaderObserver)
NS_INTERFACE_MAP_ENTRY(nsIScriptElement)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGScriptElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGScriptElementBase)
@ -156,10 +128,9 @@ nsSVGScriptElement::nsSVGScriptElement(nsINodeInfo *aNodeInfo)
mIsEvaluated(PR_FALSE),
mEvaluating(PR_FALSE)
{
AddMutationObserver(this);
}
nsresult
nsSVGScriptElement::Init()
{
@ -214,83 +185,6 @@ nsSVGScriptElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
return NS_OK;
}
//----------------------------------------------------------------------
// nsIScriptLoaderObserver methods
// variation of this code in nsHTMLScriptElement - check if changes
// need to be transfered when modifying
/* void scriptAvailable (in nsresult aResult, in nsIScriptElement aElement , in nsIURI aURI, in PRInt32 aLineNo, in PRUint32 aScriptLength, [size_is (aScriptLength)] in wstring aScript); */
NS_IMETHODIMP
nsSVGScriptElement::ScriptAvailable(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString& aScript)
{
if (!aIsInline && NS_FAILED(aResult)) {
nsCOMPtr<nsPresContext> presContext;
nsIDocument* doc = GetCurrentDoc();
if (doc) {
nsIPresShell *presShell = doc->GetShellAt(0);
if (presShell)
presContext = presShell->GetPresContext();
}
nsEventStatus status = nsEventStatus_eIgnore;
nsScriptErrorEvent event(PR_TRUE, NS_LOAD_ERROR);
event.lineNr = aLineNo;
NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
event.errorMsg = errorString.get();
nsCAutoString spec;
aURI->GetSpec(spec);
NS_ConvertUTF8toUTF16 fileName(spec);
event.fileName = fileName.get();
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this), presContext,
&event, nsnull, &status);
}
return NS_OK;
}
// variation of this code in nsHTMLScriptElement - check if changes
// need to be transfered when modifying
/* void scriptEvaluated (in nsresult aResult, in nsIScriptElement aElement); */
NS_IMETHODIMP
nsSVGScriptElement::ScriptEvaluated(nsresult aResult,
nsIScriptElement *aElement,
PRBool aIsInline,
PRBool aWasPending)
{
nsresult rv = NS_OK;
if (!aIsInline) {
nsCOMPtr<nsPresContext> presContext;
nsIDocument* doc = GetCurrentDoc();
if (doc) {
nsIPresShell *presShell = doc->GetShellAt(0);
if (presShell)
presContext = presShell->GetPresContext();
}
nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event(PR_TRUE,
NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR);
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
nsEventDispatcher::Dispatch(NS_STATIC_CAST(nsIContent*, this),
presContext, &event, nsnull, &status);
}
return rv;
}
//----------------------------------------------------------------------
// nsIScriptElement methods
@ -328,30 +222,6 @@ nsSVGScriptElement::GetScriptCharset(nsAString& charset)
charset.Truncate();
}
void
nsSVGScriptElement::SetScriptLineNumber(PRUint32 aLineNumber)
{
mLineNumber = aLineNumber;
}
PRUint32
nsSVGScriptElement::GetScriptLineNumber()
{
return mLineNumber;
}
// Note: The following two methods don't apply to us.
void
nsSVGScriptElement::SetIsMalformed()
{
}
PRBool
nsSVGScriptElement::IsMalformed()
{
return PR_FALSE;
}
//----------------------------------------------------------------------
// nsISVGValueObserver methods
@ -385,47 +255,5 @@ nsSVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
MaybeProcessScript();
}
return rv;
}
nsresult
nsSVGScriptElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify)
{
nsresult rv = nsSVGScriptElementBase::InsertChildAt(aKid, aIndex, aNotify);
if (NS_SUCCEEDED(rv) && aNotify) {
MaybeProcessScript();
}
return rv;
}
//----------------------------------------------------------------------
// implementation helpers
// variation of this code in nsHTMLScriptElement - check if changes
// need to be transfered when modifying
void
nsSVGScriptElement::MaybeProcessScript()
{
if (mIsEvaluated || mEvaluating || !IsInDoc()) {
return;
}
// We'll always call this to make sure that
// ScriptAvailable/ScriptEvaluated gets called. See bug 153600
nsresult rv = NS_OK;
nsCOMPtr<nsIScriptLoader> loader = GetOwnerDoc()->GetScriptLoader();
if (loader) {
mEvaluating = PR_TRUE;
rv = loader->ProcessScriptElement(this, this);
mEvaluating = PR_FALSE;
}
// But we'll only set mIsEvaluated if we did really load or evaluate
// something
if (HasAttr(kNameSpaceID_XLink, nsSVGAtoms::href) ||
mAttrsAndChildren.ChildCount()) {
mIsEvaluated = PR_TRUE;
}
return NS_OK;
}

View File

@ -78,7 +78,7 @@
#include "nsGenericElement.h"
#include "nsIWebNavigation.h"
#include "nsIScriptElement.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsStyleLinkElement.h"
#include "nsIImageLoadingContent.h"
#include "nsReadableUtils.h"
@ -301,7 +301,7 @@ nsXMLContentSink::DidBuildModel()
}
else {
// Kick off layout for non-XSLT transformed documents.
nsIScriptLoader *loader = mDocument->GetScriptLoader();
nsScriptLoader *loader = mDocument->GetScriptLoader();
if (loader) {
loader->RemoveObserver(this);
}
@ -392,7 +392,7 @@ nsXMLContentSink::OnTransformDone(nsresult aResult,
mDocument = aResultDocument;
}
nsIScriptLoader *loader = originalDocument->GetScriptLoader();
nsScriptLoader *loader = originalDocument->GetScriptLoader();
if (loader) {
loader->RemoveObserver(this);
}
@ -469,11 +469,10 @@ nsXMLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
|| aNodeInfo->Equals(nsSVGAtoms::script, kNameSpaceID_SVG)
#endif
) {
// Don't append the content to the tree until we're all
// done collecting its contents
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(content);
sele->SetScriptLineNumber(aLineNumber);
sele->WillCallDoneAddingChildren();
mConstrainSize = PR_FALSE;
mScriptLineNo = aLineNumber;
*aAppendContent = PR_FALSE;
}
// XHTML needs some special attention
@ -531,13 +530,10 @@ nsXMLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsresult
nsXMLContentSink::CloseElement(nsIContent* aContent, nsIContent* aParent,
PRBool* aAppendContent)
nsXMLContentSink::CloseElement(nsIContent* aContent)
{
NS_ASSERTION(aContent, "missing element to close");
*aAppendContent = PR_FALSE;
nsINodeInfo *nodeInfo = aContent->NodeInfo();
// Some HTML nodes need DoneAddingChildren() called to initialize
@ -566,8 +562,28 @@ nsXMLContentSink::CloseElement(nsIContent* aContent, nsIContent* aParent,
|| nodeInfo->Equals(nsSVGAtoms::script, kNameSpaceID_SVG)
#endif
) {
rv = ProcessEndSCRIPTTag(aContent, aParent);
*aAppendContent = PR_TRUE;
mConstrainSize = PR_TRUE;
// Now tell the script that it's ready to go. This may execute the script
// or return NS_ERROR_HTMLPARSER_BLOCK. Or neither if the script doesn't
// need executing.
rv = aContent->DoneAddingChildren(PR_TRUE);
// If the act of insertion evaluated the script, we're fine.
// Else, block the parser till the script has loaded.
if (rv == NS_ERROR_HTMLPARSER_BLOCK) {
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
mScriptElements.AppendObject(sele);
}
// If the parser got blocked, make sure to return the appropriate rv.
// I'm not sure if this is actually needed or not.
if (mParser && !mParser->IsParserEnabled()) {
// XXX The HTML sink doesn't call BlockParser here, why do we?
mParser->BlockParser();
rv = NS_ERROR_HTMLPARSER_BLOCK;
}
return rv;
}
@ -908,7 +924,7 @@ nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
// In this case, disable script execution, stylesheet
// loading, and auto XLinks since we plan to prettyprint.
mAllowAutoXLinks = PR_FALSE;
nsIScriptLoader* scriptLoader = mDocument->GetScriptLoader();
nsScriptLoader* scriptLoader = mDocument->GetScriptLoader();
if (scriptLoader) {
scriptLoader->SetEnabled(PR_FALSE);
}
@ -1019,7 +1035,6 @@ NS_IMETHODIMP
nsXMLContentSink::HandleEndElement(const PRUnichar *aName)
{
nsresult result = NS_OK;
PRBool appendContent = PR_FALSE;
// XXX Hopefully the parser will flag this before we get
// here. If we're in the prolog or epilog, there should be
@ -1041,26 +1056,13 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName)
"Wrong element being closed");
#endif
nsCOMPtr<nsIContent> parent = GetCurrentContent();
result = CloseElement(content, parent, &appendContent);
NS_ENSURE_SUCCESS(result, result);
result = CloseElement(content);
if (mDocElement == content) {
// XXXbz for roots that don't want to be appended on open, we
// probably need to deal here.... (and stop appending them on open).
mState = eXMLContentSinkState_InEpilog;
}
else if (appendContent) {
NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
parent->AppendChildTo(content, PR_FALSE);
}
if (mNeedToBlockParser || (mParser && !mParser->IsParserEnabled())) {
if (mParser) mParser->BlockParser();
result = NS_ERROR_HTMLPARSER_BLOCK;
}
#ifdef MOZ_SVG
if (content->GetNameSpaceID() == kNameSpaceID_SVG &&
@ -1440,26 +1442,3 @@ nsXMLContentSink::AddText(const PRUnichar* aText,
return NS_OK;
}
nsresult
nsXMLContentSink::ProcessEndSCRIPTTag(nsIContent* aContent,
nsIContent* aParent)
{
nsresult result = NS_OK;
mConstrainSize = PR_TRUE;
nsCOMPtr<nsIScriptElement> scriptElement(do_QueryInterface(aContent));
NS_ASSERTION(scriptElement, "null script element in XML content sink");
scriptElement->SetScriptLineNumber(mScriptLineNo);
if (!aParent || aParent->GetCurrentDoc() == mDocument) {
// Assume that we're going to block the parser with a script load.
// If it's an inline script, we'll be told otherwise in the call
// to our ScriptAvailable method.
mScriptElements.AppendObject(scriptElement);
mNeedToBlockParser = PR_TRUE;
}
return result;
}

View File

@ -101,7 +101,6 @@ protected:
virtual nsresult AddAttributes(const PRUnichar** aNode, nsIContent* aContent);
nsresult AddText(const PRUnichar* aString, PRInt32 aLength);
nsresult ProcessEndSCRIPTTag(nsIContent* aContent, nsIContent* aParent);
virtual PRBool OnOpenContainer(const PRUnichar **aAtts,
PRUint32 aAttsCount,
@ -120,8 +119,7 @@ protected:
// aParent is allowed to be null here if this is the root content
// being closed
virtual nsresult CloseElement(nsIContent* aContent, nsIContent* aParent,
PRBool* aAppendContent);
virtual nsresult CloseElement(nsIContent* aContent);
virtual nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
@ -156,7 +154,6 @@ protected:
PRInt32 mTextLength;
PRInt32 mTextSize;
PRUint32 mScriptLineNo;
PRUint8 mConstrainSize : 1;
PRUint8 mInTitle : 1;

View File

@ -558,7 +558,7 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand,
// who puts the document on display to worry about enabling.
// scripts
nsIScriptLoader *loader = GetScriptLoader();
nsScriptLoader *loader = GetScriptLoader();
if (loader) {
loader->SetEnabled(PR_FALSE); // Do not load/process scripts when loading as data
}

View File

@ -109,8 +109,7 @@ protected:
virtual nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
nsIContent** aResult, PRBool* aAppendContent);
virtual nsresult CloseElement(nsIContent* aContent, nsIContent* aParent,
PRBool* aAppendContent);
virtual nsresult CloseElement(nsIContent* aContent);
// nsContentSink overrides
virtual nsresult ProcessStyleLink(nsIContent* aElement,
@ -244,10 +243,7 @@ nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsC
aNodeInfo, aLineNumber,
aResult, aAppendContent);
// Make sure that scripts are added immediately, not on close.
*aAppendContent = PR_TRUE;
// However, when we aren't grabbing all of the content we, never open a doc
// When we aren't grabbing all of the content we, never open a doc
// element, we run into trouble on the first element, so we don't append,
// and simply push this onto the content stack.
if (!mAllContent && mContentStack.Count() == 0) {
@ -258,13 +254,9 @@ nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsC
}
nsresult
nsXMLFragmentContentSink::CloseElement(nsIContent* aContent,
nsIContent* aParent,
PRBool* aAppendContent)
nsXMLFragmentContentSink::CloseElement(nsIContent* aContent)
{
// don't do fancy stuff in nsXMLContentSink
*aAppendContent = PR_FALSE;
return NS_OK;
}

View File

@ -40,7 +40,7 @@
#include "nsIDocument.h"
#include "nsIDocShell.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentType.h"
#include "nsIScriptElement.h"
@ -86,7 +86,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsSubstring& aRootName,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mDontAddCurrent(PR_FALSE),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_TRUE),
@ -111,7 +110,6 @@ txMozillaXMLOutput::txMozillaXMLOutput(txOutputFormat* aFormat,
: mTreeDepth(0),
mBadChildLevel(0),
mTableState(NORMAL),
mDontAddCurrent(PR_FALSE),
mHaveTitleElement(PR_FALSE),
mHaveBaseElement(PR_FALSE),
mCreatingNewDocument(PR_FALSE),
@ -324,14 +322,20 @@ txMozillaXMLOutput::endElement()
NS_ENSURE_SUCCESS(rv, rv);
}
// Handle svg script elements
if (element->NodeInfo()->Equals(nsGkAtoms::script, kNameSpaceID_SVG)) {
// Add this script element to the array of loading script elements.
nsCOMPtr<nsIScriptElement> scriptElement =
do_QueryInterface(mCurrentNode);
NS_ASSERTION(scriptElement, "Need script element");
rv = mNotifier->AddScriptElement(scriptElement);
NS_ENSURE_SUCCESS(rv, rv);
// Handle script elements
if (element->Tag() == nsGkAtoms::script &&
(element->IsNodeOfType(nsINode::eHTML) ||
element->GetNameSpaceID() == kNameSpaceID_SVG)) {
rv = element->DoneAddingChildren(PR_TRUE);
// If the act of insertion evaluated the script, we're fine.
// Else, add this script element to the array of loading scripts.
if (rv == NS_ERROR_HTMLPARSER_BLOCK) {
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(element);
rv = mNotifier->AddScriptElement(sele);
NS_ENSURE_SUCCESS(rv, rv);
}
}
if (mCreatingNewDocument) {
@ -541,7 +545,6 @@ txMozillaXMLOutput::startElementInternal(nsIAtom* aPrefix,
}
mTableState = NORMAL;
mDontAddCurrent = PR_FALSE;
mOpenedElementIsHTML = PR_FALSE;
// Create the element
@ -560,7 +563,8 @@ txMozillaXMLOutput::startElementInternal(nsIAtom* aPrefix,
}
else if (aNsID == kNameSpaceID_SVG && aLocalName == txHTMLAtoms::script) {
mDontAddCurrent = PR_TRUE;
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(mOpenedElement);
sele->WillCallDoneAddingChildren();
}
if (mCreatingNewDocument) {
@ -593,17 +597,13 @@ txMozillaXMLOutput::closePrevious(PRBool aFlushText)
NS_ENSURE_SUCCESS(rv, rv);
}
if (mDontAddCurrent && !mNonAddedNode) {
mNonAddedNode = mOpenedElement;
}
else {
if (currentIsDoc) {
mRootContentCreated = PR_TRUE;
}
rv = mCurrentNode->AppendChildTo(mOpenedElement, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
if (currentIsDoc) {
mRootContentCreated = PR_TRUE;
}
rv = mCurrentNode->AppendChildTo(mOpenedElement, PR_TRUE);
NS_ENSURE_SUCCESS(rv, rv);
mCurrentNode = mOpenedElement;
mOpenedElement = nsnull;
}
@ -698,8 +698,6 @@ txMozillaXMLOutput::startHTMLElement(nsIContent* aElement, PRBool aIsHTML)
nsresult rv = NS_OK;
nsIAtom *atom = aElement->Tag();
mDontAddCurrent = (atom == txHTMLAtoms::script);
if ((atom != txHTMLAtoms::tr || !aIsHTML) &&
NS_PTR_TO_INT32(mTableStateStack.peek()) == ADDED_TBODY) {
PRUint32 last = mCurrentNodeStack.Count() - 1;
@ -756,6 +754,10 @@ txMozillaXMLOutput::startHTMLElement(nsIContent* aElement, PRBool aIsHTML)
rv = aElement->AppendChildTo(meta, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
else if (atom == nsGkAtoms::script) {
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aElement);
sele->WillCallDoneAddingChildren();
}
return NS_OK;
}
@ -780,15 +782,6 @@ txMozillaXMLOutput::endHTMLElement(nsIContent* aElement)
return NS_OK;
}
// Load scripts
if (mNotifier && atom == txHTMLAtoms::script) {
// Add this script element to the array of loading script elements.
nsCOMPtr<nsIScriptElement> scriptElement =
do_QueryInterface(mCurrentNode);
NS_ASSERTION(scriptElement, "Need script element");
rv = mNotifier->AddScriptElement(scriptElement);
NS_ENSURE_SUCCESS(rv, rv);
}
// Set document title
else if (mCreatingNewDocument &&
atom == txHTMLAtoms::title && !mHaveTitleElement) {
@ -924,7 +917,7 @@ txMozillaXMLOutput::createResultDocument(const nsSubstring& aName, PRInt32 aNsID
}
// Set up script loader of the result document.
nsIScriptLoader *loader = mDocument->GetScriptLoader();
nsScriptLoader *loader = mDocument->GetScriptLoader();
if (loader) {
if (mNotifier) {
loader->AddObserver(mNotifier);
@ -1021,8 +1014,7 @@ txTransformNotifier::ScriptAvailable(nsresult aResult,
PRBool aIsInline,
PRBool aWasPending,
nsIURI *aURI,
PRInt32 aLineNo,
const nsAString& aScript)
PRInt32 aLineNo)
{
if (NS_FAILED(aResult) &&
mScriptElements.RemoveObject(aElement)) {
@ -1121,7 +1113,7 @@ txTransformNotifier::SignalTransformEnd(nsresult aResult)
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
if (doc) {
nsIScriptLoader *scriptLoader = doc->GetScriptLoader();
nsScriptLoader *scriptLoader = doc->GetScriptLoader();
if (scriptLoader) {
scriptLoader->RemoveObserver(this);
// XXX Maybe we want to cancel script loads if NS_FAILED(rv)?

View File

@ -154,8 +154,6 @@ private:
txOutputFormat mOutputFormat;
PRPackedBool mDontAddCurrent;
PRPackedBool mHaveTitleElement;
PRPackedBool mHaveBaseElement;

View File

@ -50,7 +50,6 @@
#include "nsIDOMNodeList.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIScriptLoader.h"
#include "nsIStringBundle.h"
#include "nsIURI.h"
#include "nsNetUtil.h"

View File

@ -472,11 +472,13 @@ nsXTFElementWrapper::BeginAddingChildren()
GetXTFElement()->BeginAddingChildren();
}
void
nsresult
nsXTFElementWrapper::DoneAddingChildren(PRBool aHaveNotified)
{
if (mNotificationMask & nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN)
GetXTFElement()->DoneAddingChildren();
return NS_OK;
}
already_AddRefed<nsINodeInfo>

View File

@ -104,7 +104,7 @@ public:
virtual PRInt32 IntrinsicState() const;
virtual void BeginAddingChildren();
virtual void DoneAddingChildren(PRBool aHaveNotified);
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
virtual nsIAtom *GetClassAttributeName() const;
virtual const nsAttrValue* GetClasses() const;

View File

@ -41,7 +41,7 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsXPIDLString.h"
#include "nsIScriptLoader.h"
#include "nsScriptLoader.h"
#include "nsIParser.h"
#include "nsIDTD.h"
@ -65,6 +65,7 @@
#include "nsContentCID.h"
#include "nsIScriptableUnescapeHTML.h"
#include "nsScriptableUnescapeHTML.h"
#include "nsAutoPtr.h"
#define XHTML_DIV_TAG "div xmlns=\"http://www.w3.org/1999/xhtml\""
#define HTML_BODY_TAG "BODY"
@ -134,12 +135,12 @@ nsScriptableUnescapeHTML::ParseFragment(const nsAString &aFragment,
NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE);
// stop scripts
nsCOMPtr<nsIScriptLoader> loader;
nsRefPtr<nsScriptLoader> loader;
PRBool scripts_enabled = PR_FALSE;
if (document) {
loader = document->GetScriptLoader();
if (loader) {
loader->GetEnabled(&scripts_enabled);
scripts_enabled = loader->GetEnabled();
}
}
if (scripts_enabled) {