mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
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:
parent
bdac3071e0
commit
17ded5692c
@ -95,7 +95,6 @@ XPIDLSRCS = \
|
||||
nsISelectionDisplay.idl \
|
||||
nsISelectionListener.idl \
|
||||
nsISelectionPrivate.idl \
|
||||
nsIScriptLoader.idl \
|
||||
nsIScriptLoaderObserver.idl \
|
||||
nsISyncLoadDOMService.idl \
|
||||
nsIDragDropHandler.idl \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
@ -125,7 +125,6 @@ protected:
|
||||
nsCOMArray<nsIScriptElement> mScriptElements;
|
||||
|
||||
nsCString mRef; // ScrollTo #ref
|
||||
PRBool mNeedToBlockParser;
|
||||
};
|
||||
|
||||
// these two lists are used by the sanitizing fragment serializers
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
218
content/base/src/nsScriptElement.cpp
Executable file
218
content/base/src/nsScriptElement.cpp
Executable 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;
|
||||
}
|
90
content/base/src/nsScriptElement.h
Executable file
90
content/base/src/nsScriptElement.h
Executable 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();
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
if (currentIsDoc) {
|
||||
mRootContentCreated = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
if (currentIsDoc) {
|
||||
mRootContentCreated = PR_TRUE;
|
||||
}
|
||||
|
||||
rv = mCurrentNode->AppendChildTo(mOpenedElement, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
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)?
|
||||
|
@ -154,8 +154,6 @@ private:
|
||||
|
||||
txOutputFormat mOutputFormat;
|
||||
|
||||
PRPackedBool mDontAddCurrent;
|
||||
|
||||
PRPackedBool mHaveTitleElement;
|
||||
PRPackedBool mHaveBaseElement;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user