зеркало из https://github.com/mozilla/pjs.git
Land DOM_AGNOSTIC3_BRANCH, bug 255942. r=a few people, sr=brendan.
This commit is contained in:
Родитель
c5b0a97e63
Коммит
d5ad1dc2b9
|
@ -1543,6 +1543,14 @@ for extension in $MOZ_EXTENSIONS; do
|
|||
extensions/python/xpcom/test/Makefile
|
||||
extensions/python/xpcom/test/test_component/Makefile
|
||||
" ;;
|
||||
python/dom ) MAKEFILES_extensions="$MAKEFILES_extensions
|
||||
extensions/python/dom/Makefile
|
||||
extensions/python/dom/test/Makefile
|
||||
extensions/python/dom/test/pyxultest/Makefile
|
||||
extensions/python/dom/src/Makefile
|
||||
extensions/python/dom/nsdom/Makefile
|
||||
extensions/python/dom/nsdom/test/Makefile
|
||||
" ;;
|
||||
sql ) MAKEFILES_extensions="$MAKEFILES_extensions
|
||||
$MAKEFILES_sql"
|
||||
;;
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIURIFixup.h"
|
||||
|
|
19
configure.in
19
configure.in
|
@ -4029,7 +4029,7 @@ MOZ_PREF_EXTENSIONS=1
|
|||
MOZ_PROFILELOCKING=1
|
||||
MOZ_PROFILESHARING=1
|
||||
MOZ_PSM=1
|
||||
MOZ_PYTHON_EXTENSIONS="xpcom"
|
||||
MOZ_PYTHON_EXTENSIONS="xpcom dom"
|
||||
MOZ_PYTHON=
|
||||
MOZ_PYTHON_DEBUG_SUFFIX=
|
||||
MOZ_PYTHON_DLL_SUFFIX=
|
||||
|
@ -7088,7 +7088,7 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c python` -ne 0; then
|
|||
fi
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
dnl Convert to cygwin style "mixed" (ie, "c:/path/file.exe")
|
||||
PYTHON=`cygpath -t mixed $PYTHON`
|
||||
PYTHON=`$CYGPATH_W $PYTHON | $CYGPATH_S`
|
||||
fi
|
||||
if test ! -x "$PYTHON"; then
|
||||
AC_MSG_ERROR([Could not find Python - please adjust your PATH, or set PYTHON.])
|
||||
|
@ -7103,7 +7103,7 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c python` -ne 0; then
|
|||
MOZ_PYTHON_PREFIX=`$PYTHON -c "import sys; print sys.prefix"`
|
||||
dnl Setup the include and library directories.
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
MOZ_PYTHON_PREFIX=`cygpath -t mixed $MOZ_PYTHON_PREFIX`
|
||||
MOZ_PYTHON_PREFIX=`$CYGPATH_W $MOZ_PYTHON_PREFIX | $CYGPATH_S`
|
||||
dnl Source trees have "include" and "PC" for .h, and "PCbuild" for .lib
|
||||
dnl Binary trees have "include" for .h, and "libs" for .lib
|
||||
dnl We add 'em both - along with quotes, to handle spaces.
|
||||
|
@ -7153,7 +7153,18 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c python` -ne 0; then
|
|||
fi
|
||||
AC_MSG_RESULT(Building Python extensions using python-$MOZ_PYTHON_VER_DOTTED from $MOZ_PYTHON_PREFIX)
|
||||
fi
|
||||
dnl Later we may allow MOZ_PYTHON_EXTENSIONS to be specified, but not necessary now.
|
||||
|
||||
dnl If the user asks for the 'python' extension, then we add
|
||||
dnl MOZ_PYTHON_EXTENSIONS to MOZ_EXTENSIONS - but with the leading 'python/'
|
||||
dnl Note the careful regex - it must match 'python' followed by anything
|
||||
dnl other than a '/', including the end-of-string.
|
||||
if test `echo "$MOZ_EXTENSIONS" | grep -c 'python\([[^/]]\|$\)'` -ne 0; then
|
||||
for pyext in $MOZ_PYTHON_EXTENSIONS; do
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS python/$pyext`
|
||||
done
|
||||
fi
|
||||
dnl Later we may allow MOZ_PYTHON_EXTENSIONS to be specified on the
|
||||
dnl command-line, but not yet
|
||||
AC_SUBST(MOZ_PYTHON_EXTENSIONS)
|
||||
AC_SUBST(MOZ_PYTHON)
|
||||
AC_SUBST(MOZ_PYTHON_PREFIX)
|
||||
|
|
|
@ -573,11 +573,13 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate event argument name for the specified
|
||||
* namespace. Added because we need to switch between SVG's "evt"
|
||||
* and the rest of the world's "event".
|
||||
* Returns the appropriate event argument names for the specified
|
||||
* namespace and event name. Added because we need to switch between
|
||||
* SVG's "evt" and the rest of the world's "event", and because onerror
|
||||
* takes 3 args.
|
||||
*/
|
||||
static const char *GetEventArgName(PRInt32 aNameSpaceID);
|
||||
static void GetEventArgNames(PRInt32 aNameSpaceID, nsIAtom *aEventName,
|
||||
PRUint32 *aArgCount, const char*** aArgNames);
|
||||
|
||||
/**
|
||||
* Return the nsIXPConnect service.
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nsCaseTreatment.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIProgrammingLanguage.h" // for ::JAVASCRIPT
|
||||
|
||||
// Forward declarations
|
||||
class nsIAtom;
|
||||
|
@ -60,8 +61,8 @@ class nsAttrName;
|
|||
|
||||
// IID for the nsIContent interface
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0x67b73e9b, 0x6ec8, 0x4f20, \
|
||||
{ 0x89, 0xb2, 0xb1, 0x46, 0x9e, 0x0a, 0x51, 0x68 } }
|
||||
{ 0x469b2ce5, 0x3e00, 0x45e0, \
|
||||
{ 0x9c, 0x6e, 0x4e, 0x80, 0xfb, 0x27, 0x59, 0x7d } }
|
||||
|
||||
// hack to make egcs / gcc 2.95.2 happy
|
||||
class nsIContent_base : public nsINode {
|
||||
|
@ -614,6 +615,19 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* The default script type (language) ID for this content.
|
||||
All content must support fetching the default script language.
|
||||
*/
|
||||
virtual PRUint32 GetScriptTypeID() const
|
||||
{ return nsIProgrammingLanguage::JAVASCRIPT; }
|
||||
|
||||
/* Not all content supports setting a new default language */
|
||||
virtual nsresult SetScriptTypeID(PRUint32 aLang)
|
||||
{
|
||||
NS_NOTREACHED("SetScriptTypeID not implemented");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this node, using aNodeInfoManager to get the nodeinfo for the
|
||||
* clone. When cloning an element, all attributes of the element will be
|
||||
|
|
|
@ -79,8 +79,11 @@ class nsVoidArray;
|
|||
// NOTE: Should only be used on nsIContent nodes
|
||||
#define NODE_MAY_HAVE_FRAME 0x00000020U
|
||||
|
||||
// Four bits for the script-type ID
|
||||
#define NODE_SCRIPT_TYPE_OFFSET 6
|
||||
|
||||
// Remaining bits are node type specific.
|
||||
#define NODE_TYPE_SPECIFIC_BITS_OFFSET 6
|
||||
#define NODE_TYPE_SPECIFIC_BITS_OFFSET 0x0a
|
||||
|
||||
// IID for the nsINode interface
|
||||
#define NS_INODE_IID \
|
||||
|
|
|
@ -2198,17 +2198,34 @@ nsContentUtils::UnregisterPrefCallback(const char *aPref,
|
|||
}
|
||||
|
||||
|
||||
static const char gEventName[] = "event";
|
||||
static const char gSVGEventName[] = "evt";
|
||||
static const char *gEventNames[] = {"event"};
|
||||
static const char *gSVGEventNames[] = {"evt"};
|
||||
// for b/w compat, the first name to onerror is still 'event', even though it
|
||||
// is actually the error message. (pre this code, the other 2 were not avail.)
|
||||
// XXXmarkh - a quick lxr shows no affected code - should we correct this?
|
||||
static const char *gOnErrorNames[] = {"event", "source", "lineno"};
|
||||
|
||||
// static
|
||||
const char *
|
||||
nsContentUtils::GetEventArgName(PRInt32 aNameSpaceID)
|
||||
void
|
||||
nsContentUtils::GetEventArgNames(PRInt32 aNameSpaceID,
|
||||
nsIAtom *aEventName,
|
||||
PRUint32 *aArgCount,
|
||||
const char*** aArgArray)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_SVG)
|
||||
return gSVGEventName;
|
||||
#define SET_EVENT_ARG_NAMES(names) \
|
||||
*aArgCount = sizeof(names)/sizeof(names[0]); \
|
||||
*aArgArray = names;
|
||||
|
||||
return gEventName;
|
||||
// nsJSEventListener is what does the arg magic for onerror, and it does
|
||||
// not seem to take the namespace into account. So we let onerror in all
|
||||
// namespaces get the 3 arg names.
|
||||
if (aEventName == nsLayoutAtoms::onerror) {
|
||||
SET_EVENT_ARG_NAMES(gOnErrorNames);
|
||||
} else if (aNameSpaceID == kNameSpaceID_SVG) {
|
||||
SET_EVENT_ARG_NAMES(gSVGEventNames);
|
||||
} else {
|
||||
SET_EVENT_ARG_NAMES(gEventNames);
|
||||
}
|
||||
}
|
||||
|
||||
nsCxPusher::nsCxPusher(nsISupports *aCurrentTarget)
|
||||
|
|
|
@ -215,11 +215,8 @@ nsresult nsCopySupport::HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, PRInt16
|
|||
|
||||
// Add the URL DataFlavor to the transferable. Don't use kURLMime, as it will
|
||||
// cause an unnecessary UniformResourceLocator to be added which confuses
|
||||
// some apps eg. Outlook 2000 - (See Bug 315370). Don't use
|
||||
// kURLDataMime, as it will cause a bogus 'url ' flavor to
|
||||
// show up on the Mac clipboard, confusing other apps, like
|
||||
// Terminal (see bug 336012).
|
||||
rv = AppendString(trans, shortcut, kURLPrivateMime);
|
||||
// some apps eg. Outlook 2000 - (See Bug 315370)
|
||||
rv = AppendString(trans, shortcut, kURLDataMime );
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
static const char* kLoadAsData = "loadAsData";
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "nsIBaseWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
#include "nsGUIEvent.h"
|
||||
|
@ -1373,7 +1374,23 @@ nsDocument::SetHeaderData(nsIAtom* aHeaderField, const nsAString& aData)
|
|||
if (aHeaderField == nsHTMLAtoms::headerContentLanguage) {
|
||||
CopyUTF16toUTF8(aData, mContentLanguage);
|
||||
}
|
||||
|
||||
|
||||
// Set the default script-type on the root element.
|
||||
if (aHeaderField == nsHTMLAtoms::headerContentScriptType) {
|
||||
nsIContent *root = GetRootContent();
|
||||
if (root) {
|
||||
// Get the script-type ID for this value.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntime(aData, getter_AddRefs(runtime));
|
||||
if (NS_FAILED(rv) || runtime == nsnull) {
|
||||
NS_WARNING("The script-type is unknown");
|
||||
} else {
|
||||
root->SetScriptTypeID(runtime->GetScriptTypeID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aHeaderField == nsHTMLAtoms::headerDefaultStyle) {
|
||||
// switch alternate style sheets based on default
|
||||
// XXXldb What if we don't have all the sheets yet? Should this use
|
||||
|
@ -5097,3 +5114,17 @@ nsDocument::UpdateLinkMap()
|
|||
}
|
||||
mVisitednessChangedURIs.Clear();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetScriptTypeID(PRUint32 *aScriptType)
|
||||
{
|
||||
NS_ERROR("No default script type here - ask some element");
|
||||
return nsIProgrammingLanguage::UNKNOWN;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::SetScriptTypeID(PRUint32 aScriptType)
|
||||
{
|
||||
NS_ERROR("Can't change default script type for a document");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -855,6 +855,20 @@ nsDOMEventRTTearoff::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
|
|||
return manager->GetSystemEventGroupLM(aGroup);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMEventRTTearoff::GetScriptTypeID(PRUint32 *aLang)
|
||||
{
|
||||
*aLang = mContent->GetScriptTypeID();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMEventRTTearoff::SetScriptTypeID(PRUint32 aLang)
|
||||
{
|
||||
return mContent->SetScriptTypeID(aLang);
|
||||
}
|
||||
|
||||
|
||||
// nsIDOMEventTarget
|
||||
NS_IMETHODIMP
|
||||
nsDOMEventRTTearoff::AddEventListener(const nsAString& aType,
|
||||
|
@ -985,6 +999,9 @@ nsGenericElement::nsDOMSlots::IsEmpty()
|
|||
nsGenericElement::nsGenericElement(nsINodeInfo *aNodeInfo)
|
||||
: nsIXMLContent(aNodeInfo)
|
||||
{
|
||||
// Set the default scriptID to JS - but skip SetScriptTypeID as it
|
||||
// does extra work we know isn't necessary here...
|
||||
SetFlags(nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET);
|
||||
}
|
||||
|
||||
nsGenericElement::~nsGenericElement()
|
||||
|
@ -2301,6 +2318,29 @@ nsGenericElement::MayHaveFrame() const
|
|||
return HasFlag(NODE_MAY_HAVE_FRAME);
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsGenericElement::GetScriptTypeID() const
|
||||
{
|
||||
PtrBits flags = GetFlags();
|
||||
|
||||
/* 4 bits reserved for script-type ID. */
|
||||
return (flags >> NODE_SCRIPT_TYPE_OFFSET) & 0x000F;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericElement::SetScriptTypeID(PRUint32 aLang)
|
||||
{
|
||||
if ((aLang & 0x000F) != aLang) {
|
||||
NS_ERROR("script ID too large!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
/* SetFlags will just mask in the specific flags set, leaving existing
|
||||
ones alone. So we must clear all the bits first */
|
||||
UnsetFlags(0x000FU << NODE_SCRIPT_TYPE_OFFSET);
|
||||
SetFlags(aLang << NODE_SCRIPT_TYPE_OFFSET);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericElement::InsertChildAt(nsIContent* aKid,
|
||||
PRUint32 aIndex,
|
||||
|
@ -3128,7 +3168,8 @@ nsGenericElement::TriggerLink(nsPresContext* aPresContext,
|
|||
|
||||
nsresult
|
||||
nsGenericElement::AddScriptEventListener(nsIAtom* aEventName,
|
||||
const nsAString& aValue)
|
||||
const nsAString& aValue,
|
||||
PRBool aDefer)
|
||||
{
|
||||
NS_PRECONDITION(aEventName, "Must have event name!");
|
||||
nsCOMPtr<nsISupports> target;
|
||||
|
@ -3143,8 +3184,11 @@ nsGenericElement::AddScriptEventListener(nsIAtom* aEventName,
|
|||
if (manager) {
|
||||
nsIDocument *ownerDoc = GetOwnerDoc();
|
||||
|
||||
defer = defer && aDefer; // only defer if everyone agrees...
|
||||
|
||||
PRUint32 lang = GetScriptTypeID();
|
||||
rv =
|
||||
manager->AddScriptEventListener(target, aEventName, aValue, defer,
|
||||
manager->AddScriptEventListener(target, aEventName, aValue, lang, defer,
|
||||
!nsContentUtils::IsChromeDoc(ownerDoc));
|
||||
}
|
||||
|
||||
|
|
|
@ -373,6 +373,9 @@ public:
|
|||
virtual void SetMayHaveFrame(PRBool aMayHaveFrame);
|
||||
virtual PRBool MayHaveFrame() const;
|
||||
|
||||
virtual PRUint32 GetScriptTypeID() const;
|
||||
virtual nsresult SetScriptTypeID(PRUint32 aLang);
|
||||
|
||||
/**
|
||||
* This calls Clone to do the actual cloning so that we end up with the
|
||||
* right class for the clone.
|
||||
|
@ -487,9 +490,11 @@ public:
|
|||
* (like onclick) and with the value as JS
|
||||
* @param aEventName the event listener name
|
||||
* @param aValue the JS to attach
|
||||
* @param aDefer indicates if deferred execution is allowed
|
||||
*/
|
||||
nsresult AddScriptEventListener(nsIAtom* aEventName,
|
||||
const nsAString& aValue);
|
||||
const nsAString& aValue,
|
||||
PRBool aDefer = PR_TRUE);
|
||||
|
||||
/**
|
||||
* Trigger a link with uri aLinkURI. If aClick is false, this triggers a
|
||||
|
|
|
@ -172,7 +172,7 @@ nsParserUtils::GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
|
|||
// Returns PR_TRUE if the language name is a version of JavaScript and
|
||||
// PR_FALSE otherwise
|
||||
PRBool
|
||||
nsParserUtils::IsJavaScriptLanguage(const nsString& aName, const char* *aVersion)
|
||||
nsParserUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
|
||||
{
|
||||
JSVersion version = JSVERSION_UNKNOWN;
|
||||
|
||||
|
@ -204,7 +204,7 @@ nsParserUtils::IsJavaScriptLanguage(const nsString& aName, const char* *aVersion
|
|||
}
|
||||
if (version == JSVERSION_UNKNOWN)
|
||||
return PR_FALSE;
|
||||
*aVersion = JS_VersionToString(version);
|
||||
*aFlags = version;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
nsAString& aValue);
|
||||
|
||||
static PRBool
|
||||
IsJavaScriptLanguage(const nsString& aName, const char* *aVersion);
|
||||
IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
|
||||
|
||||
static void
|
||||
SplitMimeType(const nsAString& aValue, nsString& aType,
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
|
@ -60,7 +61,7 @@
|
|||
#include "nsIScriptElement.h"
|
||||
#include "nsIDOMHTMLScriptElement.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -117,8 +118,7 @@ class nsScriptLoadRequest : public nsISupports {
|
|||
public:
|
||||
nsScriptLoadRequest(nsIScriptElement* aElement,
|
||||
nsIScriptLoaderObserver* aObserver,
|
||||
const char* aVersionString,
|
||||
PRBool aHasE4XOption);
|
||||
PRUint32 aVersion);
|
||||
virtual ~nsScriptLoadRequest();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -132,21 +132,19 @@ public:
|
|||
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?
|
||||
PRPackedBool mHasE4XOption; // Has E4X=1 script type parameter
|
||||
nsString mScriptText; // Holds script for loaded scripts
|
||||
const char* mJSVersion; // We don't own this string
|
||||
PRUint32 mJSVersion;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
PRInt32 mLineNo;
|
||||
};
|
||||
|
||||
nsScriptLoadRequest::nsScriptLoadRequest(nsIScriptElement* aElement,
|
||||
nsIScriptLoaderObserver* aObserver,
|
||||
const char* aVersionString,
|
||||
PRBool aHasE4XOption) :
|
||||
PRUint32 aVersion) :
|
||||
mElement(aElement), mObserver(aObserver),
|
||||
mLoading(PR_TRUE), mWasPending(PR_FALSE),
|
||||
mIsInline(PR_TRUE), mHasE4XOption(aHasE4XOption),
|
||||
mJSVersion(aVersionString), mLineNo(1)
|
||||
mIsInline(PR_TRUE),
|
||||
mJSVersion(aVersion), mLineNo(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -382,10 +380,16 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
|
|||
|
||||
// Script evaluation can also be disabled in the current script
|
||||
// context even though it's enabled in the document.
|
||||
// XXX - still hard-coded for JS here, even though another language
|
||||
// may be specified. Should this check be made *after* we examine
|
||||
// the attributes to locate the script-type?
|
||||
// For now though, if JS is disabled we assume every language is
|
||||
// disabled.
|
||||
nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject();
|
||||
if (globalObject)
|
||||
{
|
||||
nsIScriptContext *context = globalObject->GetContext();
|
||||
nsIScriptContext *context = globalObject->GetScriptContext(
|
||||
nsIProgrammingLanguage::JAVASCRIPT);
|
||||
|
||||
// If scripts aren't enabled in the current context, there's no
|
||||
// point in going on.
|
||||
|
@ -394,35 +398,15 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
|
|||
}
|
||||
}
|
||||
|
||||
PRBool isJavaScript = PR_TRUE;
|
||||
PRBool hasE4XOption = PR_FALSE;
|
||||
const char* jsVersionString = nsnull;
|
||||
// Default script language is whatever the root content specifies
|
||||
// (which may come from a header or http-meta tag)
|
||||
PRUint32 typeID = mDocument->GetRootContent()->GetScriptTypeID();
|
||||
PRUint32 version = 0;
|
||||
nsAutoString language, type, src;
|
||||
|
||||
// "language" is a deprecated attribute of HTML, so we check it only for
|
||||
// HTML script elements.
|
||||
nsCOMPtr<nsIDOMHTMLScriptElement> htmlScriptElement =
|
||||
do_QueryInterface(aElement);
|
||||
if (htmlScriptElement) {
|
||||
// Check the language attribute first, so type can trump language.
|
||||
htmlScriptElement->GetAttribute(NS_LITERAL_STRING("language"), language);
|
||||
if (!language.IsEmpty()) {
|
||||
isJavaScript = nsParserUtils::IsJavaScriptLanguage(language,
|
||||
&jsVersionString);
|
||||
|
||||
// IE, Opera, etc. do not respect language version, so neither should
|
||||
// we at this late date in the browser wars saga. Note that this change
|
||||
// affects HTML but not XUL or SVG (but note also that XUL has its own
|
||||
// code to check nsParserUtils::IsJavaScriptLanguage -- that's probably
|
||||
// a separate bug, one we may not be able to fix short of XUL2). See
|
||||
// bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895).
|
||||
jsVersionString = ::JS_VersionToString(JSVERSION_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Check the type attribute to determine language and version.
|
||||
// If type exists, it trumps the deprecated 'language='
|
||||
aElement->GetScriptType(type);
|
||||
if (!type.IsEmpty()) {
|
||||
nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser =
|
||||
|
@ -437,6 +421,7 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
|
|||
mimeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Javascript keeps the fast path, optimized for most-likely type
|
||||
// Table ordered from most to least likely JS MIME types.
|
||||
// See bug 62485, feel free to add <script type="..."> survey data to it,
|
||||
// or to a new bug once 62485 is closed.
|
||||
|
@ -449,38 +434,54 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
|
|||
nsnull
|
||||
};
|
||||
|
||||
isJavaScript = PR_FALSE;
|
||||
PRBool isJavaScript = PR_FALSE;
|
||||
for (PRInt32 i = 0; jsTypes[i]; i++) {
|
||||
if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) {
|
||||
isJavaScript = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isJavaScript) {
|
||||
JSVersion jsVersion = JSVERSION_DEFAULT;
|
||||
nsAutoString value;
|
||||
if (isJavaScript)
|
||||
typeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
else {
|
||||
// Use the object factory to locate a matching language.
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime));
|
||||
if (NS_FAILED(rv) || runtime == nsnull) {
|
||||
// Failed to get the explicitly specified language
|
||||
NS_WARNING("Failed to find a scripting language");
|
||||
typeID = nsIProgrammingLanguage::UNKNOWN;
|
||||
} else
|
||||
typeID = runtime->GetScriptTypeID();
|
||||
}
|
||||
if (typeID != nsIProgrammingLanguage::UNKNOWN) {
|
||||
// Get the version string, and ensure the language supports it.
|
||||
nsAutoString versionName;
|
||||
rv = mimeHdrParser->GetParameter(typeAndParams, "version",
|
||||
EmptyCString(), PR_FALSE, nsnull,
|
||||
value);
|
||||
versionName);
|
||||
if (NS_FAILED(rv)) {
|
||||
// no version attribute - version remains 0.
|
||||
if (rv != NS_ERROR_INVALID_ARG)
|
||||
return rv;
|
||||
} else {
|
||||
if (value.Length() != 3 || value[0] != '1' || value[1] != '.')
|
||||
jsVersion = JSVERSION_UNKNOWN;
|
||||
else switch (value[2]) {
|
||||
case '0': jsVersion = JSVERSION_1_0; break;
|
||||
case '1': jsVersion = JSVERSION_1_1; break;
|
||||
case '2': jsVersion = JSVERSION_1_2; break;
|
||||
case '3': jsVersion = JSVERSION_1_3; break;
|
||||
case '4': jsVersion = JSVERSION_1_4; break;
|
||||
case '5': jsVersion = JSVERSION_1_5; break;
|
||||
case '6': jsVersion = JSVERSION_1_6; break;
|
||||
default: jsVersion = JSVERSION_UNKNOWN;
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntimeByID(typeID, getter_AddRefs(runtime));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to locate the language with this ID");
|
||||
return rv;
|
||||
}
|
||||
rv = runtime->ParseVersion(versionName, &version);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("This script language version is not supported - ignored");
|
||||
typeID = nsIProgrammingLanguage::UNKNOWN;
|
||||
}
|
||||
}
|
||||
jsVersionString = ::JS_VersionToString(jsVersion);
|
||||
}
|
||||
|
||||
// Some js specifics yet to be abstracted.
|
||||
if (typeID == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
nsAutoString value;
|
||||
|
||||
rv = mimeHdrParser->GetParameter(typeAndParams, "e4x",
|
||||
EmptyCString(), PR_FALSE, nsnull,
|
||||
|
@ -490,20 +491,62 @@ nsScriptLoader::DoProcessScriptElement(nsIScriptElement *aElement,
|
|||
return rv;
|
||||
} else {
|
||||
if (value.Length() == 1 && value[0] == '1')
|
||||
hasE4XOption = PR_TRUE;
|
||||
// This means that we need to set JSOPTION_XML in the JS options.
|
||||
// We re-use our knowledge of the implementation to reuse
|
||||
// JSVERSION_HAS_XML as a safe version flag.
|
||||
// If version has JSVERSION_UNKNOWN (-1), then this is still OK.
|
||||
version |= JSVERSION_HAS_XML;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no 'type=' element
|
||||
// "language" is a deprecated attribute of HTML, so we check it only for
|
||||
// HTML script elements.
|
||||
nsCOMPtr<nsIDOMHTMLScriptElement> htmlScriptElement =
|
||||
do_QueryInterface(aElement);
|
||||
if (htmlScriptElement) {
|
||||
htmlScriptElement->GetAttribute(NS_LITERAL_STRING("language"), language);
|
||||
if (!language.IsEmpty()) {
|
||||
if (nsParserUtils::IsJavaScriptLanguage(language, &version))
|
||||
typeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
else
|
||||
typeID = nsIProgrammingLanguage::UNKNOWN;
|
||||
// IE, Opera, etc. do not respect language version, so neither should
|
||||
// we at this late date in the browser wars saga. Note that this change
|
||||
// affects HTML but not XUL or SVG (but note also that XUL has its own
|
||||
// code to check nsParserUtils::IsJavaScriptLanguage -- that's probably
|
||||
// a separate bug, one we may not be able to fix short of XUL2). See
|
||||
// bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895).
|
||||
NS_ASSERTION(JSVERSION_DEFAULT == 0,
|
||||
"We rely on all languages having 0 as a version default");
|
||||
version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this isn't JavaScript, we don't know how to evaluate.
|
||||
// XXX How and where should we deal with other scripting languages?
|
||||
// See bug 255942 (https://bugzilla.mozilla.org/show_bug.cgi?id=255942).
|
||||
if (!isJavaScript) {
|
||||
// If we don't know the language, we don't know how to evaluate
|
||||
if (typeID == nsIProgrammingLanguage::UNKNOWN) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
// If not from a chrome document (which is always trusted), we need some way
|
||||
// of checking the language is "safe". Currently the only other language
|
||||
// impl is Python, and that is *not* safe in untrusted code - so fixing
|
||||
// this isn't a priority.!
|
||||
// See also similar code in nsXULContentSink.cpp
|
||||
if (typeID != nsIProgrammingLanguage::JAVASCRIPT &&
|
||||
!nsContentUtils::IsChromeDoc(mDocument)) {
|
||||
NS_WARNING("Untrusted language called from non-chrome - ignored");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement));
|
||||
if (eltContent)
|
||||
eltContent->SetScriptTypeID(typeID);
|
||||
else
|
||||
NS_ERROR("Element is not nsIContent - can't set scripttype");
|
||||
|
||||
// Create a request object for this script
|
||||
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, aObserver, jsVersionString, hasE4XOption);
|
||||
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, aObserver, version);
|
||||
NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// First check to see if this is an external script
|
||||
|
@ -715,10 +758,20 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
|
|||
nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject();
|
||||
NS_ENSURE_TRUE(globalObject, NS_ERROR_FAILURE);
|
||||
|
||||
// Get the script-type to be used by this element.
|
||||
nsCOMPtr<nsIContent> scriptContent(do_QueryInterface(aRequest->mElement));
|
||||
NS_ASSERTION(scriptContent, "no content - what is default script-type?");
|
||||
PRUint32 stid = scriptContent ? scriptContent->GetScriptTypeID() :
|
||||
nsIProgrammingLanguage::JAVASCRIPT;
|
||||
// and make sure we are setup for this type of script.
|
||||
rv = globalObject->EnsureScriptEnvironment(stid);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Make sure context is a strong reference since we access it after
|
||||
// we've executed a script, which may cause all other references to
|
||||
// the context to go away.
|
||||
nsCOMPtr<nsIScriptContext> context = globalObject->GetContext();
|
||||
nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext(stid);
|
||||
if (!context) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -735,48 +788,38 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
|
|||
PRBool oldProcessingScriptTag = context->GetProcessingScriptTag();
|
||||
context->SetProcessingScriptTag(PR_TRUE);
|
||||
|
||||
JSContext *cx = (JSContext *)context->GetNativeContext();
|
||||
uint32 options = ::JS_GetOptions(cx);
|
||||
JSBool changed = (aRequest->mHasE4XOption ^ !!(options & JSOPTION_XML));
|
||||
if (changed) {
|
||||
::JS_SetOptions(cx,
|
||||
aRequest->mHasE4XOption
|
||||
? options | JSOPTION_XML
|
||||
: options & ~JSOPTION_XML);
|
||||
}
|
||||
|
||||
// Update our current script.
|
||||
nsCOMPtr<nsIScriptElement> oldCurrent = mCurrentScript;
|
||||
mCurrentScript = aRequest->mElement;
|
||||
|
||||
PRBool isUndefined;
|
||||
rv = context->EvaluateString(aScript, globalObject->GetGlobalJSObject(),
|
||||
mDocument->NodePrincipal(), url.get(),
|
||||
aRequest->mLineNo, aRequest->mJSVersion, nsnull,
|
||||
&isUndefined);
|
||||
rv = context->EvaluateString(aScript,
|
||||
globalObject->GetScriptGlobal(stid),
|
||||
mDocument->NodePrincipal(), url.get(),
|
||||
aRequest->mLineNo, aRequest->mJSVersion, nsnull,
|
||||
&isUndefined);
|
||||
|
||||
// Put the old script back in case it wants to do anything else.
|
||||
mCurrentScript = oldCurrent;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
::JS_ReportPendingException(cx);
|
||||
}
|
||||
if (changed) {
|
||||
::JS_SetOptions(cx, options);
|
||||
if (stid == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
JS_BeginRequest((JSContext *)context->GetNativeContext());
|
||||
}
|
||||
if (NS_FAILED(rv) && stid == nsIProgrammingLanguage::JAVASCRIPT)
|
||||
::JS_ReportPendingException((JSContext *)context->GetNativeContext());
|
||||
|
||||
context->SetProcessingScriptTag(oldProcessingScriptTag);
|
||||
|
||||
nsCOMPtr<nsIXPCNativeCallContext> ncc;
|
||||
nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(getter_AddRefs(ncc));
|
||||
if (stid == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
nsCOMPtr<nsIXPCNativeCallContext> ncc;
|
||||
nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(getter_AddRefs(ncc));
|
||||
|
||||
if (ncc) {
|
||||
ncc->SetExceptionWasThrown(PR_FALSE);
|
||||
if (ncc) {
|
||||
ncc->SetExceptionWasThrown(PR_FALSE);
|
||||
}
|
||||
JS_EndRequest((JSContext *)context->GetNativeContext());
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include "nsICachingChannel.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ class nsIScriptContext;
|
|||
class nsIDOMEventTarget;
|
||||
class nsIDOMEventGroup;
|
||||
class nsIAtom;
|
||||
struct JSObject;
|
||||
|
||||
/*
|
||||
* Event listener manager interface.
|
||||
|
@ -102,6 +101,7 @@ public:
|
|||
NS_IMETHOD AddScriptEventListener(nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aFunc,
|
||||
PRUint32 aLanguage,
|
||||
PRBool aDeferCompilation,
|
||||
PRBool aPermitUntrustedEvents) = 0;
|
||||
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
* @param the name of an event listener
|
||||
*/
|
||||
NS_IMETHOD RegisterScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName) = 0;
|
||||
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
* script object for a given event type.
|
||||
* @param an event listener */
|
||||
NS_IMETHOD CompileScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName,
|
||||
PRBool *aDidCompile) = 0;
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIJSEventListener.h"
|
||||
#include "prmem.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#ifdef MOZ_XUL
|
||||
|
@ -106,6 +107,8 @@
|
|||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsDOMScriptObjectHolder.h"
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
@ -1144,7 +1147,7 @@ nsEventListenerManager::FindJSEventListener(EventArrayType aType)
|
|||
|
||||
nsresult
|
||||
nsEventListenerManager::SetJSEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName,
|
||||
PRBool aIsString,
|
||||
|
@ -1198,32 +1201,50 @@ NS_IMETHODIMP
|
|||
nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aBody,
|
||||
PRUint32 aLanguage,
|
||||
PRBool aDeferCompilation,
|
||||
PRBool aPermitUntrustedEvents)
|
||||
{
|
||||
NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN,
|
||||
"Must know the language for the script event listener");
|
||||
nsIScriptContext *context = nsnull;
|
||||
JSContext* cx = nsnull;
|
||||
|
||||
// |aPermitUntrustedEvents| is set to False for chrome - events
|
||||
// *generated* from an unknown source are not allowed.
|
||||
// However, for script languages with no 'sandbox', we want to reject
|
||||
// such scripts based on the source of their code, not just the source
|
||||
// of the event.
|
||||
if (aPermitUntrustedEvents &&
|
||||
aLanguage != nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
NS_WARNING("Discarding non-JS event listener from untrusted source");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aObject));
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
|
||||
nsISupports *objiSupp = aObject;
|
||||
|
||||
JSObject *scope = nsnull;
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
|
||||
if (node) {
|
||||
// Try to get context from doc
|
||||
doc = node->GetOwnerDoc();
|
||||
nsIScriptGlobalObject *global;
|
||||
if (doc)
|
||||
global = doc->GetScriptGlobalObject();
|
||||
if (global) {
|
||||
// This might be the first reference to this language in the global
|
||||
// We must init the language before we attempt to fetch its context.
|
||||
if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
|
||||
NS_WARNING("Failed to setup script environment for this language");
|
||||
// but fall through and let the inevitable failure below handle it.
|
||||
}
|
||||
|
||||
if (doc && (global = doc->GetScriptGlobalObject())) {
|
||||
context = global->GetContext();
|
||||
scope = global->GetGlobalJSObject();
|
||||
context = global->GetScriptContext(aLanguage);
|
||||
NS_ASSERTION(context, "Failed to get language context from global");
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aObject));
|
||||
nsCOMPtr<nsIScriptGlobalObject> global;
|
||||
if (win) {
|
||||
NS_ASSERTION(win->IsInnerWindow(),
|
||||
"Event listener added to outer window!");
|
||||
|
@ -1236,12 +1257,25 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
|||
global = do_QueryInterface(aObject);
|
||||
}
|
||||
if (global) {
|
||||
context = global->GetContext();
|
||||
scope = global->GetGlobalJSObject();
|
||||
// As above - ensure the global is setup for the language.
|
||||
if (NS_FAILED(global->EnsureScriptEnvironment(aLanguage))) {
|
||||
NS_WARNING("Failed to setup script environment for this language");
|
||||
// but fall through and let the inevitable failure below handle it.
|
||||
}
|
||||
context = global->GetScriptContext(aLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
NS_ASSERTION(aLanguage == nsIProgrammingLanguage::JAVASCRIPT,
|
||||
"Need a multi-language stack?!?!?");
|
||||
// I've only ever seen the above fire when something else has gone wrong -
|
||||
// in normal processing, languages other than JS should not be able to get
|
||||
// here, as these languages are only called via nsIScriptContext
|
||||
|
||||
// OTOH, maybe using JS will do here - all we need is the global - try and
|
||||
// keep going...
|
||||
JSContext* cx = nsnull;
|
||||
// Get JSContext from stack, or use the safe context (and hidden
|
||||
// window global) if no JS is running.
|
||||
nsCOMPtr<nsIThreadJSContextStack> stack =
|
||||
|
@ -1257,48 +1291,32 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
|||
context = nsJSUtils::GetDynamicScriptContext(cx);
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
||||
|
||||
scope = ::JS_GetGlobalObject(cx);
|
||||
} else if (!scope) {
|
||||
global = context->GetGlobalObject();
|
||||
// but if the language is *not* js , we now have the wrong context.
|
||||
context = global->GetScriptContext(aLanguage);
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
||||
}
|
||||
if (!global) {
|
||||
NS_ERROR("Context reachable, but no scope reachable in "
|
||||
"AddScriptEventListener()!");
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
void *scope = global->GetScriptGlobal(aLanguage);
|
||||
nsresult rv;
|
||||
|
||||
if (!aDeferCompilation) {
|
||||
JSContext *cx = (JSContext *)context->GetNativeContext();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = nsContentUtils::XPConnect()->WrapNative(cx, scope, aObject,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Since JSEventListeners only have a raw nsISupports pointer, it's
|
||||
// important that it point to the same object that the WrappedNative wraps.
|
||||
// (In the case of a tearoff, the tearoff will not persist).
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper = do_QueryInterface(holder);
|
||||
NS_ASSERTION(wrapper, "wrapper must impl nsIXPConnectWrappedNative");
|
||||
|
||||
objiSupp = wrapper->Native();
|
||||
|
||||
JSObject *scriptObject = nsnull;
|
||||
|
||||
rv = holder->GetJSObject(&scriptObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
|
||||
do_QueryInterface(aObject);
|
||||
|
||||
void *handler = nsnull;
|
||||
nsScriptObjectHolder handler(context);
|
||||
PRBool done = PR_FALSE;
|
||||
|
||||
if (handlerOwner) {
|
||||
rv = handlerOwner->GetCompiledEventHandler(aName, &handler);
|
||||
rv = handlerOwner->GetCompiledEventHandler(aName, handler);
|
||||
if (NS_SUCCEEDED(rv) && handler) {
|
||||
rv = context->BindCompiledEventHandler(scriptObject, aName, handler);
|
||||
rv = context->BindCompiledEventHandler(aObject, scope, aName, handler);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
done = PR_TRUE;
|
||||
|
@ -1319,8 +1337,8 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
|||
if (handlerOwner) {
|
||||
// Always let the handler owner compile the event handler, as
|
||||
// it may want to use a special context or scope object.
|
||||
rv = handlerOwner->CompileEventHandler(context, scriptObject, aName,
|
||||
aBody, url.get(), lineNo, &handler);
|
||||
rv = handlerOwner->CompileEventHandler(context, aObject, aName,
|
||||
aBody, url.get(), lineNo, handler);
|
||||
}
|
||||
else {
|
||||
PRInt32 nameSpace = kNameSpaceID_Unknown;
|
||||
|
@ -1335,13 +1353,19 @@ nsEventListenerManager::AddScriptEventListener(nsISupports *aObject,
|
|||
if (root)
|
||||
nameSpace = root->GetNameSpaceID();
|
||||
}
|
||||
const char *eventName = nsContentUtils::GetEventArgName(nameSpace);
|
||||
PRUint32 argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(nameSpace, aName, &argCount,
|
||||
&argNames);
|
||||
|
||||
rv = context->CompileEventHandler(scriptObject, aName, eventName,
|
||||
rv = context->CompileEventHandler(aName, argCount, argNames,
|
||||
aBody,
|
||||
url.get(), lineNo,
|
||||
PR_FALSE,
|
||||
nsnull);
|
||||
handler);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// And bind it.
|
||||
rv = context->BindCompiledEventHandler(aObject, scope,
|
||||
aName, handler);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
@ -1383,7 +1407,7 @@ nsEventListenerManager::sAddListenerID = JSVAL_VOID;
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScope,
|
||||
nsISupports *aObject,
|
||||
nsIAtom *aName)
|
||||
{
|
||||
|
@ -1402,25 +1426,6 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext,
|
|||
if (NS_FAILED(rv = stack->Peek(&cx)))
|
||||
return rv;
|
||||
|
||||
JSContext *current_cx = (JSContext *)aContext->GetNativeContext();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = nsContentUtils::XPConnect()->
|
||||
WrapNative(current_cx, aScopeObject, aObject, NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Since JSEventListeners only have a raw nsISupports pointer, it's
|
||||
// important that it point to the same object that the WrappedNative wraps.
|
||||
// (In the case of a tearoff, the tearoff will not persist).
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper = do_QueryInterface(holder);
|
||||
NS_ASSERTION(wrapper, "wrapper must impl nsIXPConnectWrappedNative");
|
||||
|
||||
JSObject *jsobj = nsnull;
|
||||
|
||||
rv = holder->GetJSObject(&jsobj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (cx) {
|
||||
if (sAddListenerID == JSVAL_VOID) {
|
||||
JSAutoRequest ar(cx);
|
||||
|
@ -1428,26 +1433,41 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext,
|
|||
STRING_TO_JSVAL(::JS_InternString(cx, "addEventListener"));
|
||||
}
|
||||
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckPropertyAccess(cx, jsobj,
|
||||
"EventTarget",
|
||||
sAddListenerID,
|
||||
nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX set pending exception on the native call context?
|
||||
return rv;
|
||||
if (aContext->GetScriptTypeID() == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = nsContentUtils::XPConnect()->
|
||||
WrapNative(cx, (JSObject *)aScope, aObject, NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JSObject *jsobj = nsnull;
|
||||
|
||||
rv = holder->GetJSObject(&jsobj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckPropertyAccess(cx, jsobj,
|
||||
"EventTarget",
|
||||
sAddListenerID,
|
||||
nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX set pending exception on the native call context?
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Skipping CheckPropertyAccess for non JS language");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Untrusted events are always permitted for non-chrome script
|
||||
// handlers.
|
||||
return SetJSEventListener(aContext, aScopeObject, wrapper->Native(), aName,
|
||||
return SetJSEventListener(aContext, aScope, aObject, aName,
|
||||
PR_FALSE, !nsContentUtils::IsCallerChrome());
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScope,
|
||||
nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
PRBool *aDidCompile)
|
||||
|
@ -1470,7 +1490,7 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext,
|
|||
}
|
||||
|
||||
if (ls->mHandlerIsString & subType) {
|
||||
rv = CompileEventHandlerInternal(aContext, aScopeObject, aObject, aName,
|
||||
rv = CompileEventHandlerInternal(aContext, aScope, aObject, aName,
|
||||
ls, /*XXX fixme*/nsnull, subType);
|
||||
}
|
||||
|
||||
|
@ -1486,7 +1506,7 @@ nsEventListenerManager::CompileScriptEventListener(nsIScriptContext *aContext,
|
|||
|
||||
nsresult
|
||||
nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScope,
|
||||
nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
nsListenerStruct *aListenerStruct,
|
||||
|
@ -1495,27 +1515,16 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
|||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
result = nsContentUtils::XPConnect()->WrapNative(cx, aScopeObject, aObject,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
JSObject *jsobj = nsnull;
|
||||
|
||||
result = holder->GetJSObject(&jsobj);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
|
||||
do_QueryInterface(aObject);
|
||||
void* handler = nsnull;
|
||||
nsScriptObjectHolder handler(aContext);
|
||||
|
||||
if (handlerOwner) {
|
||||
result = handlerOwner->GetCompiledEventHandler(aName, &handler);
|
||||
result = handlerOwner->GetCompiledEventHandler(aName,
|
||||
handler);
|
||||
if (NS_SUCCEEDED(result) && handler) {
|
||||
result = aContext->BindCompiledEventHandler(jsobj, aName, handler);
|
||||
// XXXmarkh - why do we bind here, but not after compilation below?
|
||||
result = aContext->BindCompiledEventHandler(aObject, aScope, aName, handler);
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
}
|
||||
}
|
||||
|
@ -1568,20 +1577,27 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
|||
// Always let the handler owner compile the event
|
||||
// handler, as it may want to use a special
|
||||
// context or scope object.
|
||||
result = handlerOwner->CompileEventHandler(aContext, jsobj, aName,
|
||||
result = handlerOwner->CompileEventHandler(aContext, aObject, aName,
|
||||
handlerBody,
|
||||
url.get(), lineNo,
|
||||
&handler);
|
||||
handler);
|
||||
}
|
||||
else {
|
||||
const char *eventName =
|
||||
nsContentUtils::GetEventArgName(content->GetNameSpaceID());
|
||||
PRUint32 argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(content->GetNameSpaceID(), aName,
|
||||
&argCount, &argNames);
|
||||
|
||||
result = aContext->CompileEventHandler(jsobj, aName, eventName,
|
||||
result = aContext->CompileEventHandler(aName,
|
||||
argCount, argNames,
|
||||
handlerBody,
|
||||
url.get(), lineNo,
|
||||
(handlerOwner != nsnull),
|
||||
&handler);
|
||||
handler);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
// And bind it.
|
||||
result = aContext->BindCompiledEventHandler(aObject, aScope,
|
||||
aName, handler);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
|
|
|
@ -141,15 +141,16 @@ public:
|
|||
NS_IMETHOD AddScriptEventListener(nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aFunc,
|
||||
PRUint32 aLanguage,
|
||||
PRBool aDeferCompilation,
|
||||
PRBool aPermitUntrustedEvents);
|
||||
NS_IMETHOD RegisterScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName);
|
||||
NS_IMETHOD RemoveScriptEventListener(nsIAtom *aName);
|
||||
NS_IMETHOD CompileScriptEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName, PRBool *aDidCompile);
|
||||
|
||||
|
@ -210,7 +211,7 @@ protected:
|
|||
PRUint32 aSubType,
|
||||
PRUint32 aPhaseFlags);
|
||||
nsresult CompileEventHandlerInternal(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
void *aScopeObject,
|
||||
nsISupports *aObject,
|
||||
nsIAtom *aName,
|
||||
nsListenerStruct *aListenerStruct,
|
||||
|
@ -218,7 +219,8 @@ protected:
|
|||
PRUint32 aSubType);
|
||||
nsListenerStruct* FindJSEventListener(EventArrayType aType);
|
||||
nsresult SetJSEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject, nsISupports *aObject,
|
||||
void *aScopeGlobal,
|
||||
nsISupports *aObject,
|
||||
nsIAtom* aName, PRBool aIsString,
|
||||
PRBool aPermitUntrustedEvents);
|
||||
nsresult AddEventListener(nsIDOMEventListener *aListener,
|
||||
|
|
|
@ -60,7 +60,8 @@
|
|||
#include "nsIDOMDocument.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsContentErrors.h"
|
||||
|
||||
#include "nsIArray.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
//
|
||||
// Helper class used to support <SCRIPT FOR=object EVENT=handler ...>
|
||||
|
@ -229,9 +230,10 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
|
|||
// wrap the target object...
|
||||
JSContext *cx = (JSContext *)scriptContext->GetNativeContext();
|
||||
JSObject *scriptObject = nsnull;
|
||||
JSObject *scope = sgo->GetGlobalJSObject();
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsContentUtils::XPConnect()->WrapNative(cx, sgo->GetGlobalJSObject(),
|
||||
nsContentUtils::XPConnect()->WrapNative(cx, scope,
|
||||
aTargetObject,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
|
@ -299,10 +301,17 @@ nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// Create an nsIArray for the args (the JS context will efficiently
|
||||
// re-fetch the jsvals from this object)
|
||||
nsCOMPtr<nsIArray> argarray;
|
||||
rv = NS_CreateJSArgv(cx, aArgCount, (jsval *)aArgs, getter_AddRefs(argarray));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Invoke the event handler script...
|
||||
jsval dummy;
|
||||
return scriptContext->CallEventHandler(scriptObject, (JSObject *)funcObject,
|
||||
aArgCount, (jsval *)aArgs, &dummy);
|
||||
nsCOMPtr<nsIVariant> ret;
|
||||
return scriptContext->CallEventHandler(aTargetObject, scope, funcObject,
|
||||
argarray, getter_AddRefs(ret));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -869,6 +869,9 @@ nsXBLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
prototype->mNodeInfo = aNodeInfo;
|
||||
// XXX - we need to do exactly what the XUL content-sink does (eg,
|
||||
// look for 'type', 'version' etc attributes)
|
||||
prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
|
||||
AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -52,7 +53,8 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
// An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile
|
||||
|
@ -67,14 +69,16 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIScriptGlobalObject methods
|
||||
virtual void SetContext(nsIScriptContext *aContext);
|
||||
virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID);
|
||||
virtual nsresult SetScriptContext(PRUint32 lang_id, nsIScriptContext *aContext);
|
||||
|
||||
virtual nsIScriptContext *GetContext();
|
||||
virtual void SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
|
||||
virtual nsIScriptGlobalObjectOwner *GetGlobalObjectOwner();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
virtual void OnFinalize(JSObject *aObject);
|
||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal);
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||
virtual nsresult SetNewArguments(PRUint32 aArgc, void* aArgv);
|
||||
virtual nsresult SetNewArguments(nsIArray *aArguments);
|
||||
|
||||
// nsIScriptObjectPrincipal methods
|
||||
virtual nsIPrincipal* GetPrincipal();
|
||||
|
@ -85,6 +89,10 @@ public:
|
|||
protected:
|
||||
virtual ~nsXBLDocGlobalObject();
|
||||
|
||||
void SetContext(nsIScriptContext *aContext);
|
||||
nsIScriptContext *GetScriptContext(PRUint32 language);
|
||||
void *GetScriptGlobal(PRUint32 language);
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContext;
|
||||
JSObject *mJSObject; // XXX JS language rabies bigotry badness
|
||||
|
||||
|
@ -155,7 +163,7 @@ nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
|||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||
|
||||
if (sgo)
|
||||
sgo->OnFinalize(obj);
|
||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
NS_RELEASE(nativeThis);
|
||||
|
@ -229,15 +237,92 @@ XBL_ProtoErrorReporter(JSContext *cx,
|
|||
//
|
||||
|
||||
void
|
||||
nsXBLDocGlobalObject::SetContext(nsIScriptContext *aContext)
|
||||
nsXBLDocGlobalObject::SetContext(nsIScriptContext *aScriptContext)
|
||||
{
|
||||
mScriptContext = aContext;
|
||||
if (mScriptContext) {
|
||||
JSContext* cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
|
||||
if (!aScriptContext) {
|
||||
mScriptContext = nsnull;
|
||||
return;
|
||||
}
|
||||
NS_ASSERTION(aScriptContext->GetScriptTypeID() ==
|
||||
nsIProgrammingLanguage::JAVASCRIPT,
|
||||
"xbl is not multi-language");
|
||||
aScriptContext->WillInitializeContext();
|
||||
// NOTE: We init this context with a NULL global, so we automatically
|
||||
// hook up to the existing nsIScriptGlobalObject global setup by
|
||||
// nsGlobalWindow.
|
||||
nsresult rv;
|
||||
rv = aScriptContext->InitContext(nsnull);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
|
||||
aScriptContext->DidInitializeContext();
|
||||
// and we set up our global manually
|
||||
mScriptContext = aScriptContext;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLDocGlobalObject::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aContext)
|
||||
{
|
||||
NS_ASSERTION(lang_id == nsIProgrammingLanguage::JAVASCRIPT, "Only JS allowed!");
|
||||
SetContext(aContext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScriptContext *
|
||||
nsXBLDocGlobalObject::GetScriptContext(PRUint32 language)
|
||||
{
|
||||
// This impl still assumes JS
|
||||
NS_ENSURE_TRUE(language==nsIProgrammingLanguage::JAVASCRIPT, nsnull);
|
||||
return GetContext();
|
||||
}
|
||||
|
||||
void *
|
||||
nsXBLDocGlobalObject::GetScriptGlobal(PRUint32 language)
|
||||
{
|
||||
// This impl still assumes JS
|
||||
NS_ENSURE_TRUE(language==nsIProgrammingLanguage::JAVASCRIPT, nsnull);
|
||||
return GetGlobalJSObject();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLDocGlobalObject::EnsureScriptEnvironment(PRUint32 aLangID)
|
||||
{
|
||||
if (aLangID != nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
NS_WARNING("XBL still JS only");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (mScriptContext)
|
||||
return NS_OK; // already initialized for this lang
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
|
||||
NS_ENSURE_TRUE(factory, nsnull);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptRuntime> scriptRuntime;
|
||||
rv = NS_GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRuntime));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIScriptContext> newCtx;
|
||||
rv = scriptRuntime->CreateContext(getter_AddRefs(newCtx));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetScriptContext(aLangID, newCtx);
|
||||
|
||||
JSContext *cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// nsJSEnvironment set the error reporter to NS_ScriptErrorReporter so
|
||||
// we must apparently override that with our own (although it isn't clear
|
||||
// why - see bug 339647)
|
||||
JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
|
||||
mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
|
||||
if (!mJSObject)
|
||||
return nsnull;
|
||||
|
||||
::JS_SetGlobalObject(cx, mJSObject);
|
||||
|
||||
// Add an owning reference from JS back to us. This'll be
|
||||
// released when the JSObject is finalized.
|
||||
::JS_SetPrivate(cx, mJSObject, this);
|
||||
NS_ADDREF(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScriptContext *
|
||||
nsXBLDocGlobalObject::GetContext()
|
||||
|
@ -245,48 +330,27 @@ nsXBLDocGlobalObject::GetContext()
|
|||
// This whole fragile mess is predicated on the fact that
|
||||
// GetContext() will be called before GetScriptObject() is.
|
||||
if (! mScriptContext) {
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
|
||||
NS_ENSURE_TRUE(factory, nsnull);
|
||||
|
||||
nsresult rv = factory->NewScriptContext(nsnull, getter_AddRefs(mScriptContext));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
|
||||
JSContext *cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
|
||||
mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
|
||||
if (!mJSObject)
|
||||
return nsnull;
|
||||
|
||||
::JS_SetGlobalObject(cx, mJSObject);
|
||||
|
||||
// Add an owning reference from JS back to us. This'll be
|
||||
// released when the JSObject is finalized.
|
||||
::JS_SetPrivate(cx, mJSObject, this);
|
||||
NS_ADDREF(this);
|
||||
nsresult rv = EnsureScriptEnvironment(nsIProgrammingLanguage::JAVASCRIPT);
|
||||
// JS is builtin so we make noise if it fails to initialize.
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to setup JS!?");
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
NS_ASSERTION(mScriptContext, "Failed to find a script context!?");
|
||||
}
|
||||
|
||||
return mScriptContext;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXBLDocGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
|
||||
{
|
||||
mGlobalObjectOwner = aOwner; // weak reference
|
||||
}
|
||||
|
||||
|
||||
nsIScriptGlobalObjectOwner *
|
||||
nsXBLDocGlobalObject::GetGlobalObjectOwner()
|
||||
{
|
||||
return mGlobalObjectOwner;
|
||||
}
|
||||
|
||||
|
||||
JSObject *
|
||||
nsXBLDocGlobalObject::GetGlobalJSObject()
|
||||
{
|
||||
|
@ -296,17 +360,21 @@ nsXBLDocGlobalObject::GetGlobalJSObject()
|
|||
if (!mScriptContext)
|
||||
return nsnull;
|
||||
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
mScriptContext->GetNativeContext());
|
||||
JSContext* cx = NS_STATIC_CAST(JSContext*,
|
||||
mScriptContext->GetNativeContext());
|
||||
if (!cx)
|
||||
return nsnull;
|
||||
|
||||
return ::JS_GetGlobalObject(cx);
|
||||
JSObject *ret = ::JS_GetGlobalObject(cx);
|
||||
NS_ASSERTION(mJSObject == ret, "How did this magic switch happen?");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLDocGlobalObject::OnFinalize(JSObject *aObject)
|
||||
nsXBLDocGlobalObject::OnFinalize(PRUint32 aLangID, void *aObject)
|
||||
{
|
||||
NS_ASSERTION(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
|
||||
"Only JS supported");
|
||||
NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
|
||||
|
||||
mJSObject = nsnull;
|
||||
|
@ -319,7 +387,7 @@ nsXBLDocGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXBLDocGlobalObject::SetNewArguments(PRUint32 aArgc, void* aArgv)
|
||||
nsXBLDocGlobalObject::SetNewArguments(nsIArray *aArguments)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -382,7 +450,8 @@ nsXBLDocumentInfo::~nsXBLDocumentInfo()
|
|||
{
|
||||
/* destructor code */
|
||||
if (mGlobalObject) {
|
||||
mGlobalObject->SetContext(nsnull); // remove circular reference
|
||||
// remove circular reference
|
||||
mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
|
||||
mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case
|
||||
}
|
||||
delete mBindingTable;
|
||||
|
|
|
@ -102,9 +102,8 @@ nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext,
|
|||
return NS_OK; // nothing to do.
|
||||
|
||||
JSContext* cx = (JSContext*) aContext->GetNativeContext();
|
||||
JSObject * scriptObject = (JSObject *) aScriptObject;
|
||||
NS_ASSERTION(scriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
|
||||
if (!scriptObject)
|
||||
NS_ASSERTION(aScriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
|
||||
if (!aScriptObject)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCAutoString bindingURI(aClassStr);
|
||||
|
@ -126,7 +125,7 @@ nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext,
|
|||
nsCOMPtr<nsIScriptContext> context = aContext;
|
||||
rv = context->EvaluateStringWithValue(nsDependentString(mFieldText,
|
||||
mFieldTextLength),
|
||||
scriptObject,
|
||||
aScriptObject,
|
||||
nsnull, bindingURI.get(),
|
||||
mLineNumber, nsnull,
|
||||
(void*) &result, &undefined);
|
||||
|
@ -137,8 +136,9 @@ nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext,
|
|||
// Define the evaluated result as a JS property
|
||||
nsDependentString name(mName);
|
||||
JSAutoRequest ar(cx);
|
||||
if (!::JS_DefineUCProperty(cx, scriptObject, NS_REINTERPRET_CAST(const jschar*, mName),
|
||||
name.Length(), result, nsnull, nsnull, mJSAttributes))
|
||||
if (!::JS_DefineUCProperty(cx, NS_STATIC_CAST(JSObject *, aScriptObject),
|
||||
NS_REINTERPRET_CAST(const jschar*, mName),
|
||||
name.Length(), result, nsnull, nsnull, mJSAttributes))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "nsXBLEventHandler.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDOMScriptObjectHolder.h"
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
@ -402,8 +403,9 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
|
|||
onEvent += str;
|
||||
nsCOMPtr<nsIAtom> onEventAtom = do_GetAtom(onEvent);
|
||||
|
||||
void* handler = nsnull;
|
||||
|
||||
// Compile the event handler.
|
||||
PRUint32 stID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
|
||||
// Compile the handler and bind it to the element.
|
||||
nsCOMPtr<nsIScriptGlobalObject> boundGlobal;
|
||||
nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aReceiver));
|
||||
|
@ -451,32 +453,25 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
|
|||
if (!boundGlobal)
|
||||
return NS_OK;
|
||||
|
||||
nsIScriptContext *boundContext = boundGlobal->GetContext();
|
||||
nsIScriptContext *boundContext = boundGlobal->GetScriptContext(stID);
|
||||
if (!boundContext) return NS_OK;
|
||||
|
||||
JSObject* scriptObject = nsnull;
|
||||
|
||||
// strong ref to a GC root we'll need to protect scriptObject in the case
|
||||
// where it is not the global object (!winRoot).
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||
nsScriptObjectHolder handler(boundContext);
|
||||
nsISupports *scriptTarget;
|
||||
|
||||
if (winRoot) {
|
||||
scriptObject = boundGlobal->GetGlobalJSObject();
|
||||
scriptTarget = boundGlobal;
|
||||
} else {
|
||||
JSObject *global = boundGlobal->GetGlobalJSObject();
|
||||
JSContext *cx = (JSContext *)boundContext->GetNativeContext();
|
||||
|
||||
// XXX: Don't use the global object!
|
||||
rv = nsContentUtils::XPConnect()->WrapNative(cx, global, aReceiver,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = wrapper->GetJSObject(&scriptObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
scriptTarget = aReceiver;
|
||||
}
|
||||
// XXX - apparently we should not be using the global as the scope - what
|
||||
// should we use? See bug 339649, which is trying to find out!
|
||||
void *scope = boundGlobal->GetScriptGlobal(stID);
|
||||
|
||||
const char *eventName = nsContentUtils::GetEventArgName(kNameSpaceID_XBL);
|
||||
PRUint32 argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, onEventAtom, &argCount,
|
||||
&argNames);
|
||||
|
||||
nsDependentString handlerText(mHandlerText);
|
||||
if (handlerText.IsEmpty())
|
||||
|
@ -485,21 +480,20 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver,
|
|||
nsCAutoString bindingURI;
|
||||
mPrototypeBinding->DocURI()->GetSpec(bindingURI);
|
||||
|
||||
rv = boundContext->CompileEventHandler(scriptObject, onEventAtom, eventName,
|
||||
rv = boundContext->CompileEventHandler(onEventAtom, argCount, argNames,
|
||||
handlerText, bindingURI.get(),
|
||||
mLineNumber, PR_TRUE, &handler);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoGCRoot root(&handler, &rv);
|
||||
mLineNumber, handler);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Temporarily bind it to the bound element
|
||||
boundContext->BindCompiledEventHandler(scriptObject, onEventAtom, handler);
|
||||
rv = boundContext->BindCompiledEventHandler(scriptTarget, scope,
|
||||
onEventAtom, handler);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Execute it.
|
||||
nsCOMPtr<nsIDOMEventListener> eventListener;
|
||||
NS_NewJSEventListener(boundContext, boundGlobal->GetGlobalJSObject(),
|
||||
aReceiver, getter_AddRefs(eventListener));
|
||||
NS_NewJSEventListener(boundContext, scope,
|
||||
scriptTarget, getter_AddRefs(eventListener));
|
||||
|
||||
nsCOMPtr<nsIJSEventListener> jsListener(do_QueryInterface(eventListener));
|
||||
jsListener->SetEventName(onEventAtom);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Peter Annema <disttsc@bart.nl>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Mike Shaver <shaver@mozilla.org>
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -55,7 +56,6 @@
|
|||
*/
|
||||
|
||||
#include "jsapi.h" // for JS_AddNamedRoot and JS_RemoveRootRT
|
||||
#include "jsxdrapi.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "nsDOMError.h"
|
||||
|
@ -98,6 +98,7 @@
|
|||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
@ -296,6 +297,10 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
|
|||
|
||||
element->mPrototype = aPrototype;
|
||||
|
||||
NS_ASSERTION(aPrototype->mScriptTypeID != nsIProgrammingLanguage::UNKNOWN,
|
||||
"Need to know the language!");
|
||||
element->SetScriptTypeID(aPrototype->mScriptTypeID);
|
||||
|
||||
if (aIsScriptable) {
|
||||
// Check each attribute on the prototype to see if we need to do
|
||||
// any additional processing and hookup that would otherwise be
|
||||
|
@ -438,11 +443,18 @@ nsXULElement::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
|
|||
nsRefPtr<nsXULElement> element;
|
||||
if (mPrototype) {
|
||||
element = nsXULElement::Create(mPrototype, aNodeInfo, PR_TRUE);
|
||||
NS_ASSERTION(GetScriptTypeID() == mPrototype->mScriptTypeID,
|
||||
"Didn't get the default language from proto?");
|
||||
|
||||
fakeBeingInDocument = IsInDoc();
|
||||
}
|
||||
else {
|
||||
element = new nsXULElement(aNodeInfo);
|
||||
if (element) {
|
||||
// If created from a prototype, we will already have the script
|
||||
// language specified by the proto - otherwise copy it directly
|
||||
element->SetScriptTypeID(GetScriptTypeID());
|
||||
}
|
||||
}
|
||||
|
||||
if (!element) {
|
||||
|
@ -607,16 +619,17 @@ nsXULElement::IsFocusable(PRInt32 *aTabIndex)
|
|||
// nsIScriptEventHandlerOwner interface
|
||||
|
||||
nsresult
|
||||
nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
||||
nsXULElement::GetCompiledEventHandler(nsIAtom *aName,
|
||||
nsScriptObjectHolder &aHandler)
|
||||
{
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheTests);
|
||||
*aHandler = nsnull;
|
||||
aHandler.drop();
|
||||
|
||||
nsXULPrototypeAttribute *attr =
|
||||
FindPrototypeAttribute(kNameSpaceID_None, aName);
|
||||
if (attr) {
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheHits);
|
||||
*aHandler = attr->mEventHandler;
|
||||
aHandler.set(attr->mEventHandler);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -624,15 +637,14 @@ nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
|||
|
||||
nsresult
|
||||
nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsISupports* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aBody,
|
||||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
void** aHandler)
|
||||
nsScriptObjectHolder &aHandler)
|
||||
{
|
||||
nsresult rv;
|
||||
JSObject* scopeObject;
|
||||
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
|
||||
|
||||
|
@ -642,9 +654,6 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
|||
nsIScriptContext *context;
|
||||
if (mPrototype && xuldoc) {
|
||||
// It'll be shared among the instances of the prototype.
|
||||
// Use null for the scope object when precompiling shared
|
||||
// prototype scripts.
|
||||
scopeObject = nsnull;
|
||||
|
||||
// Use the prototype document's special context. Because
|
||||
// scopeObject is null, the JS engine has no other source of
|
||||
|
@ -663,28 +672,37 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
|||
nsIScriptGlobalObject* global = globalOwner->GetScriptGlobalObject();
|
||||
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
|
||||
|
||||
context = global->GetContext();
|
||||
context = global->GetScriptContext(aContext->GetScriptTypeID());
|
||||
// It could be possible the language has been setup on aContext but
|
||||
// not on the global - we don't demand-create language contexts on the
|
||||
// nsGlobalWindow
|
||||
NS_ASSERTION(context,
|
||||
"Failed to get a language context from the global!?");
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
else {
|
||||
// We don't have a prototype; do a one-off compile.
|
||||
// We don't have a prototype, so the passed context is ok.
|
||||
NS_ASSERTION(aTarget != nsnull, "no prototype and no target?!");
|
||||
scopeObject = NS_REINTERPRET_CAST(JSObject*, aTarget);
|
||||
context = aContext;
|
||||
}
|
||||
|
||||
// Compile the event handler
|
||||
const char *eventName = nsContentUtils::GetEventArgName(kNameSpaceID_XUL);
|
||||
rv = context->CompileEventHandler(scopeObject, aName, eventName, aBody,
|
||||
aURL, aLineNo, !scopeObject,
|
||||
aHandler);
|
||||
PRUint32 argCount;
|
||||
const char **argNames;
|
||||
nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
|
||||
&argNames);
|
||||
rv = context->CompileEventHandler(aName, argCount, argNames,
|
||||
aBody, aURL, aLineNo, aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! scopeObject) {
|
||||
if (mPrototype && xuldoc) {
|
||||
// If it's a shared handler, we need to bind the shared
|
||||
// function object to the real target.
|
||||
|
||||
// XXX: Shouldn't this use context and not aContext?
|
||||
rv = aContext->BindCompiledEventHandler(aTarget, aName, *aHandler);
|
||||
// XXXmarkh - is GetNativeGlobal() the correct scope?
|
||||
rv = aContext->BindCompiledEventHandler(aTarget, aContext->GetNativeGlobal(),
|
||||
aName, aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
@ -692,19 +710,11 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
|
|||
FindPrototypeAttribute(kNameSpaceID_None, aName);
|
||||
if (attr) {
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
||||
attr->mEventHandler = *aHandler;
|
||||
|
||||
// take a copy of the event handler, and tell the language about it.
|
||||
attr->mEventHandler = (void *)aHandler;
|
||||
if (attr->mEventHandler) {
|
||||
JSContext *cx = (JSContext*) context->GetNativeContext();
|
||||
if (!cx)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = nsContentUtils::AddJSGCRoot(&attr->mEventHandler,
|
||||
"nsXULPrototypeAttribute::mEventHandler");
|
||||
if (NS_FAILED(rv)) {
|
||||
attr->mEventHandler = nsnull;
|
||||
return rv;
|
||||
}
|
||||
rv = aContext->HoldScriptObject(attr->mEventHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,7 +736,7 @@ nsXULElement::AddListenerFor(const nsAttrName& aName,
|
|||
if (aCompileEventHandlers && IsEventHandler(attr)) {
|
||||
nsAutoString value;
|
||||
GetAttr(kNameSpaceID_None, attr, value);
|
||||
AddScriptEventListener(attr, value);
|
||||
AddScriptEventListener(attr, value, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +879,7 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
// XXXbz why do we have attributes depending on the current document?
|
||||
// Shouldn't they depend on the owner document? Or is this code just
|
||||
// misplaced, basically?
|
||||
|
||||
|
||||
PRInt32 count = mAttrsAndChildren.AttrCount();
|
||||
PRBool haveLocalAttributes = (count > 0);
|
||||
PRInt32 i;
|
||||
|
@ -879,6 +889,11 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|||
}
|
||||
|
||||
if (mPrototype) {
|
||||
// If we have a prototype, the node we are binding to should
|
||||
// have the same script-type - otherwise we will compile the
|
||||
// event handlers incorrectly.
|
||||
NS_ASSERTION(mPrototype->mScriptTypeID == GetScriptTypeID(),
|
||||
"Prototype and node confused about default language?");
|
||||
PRInt32 count = mPrototype->mNumAttributes;
|
||||
for (i = 0; i < count; i++) {
|
||||
nsXULPrototypeAttribute *protoattr =
|
||||
|
@ -1181,7 +1196,14 @@ nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
|||
// the attribute isn't set yet.
|
||||
MaybeAddPopupListener(aName);
|
||||
if (IsEventHandler(aName) && aValue) {
|
||||
AddScriptEventListener(aName, *aValue);
|
||||
// If mPrototype->mScriptTypeID != GetScriptTypeID(), it means
|
||||
// we are resolving an overlay with a different default script
|
||||
// language. We can't defer compilation of those handlers as
|
||||
// we will have lost the script language (storing it on each
|
||||
// nsXULPrototypeAttribute is expensive!)
|
||||
PRBool defer = mPrototype == nsnull ||
|
||||
mPrototype->mScriptTypeID == GetScriptTypeID();
|
||||
AddScriptEventListener(aName, *aValue, defer);
|
||||
}
|
||||
|
||||
// Hide chrome if needed
|
||||
|
@ -2455,8 +2477,17 @@ nsXULElement::BoolAttrIsTrue(nsIAtom* aName)
|
|||
nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
|
||||
if (mEventHandler)
|
||||
nsContentUtils::RemoveJSGCRoot(&mEventHandler);
|
||||
NS_ASSERTION(!mEventHandler, "Finalize not called - language object leak!");
|
||||
}
|
||||
|
||||
void
|
||||
nsXULPrototypeAttribute::Finalize(PRUint32 aLangID)
|
||||
{
|
||||
if (mEventHandler) {
|
||||
if (NS_FAILED(NS_DropScriptObject(aLangID, mEventHandler)))
|
||||
NS_ERROR("Failed to drop script object");
|
||||
mEventHandler = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2467,7 +2498,7 @@ nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -2475,6 +2506,9 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
|||
// Write basic prototype data
|
||||
rv = aStream->Write32(mType);
|
||||
|
||||
// Write script language
|
||||
rv |= aStream->Write32(mScriptTypeID);
|
||||
|
||||
// Write Node Info
|
||||
PRInt32 index = aNodeInfos->IndexOf(mNodeInfo);
|
||||
NS_ASSERTION(index >= 0, "unknown nsINodeInfo index");
|
||||
|
@ -2512,27 +2546,29 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
|||
switch (child->mType) {
|
||||
case eType_Element:
|
||||
case eType_Text:
|
||||
rv |= child->Serialize(aStream, aContext, aNodeInfos);
|
||||
rv |= child->Serialize(aStream, aGlobal, aNodeInfos);
|
||||
break;
|
||||
case eType_Script:
|
||||
rv |= aStream->Write32(child->mType);
|
||||
nsXULPrototypeScript* script = NS_STATIC_CAST(nsXULPrototypeScript*, child);
|
||||
|
||||
rv |= aStream->Write32(script->mScriptObject.getScriptTypeID());
|
||||
|
||||
rv |= aStream->Write8(script->mOutOfLine);
|
||||
if (! script->mOutOfLine) {
|
||||
rv |= script->Serialize(aStream, aContext, aNodeInfos);
|
||||
rv |= script->Serialize(aStream, aGlobal, aNodeInfos);
|
||||
} else {
|
||||
rv |= aStream->WriteCompoundObject(script->mSrcURI,
|
||||
NS_GET_IID(nsIURI),
|
||||
PR_TRUE);
|
||||
|
||||
if (script->mJSObject) {
|
||||
if (script->mScriptObject) {
|
||||
// This may return NS_OK without muxing script->mSrcURI's
|
||||
// data into the FastLoad file, in the case where that
|
||||
// muxed document is already there (written by a prior
|
||||
// session, or by an earlier FastLoad episode during this
|
||||
// session).
|
||||
rv |= script->SerializeOutOfLine(aStream, aContext);
|
||||
rv |= script->SerializeOutOfLine(aStream, aGlobal);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2544,16 +2580,18 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
NS_PRECONDITION(aNodeInfos, "missing nodeinfo array");
|
||||
nsresult rv;
|
||||
|
||||
// Read script language
|
||||
rv = aStream->Read32(&mScriptTypeID);
|
||||
// Read Node Info
|
||||
PRUint32 number;
|
||||
rv = aStream->Read32(&number);
|
||||
rv |= aStream->Read32(&number);
|
||||
mNodeInfo = aNodeInfos->SafeObjectAt(number);
|
||||
if (!mNodeInfo)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -2605,7 +2643,7 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
child->mType = childType;
|
||||
|
||||
rv |= child->Deserialize(aStream, aContext, aDocumentURI,
|
||||
rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
|
||||
aNodeInfos);
|
||||
break;
|
||||
case eType_Text:
|
||||
|
@ -2614,33 +2652,30 @@ nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
child->mType = childType;
|
||||
|
||||
rv |= child->Deserialize(aStream, aContext, aDocumentURI,
|
||||
rv |= child->Deserialize(aStream, aGlobal, aDocumentURI,
|
||||
aNodeInfos);
|
||||
break;
|
||||
case eType_Script: {
|
||||
PRUint32 langID = nsIProgrammingLanguage::UNKNOWN;
|
||||
rv |= aStream->Read32(&langID);
|
||||
|
||||
// language version/options obtained during deserialization.
|
||||
// Don't clobber rv here, since it might already be a failure!
|
||||
nsresult result;
|
||||
nsXULPrototypeScript* script =
|
||||
new nsXULPrototypeScript(0, nsnull, PR_FALSE, &result);
|
||||
nsXULPrototypeScript* script = new nsXULPrototypeScript(langID, 0, 0);
|
||||
if (! script)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (NS_FAILED(result)) {
|
||||
delete script;
|
||||
return result;
|
||||
}
|
||||
child = script;
|
||||
child->mType = childType;
|
||||
|
||||
rv |= aStream->Read8(&script->mOutOfLine);
|
||||
if (! script->mOutOfLine) {
|
||||
rv |= script->Deserialize(aStream, aContext, aDocumentURI,
|
||||
rv |= script->Deserialize(aStream, aGlobal, aDocumentURI,
|
||||
aNodeInfos);
|
||||
} else {
|
||||
rv |= aStream->ReadObject(PR_TRUE, getter_AddRefs(script->mSrcURI));
|
||||
|
||||
rv |= script->DeserializeOutOfLine(aStream, aContext);
|
||||
rv |= script->DeserializeOutOfLine(aStream, aGlobal);
|
||||
}
|
||||
// If we failed to deserialize, consider deleting 'script'?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2721,93 +2756,45 @@ nsXULPrototypeElement::SetAttrAt(PRUint32 aPos, const nsAString& aValue,
|
|||
// nsXULPrototypeScript
|
||||
//
|
||||
|
||||
nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLineNo,
|
||||
const char *aVersion,
|
||||
PRBool aHasE4XOption,
|
||||
nsresult* rv)
|
||||
nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 aVersion)
|
||||
: nsXULPrototypeNode(eType_Script),
|
||||
mLineNo(aLineNo),
|
||||
mSrcLoading(PR_FALSE),
|
||||
mOutOfLine(PR_TRUE),
|
||||
mHasE4XOption(aHasE4XOption),
|
||||
mSrcLoadWaiters(nsnull),
|
||||
mJSObject(nsnull),
|
||||
mScriptObject(aLangID, nsnull),
|
||||
mLangVersion(aVersion)
|
||||
{
|
||||
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
|
||||
*rv = nsContentUtils::AddJSGCRoot(&mJSObject,
|
||||
"nsXULPrototypeScript::mJSObject");
|
||||
mAddedGCRoot = NS_SUCCEEDED(*rv);
|
||||
NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
|
||||
"The language ID must be known and constant");
|
||||
}
|
||||
|
||||
|
||||
nsXULPrototypeScript::~nsXULPrototypeScript()
|
||||
{
|
||||
if (mAddedGCRoot) {
|
||||
nsContentUtils::RemoveJSGCRoot(&mJSObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mJSObject,
|
||||
nsIScriptContext *context = aGlobal->GetScriptContext(
|
||||
mScriptObject.getScriptTypeID());
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mScriptObject,
|
||||
"script source still loading when serializing?!");
|
||||
if (!mJSObject)
|
||||
if (!mScriptObject)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Write basic prototype data
|
||||
aStream->Write32(mLineNo);
|
||||
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
aContext->GetNativeContext());
|
||||
JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_ENCODE);
|
||||
if (! xdr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
xdr->userdata = (void*) aStream;
|
||||
|
||||
JSScript *script = NS_REINTERPRET_CAST(JSScript*,
|
||||
::JS_GetPrivate(cx, mJSObject));
|
||||
JSAutoRequest ar(cx);
|
||||
if (! ::JS_XDRScript(xdr, &script)) {
|
||||
rv = NS_ERROR_FAILURE; // likely to be a principals serialization error
|
||||
} else {
|
||||
// Get the encoded JSXDRState data and write it. The JSXDRState owns
|
||||
// this buffer memory and will free it beneath ::JS_XDRDestroy.
|
||||
//
|
||||
// If an XPCOM object needs to be written in the midst of the JS XDR
|
||||
// encoding process, the C++ code called back from the JS engine (e.g.,
|
||||
// nsEncodeJSPrincipals in caps/src/nsJSPrincipals.cpp) will flush data
|
||||
// from the JSXDRState to aStream, then write the object, then return
|
||||
// to JS XDR code with xdr reset so new JS data is encoded at the front
|
||||
// of the xdr's data buffer.
|
||||
//
|
||||
// However many XPCOM objects are interleaved with JS XDR data in the
|
||||
// stream, when control returns here from ::JS_XDRScript, we'll have
|
||||
// one last buffer of data to write to aStream.
|
||||
|
||||
uint32 size;
|
||||
const char* data = NS_REINTERPRET_CAST(const char*,
|
||||
::JS_XDRMemGetData(xdr, &size));
|
||||
NS_ASSERTION(data, "no decoded JSXDRState data!");
|
||||
|
||||
rv = aStream->Write32(size);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = aStream->WriteBytes(data, size);
|
||||
}
|
||||
|
||||
::JS_XDRDestroy(xdr);
|
||||
nsresult rv;
|
||||
rv = aStream->Write32(mLineNo);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 version = PRUint32(mLangVersion
|
||||
? ::JS_StringToVersion(mLangVersion)
|
||||
: JSVERSION_DEFAULT);
|
||||
rv = aStream->Write32(version);
|
||||
rv = aStream->Write32(mLangVersion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// And delegate the writing to the nsIScriptContext
|
||||
rv = context->Serialize(aStream, mScriptObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2815,7 +2802,7 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext)
|
||||
nsIScriptGlobalObject* aGlobal)
|
||||
{
|
||||
nsIXULPrototypeCache* cache = GetXULCache();
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -2864,7 +2851,7 @@ nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
|
|||
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
rv |= fastLoadService->SelectMuxedDocument(mSrcURI, getter_AddRefs(oldURI));
|
||||
rv |= Serialize(objectOutput, aContext, nsnull);
|
||||
rv |= Serialize(objectOutput, aGlobal, nsnull);
|
||||
rv |= fastLoadService->EndMuxedDocument(mSrcURI);
|
||||
|
||||
if (oldURI) {
|
||||
|
@ -2881,94 +2868,38 @@ nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
NS_TIMELINE_MARK_FUNCTION("chrome js deserialize");
|
||||
NS_TIMELINE_MARK_FUNCTION("chrome script deserialize");
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mScriptObject,
|
||||
"prototype script not well-initialized when deserializing?!");
|
||||
|
||||
// Read basic prototype data
|
||||
aStream->Read32(&mLineNo);
|
||||
aStream->Read32(&mLangVersion);
|
||||
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mJSObject,
|
||||
"prototype script not well-initialized when deserializing?!");
|
||||
|
||||
PRUint32 size;
|
||||
rv = aStream->Read32(&size);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char* data;
|
||||
rv = aStream->ReadBytes(size, &data);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
aContext->GetNativeContext());
|
||||
|
||||
JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_DECODE);
|
||||
if (! xdr) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
xdr->userdata = (void*) aStream;
|
||||
JSAutoRequest ar(cx);
|
||||
::JS_XDRMemSetData(xdr, data, size);
|
||||
|
||||
JSScript *script = nsnull;
|
||||
if (! ::JS_XDRScript(xdr, &script)) {
|
||||
rv = NS_ERROR_FAILURE; // principals deserialization error?
|
||||
} else {
|
||||
mJSObject = ::JS_NewScriptObject(cx, script);
|
||||
if (! mJSObject) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY; // certain error
|
||||
::JS_DestroyScript(cx, script);
|
||||
}
|
||||
}
|
||||
|
||||
// Update data in case ::JS_XDRScript called back into C++ code to
|
||||
// read an XPCOM object.
|
||||
//
|
||||
// In that case, the serialization process must have flushed a run
|
||||
// of counted bytes containing JS data at the point where the XPCOM
|
||||
// object starts, after which an encoding C++ callback from the JS
|
||||
// XDR code must have written the XPCOM object directly into the
|
||||
// nsIObjectOutputStream.
|
||||
//
|
||||
// The deserialization process will XDR-decode counted bytes up to
|
||||
// but not including the XPCOM object, then call back into C++ to
|
||||
// read the object, then read more counted bytes and hand them off
|
||||
// to the JSXDRState, so more JS data can be decoded.
|
||||
//
|
||||
// This interleaving of JS XDR data and XPCOM object data may occur
|
||||
// several times beneath the call to ::JS_XDRScript, above. At the
|
||||
// end of the day, we need to free (via nsMemory) the data owned by
|
||||
// the JSXDRState. So we steal it back, nulling xdr's buffer so it
|
||||
// doesn't get passed to ::JS_free by ::JS_XDRDestroy.
|
||||
|
||||
uint32 junk;
|
||||
data = (char*) ::JS_XDRMemGetData(xdr, &junk);
|
||||
if (data)
|
||||
::JS_XDRMemSetData(xdr, NULL, 0);
|
||||
::JS_XDRDestroy(xdr);
|
||||
}
|
||||
|
||||
// If data is null now, it must have been freed while deserializing an
|
||||
// XPCOM object (e.g., a principal) beneath ::JS_XDRScript.
|
||||
if (data)
|
||||
nsMemory::Free(data);
|
||||
nsIScriptContext *context = aGlobal->GetScriptContext(
|
||||
mScriptObject.getScriptTypeID());
|
||||
NS_ASSERTION(context != nsnull, "Have no context for deserialization");
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
|
||||
nsScriptObjectHolder newScriptObject(context);
|
||||
rv = context->Deserialize(aStream, newScriptObject);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Language deseralization failed");
|
||||
return rv;
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRUint32 version;
|
||||
rv = aStream->Read32(&version);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mLangVersion = ::JS_VersionToString(JSVersion(version));
|
||||
mScriptObject = newScriptObject;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
nsIScriptContext* aContext)
|
||||
nsIScriptGlobalObject* aGlobal)
|
||||
{
|
||||
// Keep track of FastLoad failure via rv, so we can
|
||||
// AbortFastLoads if things look bad.
|
||||
|
@ -3001,11 +2932,27 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
|||
cache->GetEnabled(&useXULCache);
|
||||
|
||||
if (useXULCache) {
|
||||
cache->GetScript(mSrcURI, NS_REINTERPRET_CAST(void**, &mJSObject));
|
||||
void *newScriptObject = nsnull;
|
||||
PRUint32 newLangID = nsIProgrammingLanguage::UNKNOWN;
|
||||
cache->GetScript(mSrcURI, &newLangID, &newScriptObject);
|
||||
if (newScriptObject) {
|
||||
// Things may blow here if we simply change the script
|
||||
// language - other code may already have pre-fetched the
|
||||
// global for the language. (You can see this code by
|
||||
// setting langID to UNKNOWN in the nsXULPrototypeScript
|
||||
// ctor and not setting it until the scriptObject is set -
|
||||
// code that pre-fetches these globals will then start
|
||||
// asserting.)
|
||||
if (mScriptObject.getScriptTypeID() != newLangID) {
|
||||
NS_ERROR("XUL cache gave different language?");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
mScriptObject.set(newScriptObject);
|
||||
}
|
||||
}
|
||||
|
||||
if (! mJSObject) {
|
||||
if (! mScriptObject) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
|
||||
if (mSrcURI) {
|
||||
|
@ -3027,13 +2974,13 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
|||
}
|
||||
|
||||
// We do reflect errors into rv, but our caller may want to
|
||||
// ignore our return value, because mJSObject will be null
|
||||
// ignore our return value, because mScriptObject will be null
|
||||
// after any error, and that suffices to cause the script to
|
||||
// be reloaded (from the src= URI, if any) and recompiled.
|
||||
// We're better off slow-loading than bailing out due to a
|
||||
// FastLoad error.
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = Deserialize(objectInput, aContext, nsnull, nsnull);
|
||||
rv = Deserialize(objectInput, aGlobal, nsnull, nsnull);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && mSrcURI) {
|
||||
rv = fastLoadService->EndMuxedDocument(mSrcURI);
|
||||
|
@ -3052,7 +2999,9 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
|||
PRBool isChrome = PR_FALSE;
|
||||
mSrcURI->SchemeIs("chrome", &isChrome);
|
||||
if (isChrome) {
|
||||
cache->PutScript(mSrcURI, NS_REINTERPRET_CAST(void*, mJSObject));
|
||||
cache->PutScript(mSrcURI,
|
||||
mScriptObject.getScriptTypeID(),
|
||||
mScriptObject);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -3100,8 +3049,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
|||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
context = global->GetContext();
|
||||
|
||||
context = global->GetScriptContext(mScriptObject.getScriptTypeID());
|
||||
NS_ASSERTION(context != nsnull, "no context for script global");
|
||||
if (! context)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
@ -3112,22 +3060,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
|||
|
||||
// Ok, compile it to create a prototype script object!
|
||||
|
||||
// XXXbe violate nsIScriptContext layering because its version parameter
|
||||
// is mis-typed as const char * -- if it were uint32, we could more easily
|
||||
// extend version to include compile-time option, as the JS engine does.
|
||||
// It'd also be more efficient than converting to and from a C string.
|
||||
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
context->GetNativeContext());
|
||||
uint32 options = ::JS_GetOptions(cx);
|
||||
JSBool changed = (mHasE4XOption ^ !!(options & JSOPTION_XML));
|
||||
if (changed) {
|
||||
::JS_SetOptions(cx,
|
||||
mHasE4XOption
|
||||
? options | JSOPTION_XML
|
||||
: options & ~JSOPTION_XML);
|
||||
}
|
||||
|
||||
nsScriptObjectHolder newScriptObject(context);
|
||||
rv = context->CompileScript(aText,
|
||||
aTextLength,
|
||||
nsnull,
|
||||
|
@ -3138,11 +3071,11 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
|||
urlspec.get(),
|
||||
aLineNo,
|
||||
mLangVersion,
|
||||
(void**)&mJSObject);
|
||||
newScriptObject);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (changed) {
|
||||
::JS_SetOptions(cx, options);
|
||||
}
|
||||
mScriptObject = newScriptObject;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -3153,7 +3086,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -3168,7 +3101,7 @@ nsXULPrototypeText::Serialize(nsIObjectOutputStream* aStream,
|
|||
|
||||
nsresult
|
||||
nsXULPrototypeText::Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* Peter Annema <disttsc@bart.nl>
|
||||
* Mike Shaver <shaver@mozilla.org>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -78,6 +79,7 @@
|
|||
#include "nsXULAtoms.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsGenericElement.h"
|
||||
#include "nsDOMScriptObjectHolder.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsIRDFService;
|
||||
|
@ -125,8 +127,14 @@ public:
|
|||
|
||||
nsAttrName mName;
|
||||
nsAttrValue mValue;
|
||||
// mEventHandler is only valid for the language ID specified in the
|
||||
// containing nsXULPrototypeElement. We would ideally use
|
||||
// nsScriptObjectHolder, but want to avoid the extra lang ID.
|
||||
void* mEventHandler;
|
||||
|
||||
// Containing element must tell us the langID so we can cleanup.
|
||||
void Finalize(PRUint32 aLangID);
|
||||
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
/**
|
||||
If enough attributes, on average, are event handlers, it pays to keep
|
||||
|
@ -197,10 +205,10 @@ public:
|
|||
|
||||
virtual ~nsXULPrototypeNode() {}
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos) = 0;
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos) = 0;
|
||||
|
||||
|
@ -235,13 +243,17 @@ public:
|
|||
mNumChildren(0),
|
||||
mChildren(nsnull),
|
||||
mNumAttributes(0),
|
||||
mAttributes(nsnull)
|
||||
mAttributes(nsnull),
|
||||
mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
|
||||
{
|
||||
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
|
||||
}
|
||||
|
||||
virtual ~nsXULPrototypeElement()
|
||||
{
|
||||
PRUint32 i;
|
||||
for (i = 0; i < mNumAttributes; i++)
|
||||
mAttributes[i].Finalize(mScriptTypeID);
|
||||
delete[] mAttributes;
|
||||
delete[] mChildren;
|
||||
}
|
||||
|
@ -264,10 +276,10 @@ public:
|
|||
}
|
||||
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
|
||||
|
@ -281,6 +293,11 @@ public:
|
|||
PRUint32 mNumAttributes;
|
||||
nsXULPrototypeAttribute* mAttributes; // [OWNER]
|
||||
|
||||
// The language ID can not be set on a per-node basis, but is tracked
|
||||
// so that the language ID from the originating root can be used
|
||||
// (eg, when a node from an overlay ends up in our document, that node
|
||||
// must use its original script language, not our document's default.
|
||||
PRUint32 mScriptTypeID;
|
||||
static void ReleaseGlobals()
|
||||
{
|
||||
NS_IF_RELEASE(sCSSParser);
|
||||
|
@ -301,17 +318,12 @@ protected:
|
|||
static nsICSSParser* sCSSParser;
|
||||
};
|
||||
|
||||
struct JSRuntime;
|
||||
struct JSObject;
|
||||
class nsXULDocument;
|
||||
|
||||
class nsXULPrototypeScript : public nsXULPrototypeNode
|
||||
{
|
||||
public:
|
||||
// Note: if *rv is failure after the script is constructed, delete
|
||||
// it and return *rv.
|
||||
nsXULPrototypeScript(PRUint32 aLineNo, const char *aVersion,
|
||||
PRBool aHasE4XOption, nsresult* rv);
|
||||
nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 version);
|
||||
virtual ~nsXULPrototypeScript();
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
@ -320,16 +332,16 @@ public:
|
|||
#endif
|
||||
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
nsresult SerializeOutOfLine(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext);
|
||||
nsIScriptGlobalObject* aGlobal);
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
nsIScriptContext* aContext);
|
||||
nsIScriptGlobalObject* aGlobal);
|
||||
|
||||
nsresult Compile(const PRUnichar* aText, PRInt32 aTextLength,
|
||||
nsIURI* aURI, PRUint32 aLineNo,
|
||||
|
@ -340,11 +352,9 @@ public:
|
|||
PRUint32 mLineNo;
|
||||
PRPackedBool mSrcLoading;
|
||||
PRPackedBool mOutOfLine;
|
||||
PRPackedBool mHasE4XOption;
|
||||
PRPackedBool mAddedGCRoot;
|
||||
nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
|
||||
JSObject* mJSObject;
|
||||
const char* mLangVersion;
|
||||
PRUint32 mLangVersion;
|
||||
nsScriptObjectHolder mScriptObject;
|
||||
|
||||
static void ReleaseGlobals()
|
||||
{
|
||||
|
@ -381,10 +391,10 @@ public:
|
|||
#endif
|
||||
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsIScriptContext* aContext,
|
||||
nsIScriptGlobalObject* aGlobal,
|
||||
nsIURI* aDocumentURI,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos);
|
||||
|
||||
|
@ -496,6 +506,7 @@ public:
|
|||
PRBool aNotify);
|
||||
virtual const nsAttrName* GetAttrNameAt(PRUint32 aIndex) const;
|
||||
virtual PRUint32 GetAttrCount() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out, PRInt32 aIndent) const;
|
||||
virtual void DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const
|
||||
|
@ -548,13 +559,14 @@ public:
|
|||
|
||||
// nsIScriptEventHandlerOwner
|
||||
nsresult CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsISupports* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aBody,
|
||||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
void** aHandler);
|
||||
nsresult GetCompiledEventHandler(nsIAtom *aName, void** aHandler);
|
||||
nsScriptObjectHolder &aHandler);
|
||||
nsresult GetCompiledEventHandler(nsIAtom *aName,
|
||||
nsScriptObjectHolder &aHandler);
|
||||
|
||||
// nsIChromeEventHandler
|
||||
NS_DECL_NSICHROMEEVENTHANDLER
|
||||
|
|
|
@ -59,9 +59,9 @@ class nsIFastLoadService;
|
|||
#define NS_XULPROTOTYPECACHE_CID \
|
||||
{ 0x3a0a0fc1, 0x8349, 0x11d3, { 0xbe, 0x47, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } }
|
||||
|
||||
// {CD196299-18E9-4642-AD43-666315C4D241}
|
||||
// {F53A6C7E-0344-4543-9213-AFFFD30AC2BE}
|
||||
#define NS_IXULPROTOTYPECACHE_IID \
|
||||
{ 0xcd196299, 0x18e9, 0x4642, { 0xad, 0x43, 0x66, 0x63, 0x15, 0xc4, 0xd2, 0x41 } }
|
||||
{ 0xf53a6c7e, 0x344, 0x4543, { 0x92, 0x13, 0xaf, 0xff, 0xd3, 0xa, 0xc2, 0xbe } };
|
||||
|
||||
|
||||
class nsIXULPrototypeCache : public nsISupports
|
||||
|
@ -77,8 +77,8 @@ public:
|
|||
NS_IMETHOD PutStyleSheet(nsICSSStyleSheet* aStyleSheet) = 0;
|
||||
NS_IMETHOD FlushStyleSheets() = 0;
|
||||
|
||||
NS_IMETHOD GetScript(nsIURI* aURI, void** aScriptObject) = 0;
|
||||
NS_IMETHOD PutScript(nsIURI* aURI, void* aScriptObject) = 0;
|
||||
NS_IMETHOD GetScript(nsIURI* aURI, PRUint32 *aLangID, void** aScriptObject) = 0;
|
||||
NS_IMETHOD PutScript(nsIURI* aURI, PRUint32 aLangID, void* aScriptObject) = 0;
|
||||
NS_IMETHOD FlushScripts() = 0;
|
||||
|
||||
NS_IMETHOD GetXBLDocumentInfo(nsIURI* aURL, nsIXBLDocumentInfo** aResult) = 0;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Chris Waterson <waterson@netscape.com>
|
||||
* David Hyatt <hyatt@netscape.com>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -68,6 +69,7 @@
|
|||
#include "nsIParser.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITextContent.h"
|
||||
|
@ -90,7 +92,7 @@
|
|||
#include "nsXULElement.h"
|
||||
#include "prlog.h"
|
||||
#include "prmem.h"
|
||||
#include "jsapi.h" // for JSVERSION_*, JS_VersionToString, etc.
|
||||
#include "jscntxt.h" // for JSVERSION_HAS_XML
|
||||
#include "nsCRT.h"
|
||||
|
||||
#include "nsIFastLoadService.h" // XXXbe temporary
|
||||
|
@ -168,6 +170,9 @@ protected:
|
|||
|
||||
static PRBool IsDataInBuffer(PRUnichar* aBuffer, PRInt32 aLength);
|
||||
|
||||
nsresult SetElementScriptType(nsXULPrototypeElement* element,
|
||||
const PRUnichar** aAttributes,
|
||||
const PRUint32 aAttrLen);
|
||||
|
||||
// Text management
|
||||
nsresult FlushText(PRBool aCreateTextNode = PR_TRUE);
|
||||
|
@ -221,6 +226,7 @@ protected:
|
|||
|
||||
nsresult GetTopNode(nsXULPrototypeNode** aNode);
|
||||
nsresult GetTopChildren(nsVoidArray** aChildren);
|
||||
nsresult GetTopNodeScriptType(PRUint32 *aScriptType);
|
||||
};
|
||||
|
||||
friend class ContextStack;
|
||||
|
@ -310,6 +316,38 @@ XULContentSinkImpl::ContextStack::GetTopChildren(nsVoidArray** aChildren)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::ContextStack::GetTopNodeScriptType(PRUint32 *aScriptType)
|
||||
{
|
||||
if (mDepth == 0)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// This would be much simpler if nsXULPrototypeNode itself
|
||||
// stored the language ID - but text elements don't need it!
|
||||
nsresult rv = NS_OK;
|
||||
nsXULPrototypeNode* node;
|
||||
rv = GetTopNode(&node);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
switch (node->mType) {
|
||||
case nsXULPrototypeNode::eType_Element: {
|
||||
nsXULPrototypeElement *parent = \
|
||||
NS_REINTERPRET_CAST(nsXULPrototypeElement*, node);
|
||||
*aScriptType = parent->mScriptTypeID;
|
||||
break;
|
||||
}
|
||||
case nsXULPrototypeNode::eType_Script: {
|
||||
nsXULPrototypeScript *parent = \
|
||||
NS_REINTERPRET_CAST(nsXULPrototypeScript*, node);
|
||||
*aScriptType = parent->mScriptObject.getScriptTypeID();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NS_WARNING("Unexpected parent node type");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -807,7 +845,7 @@ XULContentSinkImpl::HandleEndElement(const PRUnichar *aName)
|
|||
NS_STATIC_CAST(nsXULPrototypeScript*, node);
|
||||
|
||||
// If given a src= attribute, we must ignore script tag content.
|
||||
if (! script->mSrcURI && ! script->mJSObject) {
|
||||
if (! script->mSrcURI && ! script->mScriptObject) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
|
||||
script->mOutOfLine = PR_FALSE;
|
||||
|
@ -1035,6 +1073,52 @@ XULContentSinkImpl::ReportError(const PRUnichar* aErrorText,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::SetElementScriptType(nsXULPrototypeElement* element,
|
||||
const PRUnichar** aAttributes,
|
||||
const PRUint32 aAttrLen)
|
||||
{
|
||||
// First check if the attributes specify an explicit script type.
|
||||
nsresult rv = NS_OK;
|
||||
PRUint32 i;
|
||||
PRBool found = PR_FALSE;
|
||||
for (i=0;i<aAttrLen;i++) {
|
||||
const nsDependentString key(aAttributes[i*2]);
|
||||
if (key.EqualsLiteral("script-type")) {
|
||||
const nsDependentString value(aAttributes[i*2+1]);
|
||||
if (!value.IsEmpty()) {
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntime(value, getter_AddRefs(runtime));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
element->mScriptTypeID = runtime->GetScriptTypeID();
|
||||
else {
|
||||
// probably just a bad language name (typo, etc)
|
||||
NS_WARNING("Failed to load the node's script language!");
|
||||
// Leave the default language as unknown - we don't want js
|
||||
// trying to execute this stuff.
|
||||
NS_ASSERTION(element->mScriptTypeID == nsIProgrammingLanguage::UNKNOWN,
|
||||
"Default script type should be unknown");
|
||||
}
|
||||
found = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not specified, look at the context stack and use the element
|
||||
// there.
|
||||
if (!found) {
|
||||
if (mContextStack.Depth() == 0) {
|
||||
// This is the root element - default to JS
|
||||
element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
} else {
|
||||
// Ask the top-node for its script type (which has already
|
||||
// had this function called for it - so no need to recurse
|
||||
// until we find it)
|
||||
rv = mContextStack.GetTopNodeScriptType(&element->mScriptTypeID);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULContentSinkImpl::OpenRoot(const PRUnichar** aAttributes,
|
||||
|
@ -1074,6 +1158,10 @@ XULContentSinkImpl::OpenRoot(const PRUnichar** aAttributes,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// Set the correct script-type for the element.
|
||||
rv = SetElementScriptType(element, aAttributes, aAttrLen);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Push the element onto the context stack, so that child
|
||||
// containers will hook up to us as their parent.
|
||||
rv = mContextStack.Push(element, mState);
|
||||
|
@ -1133,11 +1221,19 @@ XULContentSinkImpl::OpenTag(const PRUnichar** aAttributes,
|
|||
|
||||
if (aNodeInfo->Equals(nsHTMLAtoms::script, kNameSpaceID_XHTML) ||
|
||||
aNodeInfo->Equals(nsHTMLAtoms::script, kNameSpaceID_XUL)) {
|
||||
// Do scripty things now. OpenScript will push the
|
||||
// nsPrototypeScriptElement onto the stack, so we're done after this.
|
||||
// Do scripty things now. Set a script language for the element,
|
||||
// even though it is ignored (the nsPrototypeScriptElement
|
||||
// has its own script-type).
|
||||
element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
// OpenScript will push the nsPrototypeScriptElement onto the
|
||||
// stack, so we're done after this.
|
||||
return OpenScript(aAttributes, aLineNumber);
|
||||
}
|
||||
|
||||
// Set the correct script-type for the element.
|
||||
rv = SetElementScriptType(element, aAttributes, aAttrLen);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Push the element onto the context stack, so that child
|
||||
// containers will hook up to us as their parent.
|
||||
rv = mContextStack.Push(element, mState);
|
||||
|
@ -1151,10 +1247,10 @@ nsresult
|
|||
XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
||||
const PRUint32 aLineNumber)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool isJavaScript = PR_TRUE;
|
||||
PRBool hasE4XOption = PR_TRUE;
|
||||
const char* jsVersionString = nsnull;
|
||||
PRUint32 langID;
|
||||
nsresult rv = mContextStack.GetTopNodeScriptType(&langID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PRUint32 version = 0;
|
||||
|
||||
// Look for SRC attribute and look for a LANGUAGE attribute
|
||||
nsAutoString src;
|
||||
|
@ -1176,6 +1272,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
mimeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Javascript keeps the fast path, optimized for most-likely type
|
||||
// Table ordered from most to least likely JS MIME types. For .xul
|
||||
// files that we host, the likeliest type is application/x-javascript.
|
||||
// See bug 62485, feel free to add <script type="..."> survey data to it,
|
||||
|
@ -1189,7 +1286,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
nsnull
|
||||
};
|
||||
|
||||
isJavaScript = PR_FALSE;
|
||||
PRBool isJavaScript = PR_FALSE;
|
||||
for (PRInt32 i = 0; jsTypes[i]; i++) {
|
||||
if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) {
|
||||
isJavaScript = PR_TRUE;
|
||||
|
@ -1198,30 +1295,44 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
}
|
||||
|
||||
if (isJavaScript) {
|
||||
JSVersion jsVersion = JSVERSION_DEFAULT;
|
||||
nsAutoString value;
|
||||
rv = mimeHdrParser->GetParameter(typeAndParams, "version",
|
||||
EmptyCString(), PR_FALSE, nsnull,
|
||||
value);
|
||||
if (NS_FAILED(rv)) {
|
||||
langID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
} else {
|
||||
// Use the script object factory to locate the language.
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime));
|
||||
if (NS_FAILED(rv) || runtime == nsnull) {
|
||||
// Failed to get the explicitly specified language
|
||||
NS_WARNING("Failed to find a scripting language");
|
||||
langID = nsIProgrammingLanguage::UNKNOWN;
|
||||
} else
|
||||
langID = runtime->GetScriptTypeID();
|
||||
}
|
||||
|
||||
if (langID != nsIProgrammingLanguage::UNKNOWN) {
|
||||
// Get the version string, and ensure the language supports it.
|
||||
nsAutoString versionName;
|
||||
rv = mimeHdrParser->GetParameter(typeAndParams, "version",
|
||||
EmptyCString(), PR_FALSE, nsnull,
|
||||
versionName);
|
||||
if (NS_FAILED(rv)) {
|
||||
// no version specified - version remains 0.
|
||||
if (rv != NS_ERROR_INVALID_ARG)
|
||||
return rv;
|
||||
} else {
|
||||
if (value.Length() != 3 || value[0] != '1' || value[1] != '.')
|
||||
jsVersion = JSVERSION_UNKNOWN;
|
||||
else switch (value[2]) {
|
||||
case '0': jsVersion = JSVERSION_1_0; break;
|
||||
case '1': jsVersion = JSVERSION_1_1; break;
|
||||
case '2': jsVersion = JSVERSION_1_2; break;
|
||||
case '3': jsVersion = JSVERSION_1_3; break;
|
||||
case '4': jsVersion = JSVERSION_1_4; break;
|
||||
case '5': jsVersion = JSVERSION_1_5; break;
|
||||
case '6': jsVersion = JSVERSION_1_6; break;
|
||||
default: jsVersion = JSVERSION_UNKNOWN;
|
||||
nsCOMPtr<nsIScriptRuntime> runtime;
|
||||
rv = NS_GetScriptRuntimeByID(langID, getter_AddRefs(runtime));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = runtime->ParseVersion(versionName, &version);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("This script language version is not supported - ignored");
|
||||
langID = nsIProgrammingLanguage::UNKNOWN;
|
||||
}
|
||||
}
|
||||
jsVersionString = ::JS_VersionToString(jsVersion);
|
||||
|
||||
}
|
||||
// Some js specifics yet to be abstracted.
|
||||
if (langID == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
nsAutoString value;
|
||||
rv = mimeHdrParser->GetParameter(typeAndParams, "e4x",
|
||||
EmptyCString(), PR_FALSE, nsnull,
|
||||
value);
|
||||
|
@ -1230,29 +1341,48 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
return rv;
|
||||
} else {
|
||||
if (value.Length() == 1 && value[0] == '0')
|
||||
hasE4XOption = PR_FALSE;
|
||||
// This means that we need to set JSOPTION_XML in the JS
|
||||
// options. We use our implementation knowledge to reuse
|
||||
// JSVERSION_HAS_XML as a safe version flag. If version
|
||||
// has JSVERSION_UNKNOWN (-1), then this is still OK.
|
||||
version |= JSVERSION_HAS_XML;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (key.EqualsLiteral("language")) {
|
||||
// Language is deprecated, and the impl in nsScriptLoader ignores the
|
||||
// various version strings anyway. So we make no attempt to support
|
||||
// languages other than JS for language=
|
||||
nsAutoString lang(aAttributes[1]);
|
||||
isJavaScript =
|
||||
nsParserUtils::IsJavaScriptLanguage(lang, &jsVersionString);
|
||||
if (nsParserUtils::IsJavaScriptLanguage(lang, &version))
|
||||
langID = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
}
|
||||
aAttributes += 2;
|
||||
}
|
||||
|
||||
// Don't process scripts that aren't JavaScript
|
||||
if (isJavaScript) {
|
||||
// Not all script languages have a "sandbox" concept. At time of
|
||||
// writing, Python is the only other language, and it does not.
|
||||
// For such languages, neither any inline script nor remote script are
|
||||
// safe to execute from untrusted sources.
|
||||
// So for such languages, we only allow script when the document
|
||||
// itself is from chrome. We then don't bother to check the
|
||||
// "src=" tag - we trust chrome to do the right thing.
|
||||
// (See also similar code in nsScriptLoader.cpp)
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryReferent(mDocument));
|
||||
if (langID != nsIProgrammingLanguage::UNKNOWN &&
|
||||
langID != nsIProgrammingLanguage::JAVASCRIPT &&
|
||||
doc && !nsContentUtils::IsChromeDoc(doc)) {
|
||||
langID = nsIProgrammingLanguage::UNKNOWN;
|
||||
NS_WARNING("Non JS language called from non chrome - ignored");
|
||||
}
|
||||
// Don't process scripts that aren't known
|
||||
if (langID != nsIProgrammingLanguage::UNKNOWN) {
|
||||
nsIScriptGlobalObject* globalObject = nsnull; // borrowed reference
|
||||
if (doc)
|
||||
globalObject = doc->GetScriptGlobalObject();
|
||||
nsXULPrototypeScript* script =
|
||||
new nsXULPrototypeScript(aLineNumber, jsVersionString, hasE4XOption,
|
||||
&rv);
|
||||
new nsXULPrototypeScript(langID, aLineNumber, version);
|
||||
if (! script)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (NS_FAILED(rv)) {
|
||||
delete script;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If there is a SRC attribute...
|
||||
if (! src.IsEmpty()) {
|
||||
|
@ -1286,15 +1416,8 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
// file right away. Otherwise we'll end up reloading the script and
|
||||
// corrupting the FastLoad file trying to serialize it, in the case
|
||||
// where it's already there.
|
||||
nsCOMPtr<nsIDocument> doc(do_QueryReferent(mDocument));
|
||||
if (doc) {
|
||||
nsIScriptGlobalObject* globalObject = doc->GetScriptGlobalObject();
|
||||
if (globalObject) {
|
||||
nsIScriptContext *scriptContext = globalObject->GetContext();
|
||||
if (scriptContext)
|
||||
script->DeserializeOutOfLine(nsnull, scriptContext);
|
||||
}
|
||||
}
|
||||
if (globalObject)
|
||||
script->DeserializeOutOfLine(nsnull, globalObject);
|
||||
}
|
||||
|
||||
nsVoidArray* children;
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#include "nsContentList.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
@ -642,6 +643,10 @@ nsXULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster,
|
|||
nsCOMPtr<nsIContent> broadcaster = do_QueryInterface(aBroadcaster);
|
||||
nsCOMPtr<nsIContent> listener = do_QueryInterface(aListener);
|
||||
|
||||
// We may be copying event handlers etc, so we must also copy
|
||||
// the script-type to the listener.
|
||||
listener->SetScriptTypeID(broadcaster->GetScriptTypeID());
|
||||
|
||||
if (aAttr.EqualsLiteral("*")) {
|
||||
PRUint32 count = broadcaster->GetAttrCount();
|
||||
while (count-- > 0) {
|
||||
|
@ -2767,9 +2772,9 @@ nsXULDocument::ResumeWalk()
|
|||
if (NS_SUCCEEDED(rv) && blocked)
|
||||
return NS_OK;
|
||||
}
|
||||
else if (scriptproto->mJSObject) {
|
||||
else if (scriptproto->mScriptObject) {
|
||||
// An inline script
|
||||
rv = ExecuteScript(scriptproto->mJSObject);
|
||||
rv = ExecuteScript(scriptproto);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2959,8 +2964,8 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
|
|||
// Load a transcluded script
|
||||
nsresult rv;
|
||||
|
||||
if (aScriptProto->mJSObject) {
|
||||
rv = ExecuteScript(aScriptProto->mJSObject);
|
||||
if (aScriptProto->mScriptObject) {
|
||||
rv = ExecuteScript(aScriptProto);
|
||||
|
||||
// Ignore return value from execution, and don't block
|
||||
*aBlock = PR_FALSE;
|
||||
|
@ -2974,11 +2979,23 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
|
|||
gXULCache->GetEnabled(&useXULCache);
|
||||
|
||||
if (useXULCache) {
|
||||
void *newScriptObject = nsnull;
|
||||
PRUint32 fetchedLang = nsIProgrammingLanguage::UNKNOWN;
|
||||
gXULCache->GetScript(aScriptProto->mSrcURI,
|
||||
NS_REINTERPRET_CAST(void**, &aScriptProto->mJSObject));
|
||||
&fetchedLang,
|
||||
&newScriptObject);
|
||||
if (newScriptObject) {
|
||||
// The script language for a proto must remain constant - we
|
||||
// can't just change it for this unexpected language.
|
||||
if (aScriptProto->mScriptObject.getScriptTypeID() != fetchedLang) {
|
||||
NS_ERROR("XUL cache gave me an incorrect script language");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
aScriptProto->mScriptObject.set(newScriptObject);
|
||||
}
|
||||
|
||||
if (aScriptProto->mJSObject) {
|
||||
rv = ExecuteScript(aScriptProto->mJSObject);
|
||||
if (aScriptProto->mScriptObject) {
|
||||
rv = ExecuteScript(aScriptProto);
|
||||
|
||||
// Ignore return value from execution, and don't block
|
||||
*aBlock = PR_FALSE;
|
||||
|
@ -3069,7 +3086,7 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
// be writing a new FastLoad file. If we were reading this script
|
||||
// from the FastLoad file, XULContentSinkImpl::OpenScript (over in
|
||||
// nsXULContentSink.cpp) would have already deserialized a non-null
|
||||
// script->mJSObject, causing control flow at the top of LoadScript
|
||||
// script->mScriptObject, causing control flow at the top of LoadScript
|
||||
// not to reach here.
|
||||
nsCOMPtr<nsIURI> uri = scriptProto->mSrcURI;
|
||||
|
||||
|
@ -3083,8 +3100,8 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
1, this, mCurrentPrototype);
|
||||
|
||||
aStatus = rv;
|
||||
if (NS_SUCCEEDED(rv) && scriptProto->mJSObject) {
|
||||
rv = ExecuteScript(scriptProto->mJSObject);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ExecuteScript(scriptProto);
|
||||
|
||||
// If the XUL cache is enabled, save the script object there in
|
||||
// case different XUL documents source the same script.
|
||||
|
@ -3112,7 +3129,8 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
|
||||
if (useXULCache && IsChromeURI(mDocumentURI)) {
|
||||
gXULCache->PutScript(scriptProto->mSrcURI,
|
||||
NS_REINTERPRET_CAST(void*, scriptProto->mJSObject));
|
||||
scriptProto->mScriptObject.getScriptTypeID(),
|
||||
scriptProto->mScriptObject);
|
||||
}
|
||||
|
||||
if (mIsWritingFastLoad && mCurrentPrototype != mMasterPrototype) {
|
||||
|
@ -3134,9 +3152,13 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
|
||||
NS_ASSERTION(global != nsnull, "master prototype w/o global?!");
|
||||
if (global) {
|
||||
nsIScriptContext *scriptContext = global->GetContext();
|
||||
PRUint32 stid = scriptProto->mScriptObject.getScriptTypeID();
|
||||
nsIScriptContext *scriptContext = \
|
||||
global->GetScriptContext(stid);
|
||||
NS_ASSERTION(scriptContext != nsnull,
|
||||
"Failed to get script context for language");
|
||||
if (scriptContext)
|
||||
scriptProto->SerializeOutOfLine(nsnull, scriptContext);
|
||||
scriptProto->SerializeOutOfLine(nsnull, global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3162,8 +3184,8 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
doc->mNextSrcLoadWaiter = nsnull;
|
||||
|
||||
// Execute only if we loaded and compiled successfully, then resume
|
||||
if (NS_SUCCEEDED(aStatus) && scriptProto->mJSObject) {
|
||||
doc->ExecuteScript(scriptProto->mJSObject);
|
||||
if (NS_SUCCEEDED(aStatus) && scriptProto->mScriptObject) {
|
||||
doc->ExecuteScript(scriptProto);
|
||||
}
|
||||
doc->ResumeWalk();
|
||||
NS_RELEASE(doc);
|
||||
|
@ -3174,23 +3196,43 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
|
||||
|
||||
nsresult
|
||||
nsXULDocument::ExecuteScript(JSObject* aScriptObject)
|
||||
nsXULDocument::ExecuteScript(nsIScriptContext * aContext, void * aScriptObject)
|
||||
{
|
||||
NS_PRECONDITION(aScriptObject != nsnull, "null ptr");
|
||||
if (! aScriptObject)
|
||||
NS_PRECONDITION(aScriptObject != nsnull && aContext != nsnull, "null ptr");
|
||||
if (! aScriptObject || ! aContext)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Execute the precompiled script with the given version
|
||||
nsresult rv = NS_ERROR_UNEXPECTED;
|
||||
nsresult rv;
|
||||
void *global = mScriptGlobalObject->GetScriptGlobal(
|
||||
aContext->GetScriptTypeID());
|
||||
rv = aContext->ExecuteScript(aScriptObject,
|
||||
global,
|
||||
nsnull, nsnull);
|
||||
|
||||
NS_ASSERTION(mScriptGlobalObject != nsnull, "no script global object");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
if (mScriptGlobalObject && (context = mScriptGlobalObject->GetContext()))
|
||||
rv = context->ExecuteScript(aScriptObject,
|
||||
mScriptGlobalObject->GetGlobalJSObject(),
|
||||
nsnull, nsnull);
|
||||
nsresult
|
||||
nsXULDocument::ExecuteScript(nsXULPrototypeScript *aScript)
|
||||
{
|
||||
NS_PRECONDITION(aScript != nsnull, "null ptr");
|
||||
NS_ENSURE_TRUE(aScript, NS_ERROR_NULL_POINTER);
|
||||
PRUint32 stid = aScript->mScriptObject.getScriptTypeID();
|
||||
|
||||
nsresult rv;
|
||||
rv = mScriptGlobalObject->EnsureScriptEnvironment(stid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptContext *context;
|
||||
context = mScriptGlobalObject->GetScriptContext(stid);
|
||||
// failure getting a script context is fatal.
|
||||
NS_ENSURE_TRUE(context != nsnull, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (aScript->mScriptObject)
|
||||
rv = ExecuteScript(context, aScript->mScriptObject);
|
||||
else
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -3523,7 +3565,14 @@ nsXULDocument::OverlayForwardReference::Resolve()
|
|||
if (! target)
|
||||
return eResolve_Error;
|
||||
|
||||
// While merging, set the default script language of the element to be
|
||||
// the language from the overlay - attributes will then be correctly
|
||||
// hooked up with the appropriate language (while child nodes ignore
|
||||
// the default language - they have it in their proto.
|
||||
PRUint32 oldDefLang = target->GetScriptTypeID();
|
||||
target->SetScriptTypeID(mOverlay->GetScriptTypeID());
|
||||
rv = Merge(target, mOverlay, notify);
|
||||
target->SetScriptTypeID(oldDefLang);
|
||||
if (NS_FAILED(rv)) return eResolve_Error;
|
||||
|
||||
// Add child and any descendants to the element map
|
||||
|
|
|
@ -345,7 +345,13 @@ protected:
|
|||
* Execute the precompiled script object scoped by this XUL document's
|
||||
* containing window object, and using its associated script context.
|
||||
*/
|
||||
nsresult ExecuteScript(JSObject* aScriptObject);
|
||||
nsresult ExecuteScript(nsIScriptContext *aContext, void* aScriptObject);
|
||||
|
||||
/**
|
||||
* Helper method for the above that uses aScript to find the appropriate
|
||||
* script context and object.
|
||||
*/
|
||||
nsresult ExecuteScript(nsXULPrototypeScript *aScript);
|
||||
|
||||
/**
|
||||
* Create a delegate content model element from a prototype.
|
||||
|
@ -385,11 +391,6 @@ protected:
|
|||
static nsresult
|
||||
CreateTemplateBuilder(nsIContent* aElement);
|
||||
|
||||
/**
|
||||
* Do hookup for <xul:observes> tag
|
||||
*/
|
||||
nsresult HookupObserver(nsIContent* aElement);
|
||||
|
||||
/**
|
||||
* Add the current prototype's style sheets to the document.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Benjamin Smedberg <bsmedberg@covad.net>
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -54,8 +55,7 @@
|
|||
#include "nsIXBLDocumentInfo.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXULDocument.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIFastLoadService.h"
|
||||
|
@ -72,6 +72,12 @@
|
|||
#include "nsDataHashtable.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
struct CacheScriptEntry
|
||||
{
|
||||
PRUint32 mScriptTypeID; // the script language ID.
|
||||
void* mScriptObject; // the script object.
|
||||
};
|
||||
|
||||
class nsXULPrototypeCache : public nsIXULPrototypeCache,
|
||||
nsIObserver
|
||||
{
|
||||
|
@ -88,8 +94,8 @@ public:
|
|||
NS_IMETHOD PutStyleSheet(nsICSSStyleSheet* aStyleSheet);
|
||||
NS_IMETHOD FlushStyleSheets();
|
||||
|
||||
NS_IMETHOD GetScript(nsIURI* aURI, void** aScriptObject);
|
||||
NS_IMETHOD PutScript(nsIURI* aURI, void* aScriptObject);
|
||||
NS_IMETHOD GetScript(nsIURI* aURI, PRUint32 *langID, void** aScriptObject);
|
||||
NS_IMETHOD PutScript(nsIURI* aURI, PRUint32 langID, void* aScriptObject);
|
||||
NS_IMETHOD FlushScripts();
|
||||
|
||||
NS_IMETHOD GetXBLDocumentInfo(nsIURI* aURL, nsIXBLDocumentInfo** _result);
|
||||
|
@ -114,15 +120,11 @@ protected:
|
|||
|
||||
void FlushSkinFiles();
|
||||
|
||||
JSRuntime* GetJSRuntime();
|
||||
|
||||
nsInterfaceHashtable<nsURIHashKey,nsIXULPrototypeDocument> mPrototypeTable;
|
||||
nsInterfaceHashtable<nsURIHashKey,nsICSSStyleSheet> mStyleSheetTable;
|
||||
nsDataHashtable<nsURIHashKey,void*> mScriptTable;
|
||||
nsDataHashtable<nsURIHashKey,CacheScriptEntry> mScriptTable;
|
||||
nsInterfaceHashtable<nsURIHashKey,nsIXBLDocumentInfo> mXBLDocTable;
|
||||
|
||||
JSRuntime* mJSRuntime;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FastLoad
|
||||
// this is really a hash set, with a dummy data parameter
|
||||
|
@ -164,7 +166,6 @@ nsIFastLoadService* nsXULPrototypeCache::gFastLoadService = nsnull;
|
|||
nsIFile* nsXULPrototypeCache::gFastLoadFile = nsnull;
|
||||
|
||||
nsXULPrototypeCache::nsXULPrototypeCache()
|
||||
: mJSRuntime(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -298,18 +299,6 @@ nsXULPrototypeCache::PutPrototype(nsIXULPrototypeDocument* aDocument)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
JSRuntime*
|
||||
nsXULPrototypeCache::GetJSRuntime()
|
||||
{
|
||||
if (!mJSRuntime) {
|
||||
nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
if (rtsvc)
|
||||
rtsvc->GetRuntime(&mJSRuntime);
|
||||
}
|
||||
|
||||
return mJSRuntime;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeCache::FlushPrototypes()
|
||||
{
|
||||
|
@ -351,30 +340,46 @@ nsXULPrototypeCache::FlushStyleSheets()
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeCache::GetScript(nsIURI* aURI, void** aScriptObject)
|
||||
nsXULPrototypeCache::GetScript(nsIURI* aURI, PRUint32 *aLangID,
|
||||
void** aScriptObject)
|
||||
{
|
||||
if (!mScriptTable.Get(aURI, aScriptObject))
|
||||
CacheScriptEntry entry;
|
||||
if (!mScriptTable.Get(aURI, &entry)) {
|
||||
*aLangID = nsIProgrammingLanguage::UNKNOWN;
|
||||
*aScriptObject = nsnull;
|
||||
|
||||
} else {
|
||||
*aScriptObject = entry.mScriptObject;
|
||||
*aLangID = entry.mScriptTypeID;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULPrototypeCache::PutScript(nsIURI* aURI, void* aScriptObject)
|
||||
nsXULPrototypeCache::PutScript(nsIURI* aURI, PRUint32 aLangID, void* aScriptObject)
|
||||
{
|
||||
NS_ENSURE_TRUE(mScriptTable.Put(aURI, aScriptObject), NS_ERROR_OUT_OF_MEMORY);
|
||||
CacheScriptEntry entry = {aLangID, aScriptObject};
|
||||
|
||||
NS_ENSURE_TRUE(mScriptTable.Put(aURI, entry), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Lock the object from being gc'd until it is removed from the cache
|
||||
JS_LockGCThingRT(GetJSRuntime(), aScriptObject);
|
||||
return NS_OK;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> rt;
|
||||
rv = NS_GetScriptRuntimeByID(aLangID, getter_AddRefs(rt));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = rt->HoldScriptObject(aScriptObject);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to GC lock the object");
|
||||
// On failure doing the lock, we should remove the map entry?
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
ReleaseJSObjectCallback(nsIURI* aKey, void* &aData, void* aClosure)
|
||||
ReleaseScriptObjectCallback(nsIURI* aKey, CacheScriptEntry &aData, void* aClosure)
|
||||
{
|
||||
JS_UnlockGCThingRT((JSRuntime*) aClosure, aData);
|
||||
nsCOMPtr<nsIScriptRuntime> rt;
|
||||
if (NS_SUCCEEDED(NS_GetScriptRuntimeByID(aData.mScriptTypeID, getter_AddRefs(rt))))
|
||||
rt->DropScriptObject(aData.mScriptObject);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
|
@ -382,7 +387,8 @@ NS_IMETHODIMP
|
|||
nsXULPrototypeCache::FlushScripts()
|
||||
{
|
||||
// This callback will unlock each object so it can once again be gc'd.
|
||||
mScriptTable.Enumerate(ReleaseJSObjectCallback, (void*) GetJSRuntime());
|
||||
// XXX - this might be slow - we fetch the runtime each and every object.
|
||||
mScriptTable.Enumerate(ReleaseScriptObjectCallback, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
* Chris Waterson <waterson@netscape.com>
|
||||
* L. David Baron <dbaron@dbaron.org>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -54,8 +55,10 @@
|
|||
#include "nsIScriptGlobalObjectOwner.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsISupportsArray.h" // deprecated array interface.
|
||||
#include "nsIArray.h" // blessed array interface.
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXULPrototypeDocument.h"
|
||||
|
@ -70,6 +73,7 @@
|
|||
#include "nsNodeInfoManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
@ -85,14 +89,17 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIScriptGlobalObject methods
|
||||
virtual void SetContext(nsIScriptContext *aContext);
|
||||
virtual nsIScriptContext *GetContext();
|
||||
virtual void SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
|
||||
virtual nsIScriptGlobalObjectOwner *GetGlobalObjectOwner();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
virtual void OnFinalize(JSObject *aObject);
|
||||
virtual void OnFinalize(PRUint32 aLangID, void *aGlobal);
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||
virtual nsresult SetNewArguments(PRUint32 aArgc, void* aArgv);
|
||||
virtual nsresult SetNewArguments(nsIArray *aArguments);
|
||||
|
||||
virtual void *GetScriptGlobal(PRUint32 lang);
|
||||
virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID);
|
||||
|
||||
virtual nsIScriptContext *GetScriptContext(PRUint32 lang);
|
||||
virtual nsresult SetScriptContext(PRUint32 language, nsIScriptContext *ctx);
|
||||
|
||||
// nsIScriptObjectPrincipal methods
|
||||
virtual nsIPrincipal* GetPrincipal();
|
||||
|
@ -100,11 +107,11 @@ public:
|
|||
protected:
|
||||
virtual ~nsXULPDGlobalObject();
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContext;
|
||||
JSObject *mJSObject; // XXX JS language rabies bigotry badness
|
||||
|
||||
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mScriptContexts[NS_STID_ARRAY_UBOUND];
|
||||
void * mScriptGlobals[NS_STID_ARRAY_UBOUND];
|
||||
|
||||
static JSClass gSharedGlobalClass;
|
||||
};
|
||||
|
||||
|
@ -194,7 +201,7 @@ nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj)
|
|||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
|
||||
|
||||
if (sgo) {
|
||||
sgo->OnFinalize(obj);
|
||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
||||
}
|
||||
|
||||
// The addref was part of JSObject construction
|
||||
|
@ -255,8 +262,8 @@ nsXULPrototypeDocument::Init()
|
|||
nsXULPrototypeDocument::~nsXULPrototypeDocument()
|
||||
{
|
||||
if (mGlobalObject) {
|
||||
mGlobalObject->SetContext(nsnull); // remove circular reference
|
||||
mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case
|
||||
// cleaup cycles etc.
|
||||
mGlobalObject->SetGlobalObjectOwner(nsnull);
|
||||
}
|
||||
|
||||
if (mRoot)
|
||||
|
@ -393,10 +400,6 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
|
|||
if (! mRoot)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsIScriptContext *scriptContext = mGlobalObject->GetContext();
|
||||
NS_ASSERTION(scriptContext != nsnull,
|
||||
"no prototype script context!");
|
||||
|
||||
// nsINodeInfo table
|
||||
nsCOMArray<nsINodeInfo> nodeInfos;
|
||||
|
||||
|
@ -419,7 +422,7 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
|
|||
if ((nsXULPrototypeNode::Type)type != nsXULPrototypeNode::eType_Element)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv |= mRoot->Deserialize(aStream, scriptContext, mURI, &nodeInfos);
|
||||
rv |= mRoot->Deserialize(aStream, mGlobalObject, mURI, &nodeInfos);
|
||||
rv |= NotifyLoadDone();
|
||||
|
||||
return rv;
|
||||
|
@ -532,10 +535,8 @@ nsXULPrototypeDocument::Write(nsIObjectOutputStream* aStream)
|
|||
nsIScriptGlobalObject* globalObject = GetScriptGlobalObject();
|
||||
NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsIScriptContext *scriptContext = globalObject->GetContext();
|
||||
|
||||
if (mRoot)
|
||||
rv |= mRoot->Serialize(aStream, scriptContext, &nodeInfos);
|
||||
rv |= mRoot->Serialize(aStream, globalObject, &nodeInfos);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -768,9 +769,9 @@ nsXULPrototypeDocument::GetScriptGlobalObject()
|
|||
//
|
||||
|
||||
nsXULPDGlobalObject::nsXULPDGlobalObject()
|
||||
: mJSObject(nsnull),
|
||||
mGlobalObjectOwner(nsnull)
|
||||
: mGlobalObjectOwner(nsnull)
|
||||
{
|
||||
memset(mScriptGlobals, 0, sizeof(mScriptGlobals));
|
||||
}
|
||||
|
||||
|
||||
|
@ -792,51 +793,129 @@ NS_INTERFACE_MAP_END
|
|||
// nsIScriptGlobalObject methods
|
||||
//
|
||||
|
||||
void
|
||||
nsXULPDGlobalObject::SetContext(nsIScriptContext *aContext)
|
||||
nsresult
|
||||
nsXULPDGlobalObject::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptContext)
|
||||
{
|
||||
mScriptContext = aContext;
|
||||
// almost a clone of nsGlobalWindow
|
||||
nsresult rv;
|
||||
|
||||
PRBool ok = NS_STID_VALID(lang_id);
|
||||
NS_ASSERTION(ok, "Invalid programming language ID requested");
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG);
|
||||
PRUint32 lang_ndx = NS_STID_INDEX(lang_id);
|
||||
|
||||
if (!aScriptContext)
|
||||
NS_WARNING("Possibly early removal of script object, see bug #41608");
|
||||
else {
|
||||
// should probably assert the context is clean???
|
||||
aScriptContext->WillInitializeContext();
|
||||
// NOTE: We init this context with a NULL global - this is subtly
|
||||
// different than nsGlobalWindow which passes 'this'
|
||||
rv = aScriptContext->InitContext(nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsIScriptContext *existing;
|
||||
existing = mScriptContexts[lang_ndx];
|
||||
NS_ASSERTION(!aScriptContext || !existing, "Bad call to SetContext()!");
|
||||
|
||||
if (existing)
|
||||
existing->SetOwner(nsnull);
|
||||
void *script_glob = nsnull;
|
||||
|
||||
if (aScriptContext) {
|
||||
aScriptContext->DidInitializeContext();
|
||||
script_glob = aScriptContext->GetNativeGlobal();
|
||||
NS_ASSERTION(script_glob, "GetNativeGlobal returned NULL!");
|
||||
}
|
||||
mScriptContexts[lang_ndx] = aScriptContext;
|
||||
mScriptGlobals[lang_ndx] = script_glob;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsIScriptContext *
|
||||
nsXULPDGlobalObject::GetContext()
|
||||
nsresult
|
||||
nsXULPDGlobalObject::EnsureScriptEnvironment(PRUint32 lang_id)
|
||||
{
|
||||
// This whole fragile mess is predicated on the fact that
|
||||
// GetContext() will be called before GetScriptObject() is.
|
||||
if (! mScriptContext) {
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory =
|
||||
do_GetService(kDOMScriptObjectFactoryCID);
|
||||
NS_ENSURE_TRUE(factory, nsnull);
|
||||
PRBool ok = NS_STID_VALID(lang_id);
|
||||
NS_ASSERTION(ok, "Invalid programming language ID requested");
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG);
|
||||
PRUint32 lang_ndx = NS_STID_INDEX(lang_id);
|
||||
|
||||
nsresult rv =
|
||||
factory->NewScriptContext(nsnull, getter_AddRefs(mScriptContext));
|
||||
if (NS_FAILED(rv))
|
||||
return nsnull;
|
||||
if (mScriptContexts[lang_ndx] == nsnull) {
|
||||
nsresult rv;
|
||||
NS_ASSERTION(mScriptGlobals[lang_ndx] == nsnull, "Have global without context?");
|
||||
|
||||
JSContext *cx = (JSContext *)mScriptContext->GetNativeContext();
|
||||
nsCOMPtr<nsIScriptRuntime> languageRuntime;
|
||||
rv = NS_GetScriptRuntimeByID(lang_id, getter_AddRefs(languageRuntime));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
nsCOMPtr<nsIScriptContext> ctxNew;
|
||||
rv = languageRuntime->CreateContext(getter_AddRefs(ctxNew));
|
||||
// For JS, we have to setup a special global object. We do this then
|
||||
// attach it as the global for this context. Then, ::SetScriptContext
|
||||
// will re-fetch the global and set it up in our language globals array.
|
||||
if (lang_id == nsIProgrammingLanguage::JAVASCRIPT) {
|
||||
// some special JS specific code we should abstract
|
||||
JSContext *cx = (JSContext *)ctxNew->GetNativeContext();
|
||||
JSAutoRequest ar(cx);
|
||||
JSObject *newGlob = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
|
||||
if (!newGlob)
|
||||
return nsnull;
|
||||
|
||||
mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull);
|
||||
if (!mJSObject)
|
||||
return nsnull;
|
||||
::JS_SetGlobalObject(cx, newGlob);
|
||||
|
||||
::JS_SetGlobalObject(cx, mJSObject);
|
||||
|
||||
// Add an owning reference from JS back to us. This'll be
|
||||
// released when the JSObject is finalized.
|
||||
::JS_SetPrivate(cx, mJSObject, this);
|
||||
NS_ADDREF(this);
|
||||
// Add an owning reference from JS back to us. This'll be
|
||||
// released when the JSObject is finalized.
|
||||
::JS_SetPrivate(cx, newGlob, this);
|
||||
NS_ADDREF(this);
|
||||
}
|
||||
|
||||
return mScriptContext;
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
rv = SetScriptContext(lang_id, ctxNew);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScriptContext *
|
||||
nsXULPDGlobalObject::GetScriptContext(PRUint32 lang_id)
|
||||
{
|
||||
// This global object creates a context on demand - do that now.
|
||||
nsresult rv = EnsureScriptEnvironment(lang_id);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to setup script language");
|
||||
return nsnull;
|
||||
}
|
||||
// Note that EnsureScriptEnvironment has validated lang_id
|
||||
return mScriptContexts[NS_STID_INDEX(lang_id)];
|
||||
}
|
||||
|
||||
void *
|
||||
nsXULPDGlobalObject::GetScriptGlobal(PRUint32 lang_id)
|
||||
{
|
||||
PRBool ok = NS_STID_VALID(lang_id);
|
||||
NS_ASSERTION(ok, "Invalid programming language ID requested");
|
||||
NS_ENSURE_TRUE(ok, nsnull);
|
||||
PRUint32 lang_ndx = NS_STID_INDEX(lang_id);
|
||||
|
||||
NS_ASSERTION(mScriptContexts[lang_ndx] != nsnull, "Querying for global before setting up context?");
|
||||
return mScriptGlobals[lang_ndx];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXULPDGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner)
|
||||
{
|
||||
if (aOwner == nsnull) {
|
||||
// this means we should cleanup
|
||||
PRUint32 lang_ndx;
|
||||
NS_STID_FOR_INDEX(lang_ndx) {
|
||||
if (mScriptContexts[lang_ndx]) {
|
||||
mScriptContexts[lang_ndx]->FinalizeContext();
|
||||
mScriptContexts[lang_ndx] = nsnull;
|
||||
}
|
||||
}
|
||||
}
|
||||
mGlobalObjectOwner = aOwner; // weak reference
|
||||
}
|
||||
|
||||
|
@ -848,29 +927,13 @@ nsXULPDGlobalObject::GetGlobalObjectOwner()
|
|||
}
|
||||
|
||||
|
||||
JSObject *
|
||||
nsXULPDGlobalObject::GetGlobalJSObject()
|
||||
{
|
||||
// The prototype document has its own special secret script object
|
||||
// that can be used to compile scripts and event handlers.
|
||||
|
||||
if (!mScriptContext)
|
||||
return nsnull;
|
||||
|
||||
JSContext* cx = NS_REINTERPRET_CAST(JSContext*,
|
||||
mScriptContext->GetNativeContext());
|
||||
if (!cx)
|
||||
return nsnull;
|
||||
|
||||
return ::JS_GetGlobalObject(cx);
|
||||
}
|
||||
|
||||
void
|
||||
nsXULPDGlobalObject::OnFinalize(JSObject *aObject)
|
||||
nsXULPDGlobalObject::OnFinalize(PRUint32 aLangID, void *aObject)
|
||||
{
|
||||
NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!");
|
||||
|
||||
mJSObject = nsnull;
|
||||
NS_ASSERTION(NS_STID_VALID(aLangID), "Invalid language ID");
|
||||
NS_ASSERTION(aObject == mScriptGlobals[NS_STID_INDEX(aLangID)],
|
||||
"Wrong object finalized!");
|
||||
mScriptGlobals[NS_STID_INDEX(aLangID)] = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -880,7 +943,7 @@ nsXULPDGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXULPDGlobalObject::SetNewArguments(PRUint32 aArgc, void* aArgv)
|
||||
nsXULPDGlobalObject::SetNewArguments(nsIArray *aArguments)
|
||||
{
|
||||
NS_NOTREACHED("waaah!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
// we want to explore making the document own the load group
|
||||
// so we can associate the document URI with the load group.
|
||||
|
@ -8320,13 +8321,12 @@ nsDocShell::EnsureScriptEnvironment()
|
|||
SetGlobalObjectOwner(NS_STATIC_CAST
|
||||
(nsIScriptGlobalObjectOwner *, this));
|
||||
|
||||
nsCOMPtr<nsIScriptContext> context;
|
||||
factory->NewScriptContext(mScriptGlobal, getter_AddRefs(context));
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
|
||||
|
||||
// Note that mScriptGlobal has taken a reference to the script
|
||||
// context, so we don't have to.
|
||||
|
||||
// Ensure the script object is set to run javascript - other languages
|
||||
// setup on demand.
|
||||
// XXXmarkh - should this be setup to run the default language for this doc?
|
||||
nsresult rv;
|
||||
rv = mScriptGlobal->EnsureScriptEnvironment(nsIProgrammingLanguage::JAVASCRIPT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,12 @@ XPIDLSRCS = nsIScriptContextOwner.idl \
|
|||
|
||||
EXPORTS=nsIScriptContext.h \
|
||||
nsIJSNativeInitializer.h \
|
||||
nsIScriptRuntime.h \
|
||||
nsIScriptObjectOwner.h \
|
||||
nsIScriptObjectPrincipal.h \
|
||||
nsIScriptGlobalObject.h \
|
||||
nsIScriptGlobalObjectOwner.h \
|
||||
nsIScriptTimeoutHandler.h \
|
||||
nsIDOMScriptObjectFactory.h \
|
||||
nsDOMCID.h \
|
||||
nsIScriptExternalNameSet.h \
|
||||
|
@ -67,6 +69,8 @@ EXPORTS=nsIScriptContext.h \
|
|||
nsDOMClassInfoID.h \
|
||||
nsIBaseDOMException.h \
|
||||
nsDOMString.h \
|
||||
nsDOMJSUtils.h \
|
||||
nsDOMScriptObjectHolder.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -67,12 +67,14 @@ enum PopupControlState {
|
|||
class nsIDocShell;
|
||||
class nsIFocusController;
|
||||
class nsIDocument;
|
||||
class nsIScriptTimeoutHandler;
|
||||
class nsPresContext;
|
||||
struct nsTimeout;
|
||||
|
||||
#define NS_PIDOMWINDOW_IID \
|
||||
{ 0xad6640fb, 0x575e, 0x4bfe, \
|
||||
{ 0x92, 0x92, 0xe6, 0x36, 0xfb, 0xee, 0xff, 0x3d } }
|
||||
{ /* {D0A82BF8-969B-4092-8FE7-D885622DA5BF} */ \
|
||||
0xd0a82bf8, 0x969b, 0x4092, \
|
||||
{ 0x8f, 0xe7, 0xd8, 0x85, 0x62, 0x2d, 0xa5, 0xbf } }
|
||||
|
||||
class nsPIDOMWindow : public nsIDOMWindowInternal
|
||||
{
|
||||
|
@ -267,6 +269,14 @@ public:
|
|||
// the window was frozen.
|
||||
virtual nsresult FireDelayedDOMEvents() = 0;
|
||||
|
||||
// Add a timeout to this window.
|
||||
virtual nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
PRInt32 interval,
|
||||
PRBool aIsInterval, PRInt32 *aReturn) = 0;
|
||||
|
||||
// Clear a timeout from this window.
|
||||
virtual nsresult ClearTimeoutOrInterval(PRInt32 aTimerID) = 0;
|
||||
|
||||
nsPIDOMWindow *GetOuterWindow()
|
||||
{
|
||||
return mIsInnerWindow ? mOuterWindow : this;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
* the Document Object Model.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(6cbbbf64-212f-4ef8-9ad4-7240dbb8d6ac)]
|
||||
[scriptable, uuid(37CA0054-C715-42df-83C7-35C69E24A632)]
|
||||
interface nsIDOMNSEventTarget : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -68,4 +68,16 @@ interface nsIDOMNSEventTarget : nsISupports
|
|||
in nsIDOMEventListener listener,
|
||||
in boolean useCapture,
|
||||
in boolean wantsUntrusted);
|
||||
|
||||
/**
|
||||
* The default script type (language) for events firing on this target.
|
||||
* Must be one of the nsIProgrammingLanguage enums, but must not be
|
||||
* nsIProgrammingLanguage::UNKNOWN. Most implementations will provide
|
||||
* a default type of nsIProgrammingLanguage::JAVASCRIPT.
|
||||
*
|
||||
* All targets must support fetching the script language, but not all
|
||||
* script targets must support changing it - ie, some targets may only
|
||||
* support event handlers written in their default language.
|
||||
*/
|
||||
attribute PRUint32 scriptTypeID;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
#ifndef nsDOMJSUtils_h__
|
||||
#define nsDOMJSUtils_h__
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
// seems like overkill for just this 1 function - but let's see what else
|
||||
// falls out first.
|
||||
inline nsIScriptContext *
|
||||
GetScriptContextFromJSContext(JSContext *cx)
|
||||
{
|
||||
if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scx =
|
||||
do_QueryInterface(NS_STATIC_CAST(nsISupports *,
|
||||
::JS_GetContextPrivate(cx)));
|
||||
|
||||
// This will return a pointer to something that's about to be
|
||||
// released, but that's ok here.
|
||||
return scx;
|
||||
}
|
||||
|
||||
// A factory function for turning a jsval argv into an nsIArray
|
||||
// but also supports an effecient way of extracting the original argv.
|
||||
// Bug 312003 describes why this must be "void *", but argv will be cast to
|
||||
// jsval* and the args are found at:
|
||||
// ((jsval*)aArgv)[0], ..., ((jsval*)aArgv)[aArgc - 1]
|
||||
// The resulting object will take a copy of the array, and ensure each
|
||||
// element is rooted.
|
||||
// Optionally, aArgv may be NULL, in which case the array is allocated and
|
||||
// rooted, but all items remain NULL. This presumably means the caller will
|
||||
// then QI us for nsIJSArgArray, and set our array elements.
|
||||
nsresult NS_CreateJSArgv(JSContext *aContext, PRUint32 aArgc, void *aArgv,
|
||||
nsIArray **aArray);
|
||||
|
||||
#endif // nsDOMJSUtils_h__
|
|
@ -0,0 +1,231 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 ***** */
|
||||
|
||||
#ifndef nsDOMScriptObjectHolder_h__
|
||||
#define nsDOMScriptObjectHolder_h__
|
||||
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
|
||||
// Drop a reference to a script object when all you have is the script
|
||||
// language ID.
|
||||
inline nsresult NS_DropScriptObject(PRUint32 aLangID, void *aThing)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> scriptRT;
|
||||
NS_DEFINE_CID(cid, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(cid, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = factory->GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRT));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = scriptRT->DropScriptObject(aThing);
|
||||
if (NS_FAILED(rv))
|
||||
NS_ERROR("Failed to drop the script object");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Hold a reference to a script object when all you have is the script
|
||||
// language ID, and you need to take a copy of the void script object.
|
||||
// Must be matched by an NS_DropScriptObject
|
||||
inline nsresult NS_HoldScriptObject(PRUint32 aLangID, void *aThing)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> scriptRT;
|
||||
NS_DEFINE_CID(cid, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(cid, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = factory->GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRT));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = scriptRT->HoldScriptObject(aThing);
|
||||
if (NS_FAILED(rv))
|
||||
NS_ERROR("Failed to hold the script object");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// A thin class used to help with script object memory management. No virtual
|
||||
// functions and a fully inline implementation should keep the cost down.
|
||||
// [Note that a fully inline implementation is necessary for use by other
|
||||
// languages, which do not link against the layout component module]
|
||||
class nsScriptObjectHolder {
|
||||
public:
|
||||
// A constructor that will cause a reference to |ctx| to be stored in
|
||||
// the object. Only use for short-lived object holders.
|
||||
nsScriptObjectHolder(nsIScriptContext *ctx, void *aObject = nsnull) :
|
||||
mObject(aObject), mContextOrLangID(NS_REINTERPRET_CAST(PtrBits, ctx)) {
|
||||
NS_ASSERTION(ctx, "Must provide a valid context");
|
||||
NS_ADDREF(ctx);
|
||||
}
|
||||
|
||||
// A constructor that stores only the integer language ID - freeing the
|
||||
// script object is slower in this case, but is safe for long-lived
|
||||
// object holders.
|
||||
nsScriptObjectHolder(PRUint32 aLangID, void *aObject = nsnull) :
|
||||
mObject(aObject),
|
||||
mContextOrLangID((aLangID << 1) | SOH_HAS_LANGID_BIT) {
|
||||
NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
|
||||
"Please supply a valid language ID");
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
nsScriptObjectHolder(const nsScriptObjectHolder& other) :
|
||||
mObject(other.mObject),
|
||||
mContextOrLangID(other.mContextOrLangID)
|
||||
{
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
if (mObject) {
|
||||
NS_HoldScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
}
|
||||
} else {
|
||||
// New hold the script object and new reference on the script context.
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost context pointer?");
|
||||
NS_ADDREF(ctx);
|
||||
if (mObject)
|
||||
ctx->HoldScriptObject(mObject);
|
||||
}
|
||||
}
|
||||
|
||||
~nsScriptObjectHolder() {
|
||||
// If we have a language ID, then we only need to NS_DropScriptObject if
|
||||
// we are holding a script object.
|
||||
// If we have a script context, we must always release our reference to it,
|
||||
// even if we are not holding a script object.
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
if (mObject) {
|
||||
NS_DropScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
}
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost context pointer?");
|
||||
if (mObject) {
|
||||
ctx->DropScriptObject(mObject);
|
||||
}
|
||||
NS_IF_RELEASE(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// misc operators
|
||||
nsScriptObjectHolder &operator=(const nsScriptObjectHolder &other) {
|
||||
set(other);
|
||||
return *this;
|
||||
}
|
||||
PRBool operator!() const {
|
||||
return !mObject;
|
||||
}
|
||||
operator void *() const {
|
||||
return mObject;
|
||||
}
|
||||
|
||||
// Drop the script object - but *not* the nsIScriptContext nor the language
|
||||
// ID.
|
||||
nsresult drop() {
|
||||
nsresult rv = NS_OK;
|
||||
if (mObject) {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
rv = NS_DropScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost ctx pointer!");
|
||||
rv = ctx->DropScriptObject(mObject);
|
||||
}
|
||||
mObject = nsnull;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
nsresult set(void *object) {
|
||||
NS_ASSERTION(getScriptTypeID() != nsIProgrammingLanguage::UNKNOWN,
|
||||
"Must know the language!");
|
||||
nsresult rv = drop();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (object) {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
rv = NS_HoldScriptObject(getScriptTypeIDFromBits(), object);
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
rv = ctx->HoldScriptObject(object);
|
||||
}
|
||||
// don't store the pointer if we failed to lock it.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mObject = object;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
nsresult set(const nsScriptObjectHolder &other) {
|
||||
NS_ASSERTION(getScriptTypeID() == other.getScriptTypeID(),
|
||||
"Must have identical languages!");
|
||||
nsresult rv = drop();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return set(other.mObject);
|
||||
}
|
||||
// Get the language ID.
|
||||
PRUint32 getScriptTypeID() const {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
return getScriptTypeIDFromBits();
|
||||
}
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "How did I lose my pointer?");
|
||||
return ctx->GetScriptTypeID();
|
||||
}
|
||||
protected:
|
||||
PRUint32 getScriptTypeIDFromBits() const {
|
||||
NS_ASSERTION(mContextOrLangID & SOH_HAS_LANGID_BIT, "Not in the bits!");
|
||||
return (mContextOrLangID & ~SOH_HAS_LANGID_BIT) >> 1;
|
||||
}
|
||||
void *mObject;
|
||||
// We store either an nsIScriptContext* if this bit is clear,
|
||||
// else the language ID (specifically, ((lang_id << 1) | SOH_HAS_LANGID_BIT)
|
||||
// when set.
|
||||
typedef PRWord PtrBits;
|
||||
enum { SOH_HAS_LANGID_BIT = 0x1 };
|
||||
|
||||
PtrBits mContextOrLangID;
|
||||
};
|
||||
|
||||
#endif // nsDOMScriptObjectHolder_h__
|
|
@ -43,19 +43,35 @@
|
|||
#include "nsString.h"
|
||||
|
||||
#define NS_IDOM_SCRIPT_OBJECT_FACTORY_IID \
|
||||
{ 0xbac2482a, 0x456e, 0x4ea5, \
|
||||
{ 0x83, 0xfb, 0x16, 0xe1, 0x24, 0x9c, 0x16, 0x6f } }
|
||||
{ /* {38EC7717-6CBE-44a8-B2BB-53F2BA998B31} */ \
|
||||
0x38ec7717, 0x6cbe, 0x44a8, \
|
||||
{ 0xb2, 0xbb, 0x53, 0xf2, 0xba, 0x99, 0x8b, 0x31 } }
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIScriptRuntime;
|
||||
class nsIDOMEventListener;
|
||||
|
||||
class nsIDOMScriptObjectFactory : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOM_SCRIPT_OBJECT_FACTORY_IID)
|
||||
|
||||
NS_IMETHOD NewScriptContext(nsIScriptGlobalObject *aGlobal,
|
||||
nsIScriptContext **aContext) = 0;
|
||||
// Get a script language given its "name" (ie, the mime-type)
|
||||
// Note that to fetch javascript from this function, you must currently
|
||||
// use the name "application/javascript" (but also note that all existing
|
||||
// callers of this function optimize the detection of JS, so do not
|
||||
// ask this function for JS)
|
||||
NS_IMETHOD GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aLanguage) = 0;
|
||||
|
||||
// Get a script language given its nsIProgrammingLanguage ID.
|
||||
NS_IMETHOD GetScriptRuntimeByID(PRUint32 aScriptTypeID,
|
||||
nsIScriptRuntime **aLanguage) = 0;
|
||||
|
||||
// Get the ID for a language given its name - but like GetScriptRuntime,
|
||||
// only "application/javascript" is currently supported for JS.
|
||||
NS_IMETHOD GetIDForScriptType(const nsAString &aLanguageName,
|
||||
PRUint32 *aScriptTypeID) = 0;
|
||||
|
||||
NS_IMETHOD NewScriptGlobalObject(PRBool aIsChrome,
|
||||
nsIScriptGlobalObject **aGlobal) = 0;
|
||||
|
|
|
@ -43,29 +43,42 @@
|
|||
class nsIScriptObjectOwner;
|
||||
class nsIDOMEventListener;
|
||||
class nsIAtom;
|
||||
struct JSObject;
|
||||
|
||||
#define NS_IJSEVENTLISTENER_IID \
|
||||
{ 0xa6cf9118, 0x15b3, 0x11d2, \
|
||||
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
|
||||
|
||||
// Implemented by JS event listeners. Used to retrieve the
|
||||
// JSObject corresponding to the event target.
|
||||
// Implemented by script event listeners. Used to retrieve the
|
||||
// script object corresponding to the event target.
|
||||
// (Note this interface is now used to store script objects for all
|
||||
// script languages, so is no longer JS specific)
|
||||
class nsIJSEventListener : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
|
||||
|
||||
nsIJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject,
|
||||
nsIJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
|
||||
nsISupports *aTarget)
|
||||
: mContext(aContext), mScopeObject(aScopeObject), mTarget(aTarget)
|
||||
: mContext(aContext), mScopeObject(aScopeObject), mTarget(nsnull)
|
||||
{
|
||||
// mTarget is a weak reference. We are guaranteed because of the
|
||||
// ownership model that the target will be freed (and the
|
||||
// references dropped) before either the context or the owner goes
|
||||
// away.
|
||||
|
||||
NS_IF_ADDREF(mContext);
|
||||
// We keep a weak-ref to the event target to prevent cycles that prevent
|
||||
// GC from cleaning up our global in all cases. However, as this is a
|
||||
// weak-ref, we must ensure it is the identity of the event target and
|
||||
// not a "tear-off" or similar that may not live as long as we expect.
|
||||
aTarget->QueryInterface(NS_GET_IID(nsISupports),
|
||||
NS_REINTERPRET_CAST(void **, &mTarget));
|
||||
if (mTarget)
|
||||
// We keep a weak-ref, so remove the reference the QI added.
|
||||
mTarget->Release();
|
||||
else {
|
||||
NS_ERROR("Failed to get identity pointer");
|
||||
}
|
||||
// To help debug such leaks, we keep a counter of the event listeners
|
||||
// currently alive. If you change |mTarget| to a strong-ref, this never
|
||||
// hits zero (running seamonkey.)
|
||||
#ifdef NS_DEBUG
|
||||
PR_AtomicIncrement(&sNumJSEventListeners);
|
||||
#endif
|
||||
}
|
||||
|
||||
nsIScriptContext *GetEventContext()
|
||||
|
@ -78,29 +91,34 @@ public:
|
|||
return mTarget;
|
||||
}
|
||||
|
||||
JSObject *GetEventScope()
|
||||
void *GetEventScope()
|
||||
{
|
||||
return mScopeObject;
|
||||
}
|
||||
|
||||
virtual void SetEventName(nsIAtom* aName) = 0;
|
||||
|
||||
protected:
|
||||
~nsIJSEventListener()
|
||||
{
|
||||
NS_IF_RELEASE(mContext);
|
||||
}
|
||||
#ifdef NS_DEBUG
|
||||
static PRInt32 sNumJSEventListeners;
|
||||
#endif
|
||||
|
||||
nsIScriptContext *mContext;
|
||||
JSObject *mScopeObject;
|
||||
nsISupports *mTarget;
|
||||
protected:
|
||||
virtual ~nsIJSEventListener()
|
||||
{
|
||||
#ifdef NS_DEBUG
|
||||
PR_AtomicDecrement(&sNumJSEventListeners);
|
||||
#endif
|
||||
}
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
void *mScopeObject;
|
||||
nsISupports *mTarget; // weak ref.
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
|
||||
|
||||
/* factory function */
|
||||
nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject, nsISupports *aObject,
|
||||
void *aScopeObject, nsISupports *aObject,
|
||||
nsIDOMEventListener **aReturn);
|
||||
|
||||
#endif // nsIJSEventListener_h__
|
||||
|
|
|
@ -42,20 +42,26 @@
|
|||
#include "nsStringGlue.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
class nsIScriptGlobalObject;
|
||||
class nsIScriptSecurityManager;
|
||||
class nsIScriptContextOwner;
|
||||
class nsIPrincipal;
|
||||
class nsIAtom;
|
||||
class nsIArray;
|
||||
class nsIVariant;
|
||||
class nsIObjectInputStream;
|
||||
class nsIObjectOutputStream;
|
||||
class nsScriptObjectHolder;
|
||||
class nsIDOMDocument;
|
||||
|
||||
typedef void (*nsScriptTerminationFunc)(nsISupports* aRef);
|
||||
|
||||
#define NS_ISCRIPTCONTEXT_IID \
|
||||
{ /* b3fd8821-b46d-4160-913f-cc8fe8176f5f */ \
|
||||
0xb3fd8821, 0xb46d, 0x4160, \
|
||||
{0x91, 0x3f, 0xcc, 0x8f, 0xe8, 0x17, 0x6f, 0x5f} }
|
||||
{ /* {52B46C37-A078-4952-AED7-035D83C810C0} */ \
|
||||
0x52b46c37, 0xa078, 0x4952, \
|
||||
{0xae, 0xd7, 0x3, 0x5d, 0x83, 0xc8, 0x10, 0xc0 } }
|
||||
|
||||
/**
|
||||
* It is used by the application to initialize a runtime and run scripts.
|
||||
|
@ -69,11 +75,14 @@ class nsIScriptContext : public nsISupports
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTCONTEXT_IID)
|
||||
|
||||
/* Get the ID of this language. */
|
||||
virtual PRUint32 GetScriptTypeID() = 0;
|
||||
|
||||
/**
|
||||
* Compile and execute a script.
|
||||
*
|
||||
* @param aScript a string representing the script to be executed
|
||||
* @param aScopeObject a JavaScript JSObject for the scope to execute in, or
|
||||
* @param aScopeObject a script object for the scope to execute in, or
|
||||
* nsnull to use a default scope
|
||||
* @param aPrincipal the principal that produced the script
|
||||
* @param aURL the URL or filename for error messages
|
||||
|
@ -93,16 +102,18 @@ public:
|
|||
nsIPrincipal *aPrincipal,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
PRUint32 aVersion,
|
||||
nsAString *aRetValue,
|
||||
PRBool* aIsUndefined) = 0;
|
||||
|
||||
// Note JS bigotry remains here - 'void *aRetValue' is assumed to be a
|
||||
// jsval. This must move to JSObject before it can be made agnostic.
|
||||
virtual nsresult EvaluateStringWithValue(const nsAString& aScript,
|
||||
void *aScopeObject,
|
||||
nsIPrincipal *aPrincipal,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
PRUint32 aVersion,
|
||||
void* aRetValue,
|
||||
PRBool* aIsUndefined) = 0;
|
||||
|
||||
|
@ -118,10 +129,9 @@ public:
|
|||
* @param aLineNo the starting line number of the script for error messages
|
||||
* @param aVersion the script language version to use when executing
|
||||
* @param aScriptObject an executable object that's the result of compiling
|
||||
* the script. The caller is responsible for GC rooting
|
||||
* this object.
|
||||
* the script.
|
||||
*
|
||||
* @return NS_OK if the script source was valid and got compiled
|
||||
* @return NS_OK if the script source was valid and got compiled.
|
||||
*
|
||||
**/
|
||||
virtual nsresult CompileScript(const PRUnichar* aText,
|
||||
|
@ -130,8 +140,8 @@ public:
|
|||
nsIPrincipal* aPrincipal,
|
||||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
void** aScriptObject) = 0;
|
||||
PRUint32 aVersion,
|
||||
nsScriptObjectHolder &aScriptObject) = 0;
|
||||
|
||||
/**
|
||||
* Execute a precompiled script object.
|
||||
|
@ -154,11 +164,13 @@ public:
|
|||
|
||||
/**
|
||||
* Compile the event handler named by atom aName, with function body aBody
|
||||
* into a function object returned if ok via *aHandler. Bind the lowercase
|
||||
* ASCII name to the function in its parent object aTarget.
|
||||
* into a function object returned if ok via aHandler. Does NOT bind the
|
||||
* function to anything - BindCompiledEventHandler() should be used for that
|
||||
* purpose. Note that this event handler is always considered 'shared' and
|
||||
* hence is compiled without principals. Never call the returned object
|
||||
* directly - it must be bound (and thereby cloned, and therefore have the
|
||||
* correct principals) before use!
|
||||
*
|
||||
* @param aTarget an object telling the scope in which to bind the compiled
|
||||
* event handler function to aName.
|
||||
* @param aName an nsIAtom pointer naming the function; it must be lowercase
|
||||
* and ASCII, and should not be longer than 63 chars. This bound on
|
||||
* length is enforced only by assertions, so caveat caller!
|
||||
|
@ -166,41 +178,33 @@ public:
|
|||
* @param aBody the event handler function's body
|
||||
* @param aURL the URL or filename for error messages
|
||||
* @param aLineNo the starting line number of the script for error messages
|
||||
* @param aShared flag telling whether the compiled event handler will be
|
||||
* shared via nsIScriptEventHandlerOwner, in which case any static
|
||||
* link compiled into it based on aTarget should be cleared, both
|
||||
* to avoid entraining garbage to be collected, and to trigger static
|
||||
* link re-binding in BindCompiledEventHandler (see below).
|
||||
* @param aHandler the out parameter in which a void pointer to the compiled
|
||||
* function object is returned on success; may be null, meaning the
|
||||
* caller doesn't need to store the handler for later use.
|
||||
* function object is stored on success
|
||||
*
|
||||
* @return NS_OK if the function body was valid and got compiled
|
||||
*/
|
||||
virtual nsresult CompileEventHandler(void* aTarget,
|
||||
nsIAtom* aName,
|
||||
const char* aEventName,
|
||||
virtual nsresult CompileEventHandler(nsIAtom* aName,
|
||||
PRUint32 aArgCount,
|
||||
const char** aArgNames,
|
||||
const nsAString& aBody,
|
||||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
PRBool aShared,
|
||||
void** aHandler) = 0;
|
||||
const char* aURL, PRUint32 aLineNo,
|
||||
nsScriptObjectHolder &aHandler) = 0;
|
||||
|
||||
/**
|
||||
* Call the function object with given args and return its boolean result,
|
||||
* or true if the result isn't boolean.
|
||||
*
|
||||
* @param aTarget an object telling the scope in which to bind the compiled
|
||||
* @param aTarget the event target
|
||||
* @param aScript an object telling the scope in which to call the compiled
|
||||
* event handler function.
|
||||
* @param aHandler function object (function and static scope) to invoke.
|
||||
* @param argc actual argument count; length of argv
|
||||
* @param argv vector of arguments; length is argc
|
||||
* @param aBoolResult out parameter returning boolean function result, or
|
||||
* true if the result was not boolean.
|
||||
* @param argv array of arguments. Note each element is assumed to
|
||||
* be an nsIVariant.
|
||||
* @param rval out parameter returning result
|
||||
**/
|
||||
virtual nsresult CallEventHandler(JSObject* aTarget, JSObject* aHandler,
|
||||
uintN argc, jsval* argv,
|
||||
jsval* rval) = 0;
|
||||
virtual nsresult CallEventHandler(nsISupports* aTarget,
|
||||
void *aScope, void* aHandler,
|
||||
nsIArray *argv, nsIVariant **rval) = 0;
|
||||
|
||||
/**
|
||||
* Bind an already-compiled event handler function to a name in the given
|
||||
|
@ -209,19 +213,43 @@ public:
|
|||
* static scoping must re-bind the scope chain for aHandler to begin (after
|
||||
* the activation scope for aHandler itself, typically) with aTarget's scope.
|
||||
*
|
||||
* Logically, this 'bind' operation is more of a 'copy' - it simply
|
||||
* stashes/associates the event handler function with the event target, so
|
||||
* it can be fetched later with GetBoundEventHandler().
|
||||
*
|
||||
* @param aTarget an object telling the scope in which to bind the compiled
|
||||
* event handler function.
|
||||
* event handler function. The context will presumably associate
|
||||
* this nsISupports with a native script object.
|
||||
* @param aName an nsIAtom pointer naming the function; it must be lowercase
|
||||
* and ASCII, and should not be longer than 63 chars. This bound on
|
||||
* length is enforced only by assertions, so caveat caller!
|
||||
* @param aHandler the function object to name, created by an earlier call to
|
||||
* CompileEventHandler
|
||||
* @return NS_OK if the function was successfully bound to the name
|
||||
*
|
||||
* XXXmarkh - fold this in with SetProperty? Exactly the same concept!
|
||||
*/
|
||||
virtual nsresult BindCompiledEventHandler(void* aTarget,
|
||||
virtual nsresult BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
|
||||
nsIAtom* aName,
|
||||
void* aHandler) = 0;
|
||||
|
||||
/**
|
||||
* Lookup a previously bound event handler for the specified target. This
|
||||
* will return an object equivilent to the one passed to
|
||||
* BindCompiledEventHandler (although the pointer may not be the same).
|
||||
*
|
||||
*/
|
||||
virtual nsresult GetBoundEventHandler(nsISupports* aTarget, void *aScope,
|
||||
nsIAtom* aName,
|
||||
nsScriptObjectHolder &aHandler) = 0;
|
||||
|
||||
/**
|
||||
* Compile a function that isn't used as an event handler.
|
||||
*
|
||||
* NOTE: Not yet language agnostic (main problem is XBL - not yet agnostic)
|
||||
* Caller must make sure aFunctionObject is a JS GC root.
|
||||
*
|
||||
**/
|
||||
virtual nsresult CompileFunction(void* aTarget,
|
||||
const nsACString& aName,
|
||||
PRUint32 aArgCount,
|
||||
|
@ -230,15 +258,14 @@ public:
|
|||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
PRBool aShared,
|
||||
void** aFunctionObject) = 0;
|
||||
|
||||
void **aFunctionObject) = 0;
|
||||
|
||||
/**
|
||||
* Set the default scripting language version for this context, which must
|
||||
* be a context specific to a particular scripting language.
|
||||
*
|
||||
**/
|
||||
virtual void SetDefaultLanguageVersion(const char* aVersion) = 0;
|
||||
virtual void SetDefaultLanguageVersion(PRUint32 aVersion) = 0;
|
||||
|
||||
/**
|
||||
* Return the global object.
|
||||
|
@ -253,9 +280,38 @@ public:
|
|||
virtual void *GetNativeContext() = 0;
|
||||
|
||||
/**
|
||||
* Init this context.
|
||||
* Return the native global object for this context.
|
||||
*
|
||||
* @param aGlobalObject the gobal object
|
||||
**/
|
||||
virtual void *GetNativeGlobal() = 0;
|
||||
|
||||
/**
|
||||
* Create a new global object that will be used for an inner window.
|
||||
* Return the native global and an nsISupports 'holder' that can be used
|
||||
* to manage the lifetime of it.
|
||||
*/
|
||||
virtual nsresult CreateNativeGlobalForInner(
|
||||
nsIScriptGlobalObject *aNewInner,
|
||||
PRBool aIsChrome,
|
||||
void **aNativeGlobal,
|
||||
nsISupports **aHolder) = 0;
|
||||
|
||||
/**
|
||||
* Connect this context to a new inner window, to allow "prototype"
|
||||
* chaining from the inner to the outer.
|
||||
* Called after both the the inner and outer windows are initialized
|
||||
**/
|
||||
virtual nsresult ConnectToInner(nsIScriptGlobalObject *aNewInner,
|
||||
void *aOuterGlobal) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Init this context ready for use. If aGlobalObject is not NULL, this
|
||||
* function may initialize based on this global (for example, using the
|
||||
* global to locate a chrome window, create a new 'scope' for this
|
||||
* global, etc)
|
||||
*
|
||||
* @param aGlobalObject the gobal object, which may be nsnull.
|
||||
*
|
||||
* @return NS_OK if context initialization was successful
|
||||
*
|
||||
|
@ -271,6 +327,11 @@ public:
|
|||
*/
|
||||
virtual PRBool IsContextInitialized() = 0;
|
||||
|
||||
/**
|
||||
* Called as the global object discards its reference to the context.
|
||||
*/
|
||||
virtual void FinalizeContext() = 0;
|
||||
|
||||
/**
|
||||
* For garbage collected systems, do a synchronous collection pass.
|
||||
* May be a no-op on other systems
|
||||
|
@ -293,6 +354,14 @@ public:
|
|||
*/
|
||||
virtual void ScriptEvaluated(PRBool aTerminated) = 0;
|
||||
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
|
||||
void *aScriptObject) = 0;
|
||||
|
||||
/* Deserialize a script from a stream.
|
||||
*/
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsScriptObjectHolder &aResult) = 0;
|
||||
|
||||
/**
|
||||
* Let the script context know who its owner is.
|
||||
* The script context should not addref the owner. It
|
||||
|
@ -310,6 +379,8 @@ public:
|
|||
virtual nsIScriptContextOwner *GetOwner() = 0;
|
||||
|
||||
/**
|
||||
* JS only - this function need not be implemented by languages other
|
||||
* than JS (ie, this should be moved to a private interface!)
|
||||
* Called to specify a function that should be called when the current
|
||||
* script (if there is one) terminates. Generally used if breakdown
|
||||
* of script state needs to happen, but should be deferred till
|
||||
|
@ -326,6 +397,9 @@ public:
|
|||
virtual PRBool GetScriptsEnabled() = 0;
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) = 0;
|
||||
|
||||
// SetProperty is suspect and jst believes should not be needed. Currenly
|
||||
// used only for "arguments".
|
||||
virtual nsresult SetProperty(void *aTarget, const char *aPropName, nsISupports *aVal) = 0;
|
||||
/**
|
||||
* Called to set/get information if the script context is
|
||||
* currently processing a script tag
|
||||
|
@ -334,7 +408,8 @@ public:
|
|||
virtual void SetProcessingScriptTag(PRBool aResult) = 0;
|
||||
|
||||
/**
|
||||
* Tell the context whether or not to GC when destroyed.
|
||||
* Tell the context whether or not to GC when destroyed. An optimization
|
||||
* used when the window is a [i]frame, so GC will happen anyway.
|
||||
*/
|
||||
virtual void SetGCOnDestruction(PRBool aGCOnDestruction) = 0;
|
||||
|
||||
|
@ -344,7 +419,17 @@ public:
|
|||
* call DidInitializeContext() when a context is fully
|
||||
* (successfully) initialized.
|
||||
*/
|
||||
virtual nsresult InitClasses(JSObject *aGlobalObj) = 0;
|
||||
virtual nsresult InitClasses(void *aGlobalObj) = 0;
|
||||
|
||||
/**
|
||||
* Clear the scope object - may be called either as we are being torn down,
|
||||
* or before we are attached to a different document.
|
||||
* XXXmarkh - aClearPolluter is quite likely bogus - just that some places
|
||||
* that did this clear did not call InvalidateGlobalScopePolluter. It
|
||||
* seems likely this param should be dropped and that fn always called.
|
||||
* OR some extra virtual added to abstract when that Invalidate need happen.
|
||||
*/
|
||||
virtual void ClearScope(void* aGlobalObj, PRBool aClearPolluter) = 0;
|
||||
|
||||
/**
|
||||
* Tell the context we're about to be reinitialize it.
|
||||
|
@ -355,25 +440,25 @@ public:
|
|||
* Tell the context we're done reinitializing it.
|
||||
*/
|
||||
virtual void DidInitializeContext() = 0;
|
||||
|
||||
/**
|
||||
* Tell the context our global has a new document, and the scope
|
||||
* used by it.
|
||||
*/
|
||||
virtual void DidSetDocument(nsIDOMDocument *aDoc, void *aGlobal) = 0;
|
||||
|
||||
/* Memory managment for script objects. Used by the implementation of
|
||||
* nsScriptObjectHolder to manage the lifetimes of the held script objects.
|
||||
*
|
||||
* See also nsIScriptRuntime, which has identical methods and is useful
|
||||
* in situations when you do not have an nsIScriptContext.
|
||||
*
|
||||
*/
|
||||
virtual nsresult DropScriptObject(void *object) = 0;
|
||||
virtual nsresult HoldScriptObject(void *object) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContext, NS_ISCRIPTCONTEXT_IID)
|
||||
|
||||
inline nsIScriptContext *
|
||||
GetScriptContextFromJSContext(JSContext *cx)
|
||||
{
|
||||
if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptContext> scx =
|
||||
do_QueryInterface(NS_STATIC_CAST(nsISupports *,
|
||||
::JS_GetContextPrivate(cx)));
|
||||
|
||||
// This will return a pointer to something that's about to be
|
||||
// released, but that's ok here.
|
||||
return scx;
|
||||
}
|
||||
|
||||
#endif // nsIScriptContext_h__
|
||||
|
||||
|
|
|
@ -41,23 +41,74 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
class nsIDOMDocument;
|
||||
class nsIDOMEvent;
|
||||
class nsPresContext;
|
||||
class nsIDocShell;
|
||||
class nsIDOMWindowInternal;
|
||||
class nsIScriptGlobalObjectOwner;
|
||||
struct JSObject;
|
||||
class nsIArray;
|
||||
class nsScriptErrorEvent;
|
||||
class nsIScriptGlobalObject;
|
||||
enum nsEventStatus;
|
||||
struct JSObject; // until we finally remove GetGlobalJSObject...
|
||||
|
||||
// Some helpers for working with integer "script type IDs", and specifically
|
||||
// for working with arrays of such objects. For example, it is common for
|
||||
// implementations supporting multiple script languages to keep each
|
||||
// language's nsIScriptContext in an array indexed by the language ID.
|
||||
|
||||
// Implementation note: We always ignore nsIProgrammingLanguage::UNKNOWN and
|
||||
// nsIProgrammingLanguage::CPLUSPLUS - this gives javascript slot 0. An
|
||||
// attempted micro-optimization tried to avoid us going all the way to
|
||||
// nsIProgrammingLanguage::MAX; however:
|
||||
// * Someone is reportedly working on a PHP impl - that has value 9
|
||||
// * nsGenericElement therefore allows 4 bits for the value.
|
||||
// So there is no good reason for us to be more restrictive again...
|
||||
|
||||
#define NS_STID_FIRST nsIProgrammingLanguage::JAVASCRIPT
|
||||
// like nsGenericElement, only 4 bits worth is valid...
|
||||
#define NS_STID_LAST (nsIProgrammingLanguage::MAX > 0x000FU ? \
|
||||
0x000FU : nsIProgrammingLanguage::MAX)
|
||||
|
||||
// Use to declare the array size
|
||||
#define NS_STID_ARRAY_UBOUND (NS_STID_LAST-NS_STID_FIRST+1)
|
||||
|
||||
// Is a language ID valid?
|
||||
#define NS_STID_VALID(langID) (langID >= NS_STID_FIRST && langID <= NS_STID_LAST)
|
||||
|
||||
// Return an index for a given ID.
|
||||
#define NS_STID_INDEX(langID) (langID-NS_STID_FIRST)
|
||||
|
||||
// Create a 'for' loop iterating over all possible language IDs (*not* indexes)
|
||||
#define NS_STID_FOR_ID(varName) \
|
||||
for (varName=NS_STID_FIRST;varName<=NS_STID_LAST;varName++)
|
||||
|
||||
// Create a 'for' loop iterating over all indexes (when you don't need to know
|
||||
// what language it is)
|
||||
#define NS_STID_FOR_INDEX(varName) \
|
||||
for (varName=0;varName<=NS_STID_INDEX(NS_STID_LAST);varName++)
|
||||
|
||||
// A helper function for nsIScriptGlobalObject implementations to use
|
||||
// when handling a script error. Generally called by the global when a context
|
||||
// notifies it of an error via nsIScriptGlobalObject::HandleScriptError.
|
||||
// Returns PR_TRUE if HandleDOMEvent was actually called, in which case
|
||||
// aStatus will be filled in with the status.
|
||||
PRBool
|
||||
NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
|
||||
nsScriptErrorEvent *aErrorEvent,
|
||||
nsEventStatus *aStatus);
|
||||
|
||||
|
||||
#define NS_ISCRIPTGLOBALOBJECT_IID \
|
||||
{ 0xd3db0400, 0xcf29, 0x45ac, \
|
||||
{ 0x80, 0x72, 0x94, 0x6d, 0x99, 0x3d, 0x9d, 0xa8 } }
|
||||
{ /* {6E7EF978-47D0-47c9-9649-CDCDB1E4CCEC} */ \
|
||||
0x6e7ef978, 0x47d0, 0x47c9, \
|
||||
{ 0x96, 0x49, 0xcd, 0xcd, 0xb1, 0xe4, 0xcc, 0xec } }
|
||||
|
||||
/**
|
||||
* The JavaScript specific global object. This often used to store
|
||||
* per-window global state.
|
||||
+ * The global object which keeps a script context for each supported script
|
||||
+ * language. This often used to store per-window global state.
|
||||
*/
|
||||
|
||||
class nsIScriptGlobalObject : public nsISupports
|
||||
|
@ -65,8 +116,6 @@ class nsIScriptGlobalObject : public nsISupports
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTGLOBALOBJECT_IID)
|
||||
|
||||
virtual void SetContext(nsIScriptContext *aContext) = 0;
|
||||
virtual nsIScriptContext *GetContext() = 0;
|
||||
|
||||
/**
|
||||
* Let the script global object know who its owner is.
|
||||
|
@ -84,31 +133,71 @@ public:
|
|||
*/
|
||||
virtual nsIScriptGlobalObjectOwner *GetGlobalObjectOwner() = 0;
|
||||
|
||||
virtual JSObject *GetGlobalJSObject() = 0;
|
||||
/**
|
||||
* Ensure that the script global object is initialized for working with the
|
||||
* specified script language ID. This will set up the nsIScriptContext
|
||||
* and 'script global' for that language, allowing these to be fetched
|
||||
* and manipulated.
|
||||
* @return NS_OK if successful; error conditions include that the language
|
||||
* has not been registered, as well as 'normal' errors, such as
|
||||
* out-of-memory
|
||||
*/
|
||||
virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID) = 0;
|
||||
/**
|
||||
* Get a script context (WITHOUT added reference) for the specified language.
|
||||
*/
|
||||
virtual nsIScriptContext *GetScriptContext(PRUint32 lang) = 0;
|
||||
|
||||
/**
|
||||
* Get the opaque "global" object for the specified lang.
|
||||
*/
|
||||
virtual void *GetScriptGlobal(PRUint32 lang) = 0;
|
||||
|
||||
// Set/GetContext deprecated methods - use GetScriptContext/Global
|
||||
virtual JSObject *GetGlobalJSObject() {
|
||||
return (JSObject *)GetScriptGlobal(nsIProgrammingLanguage::JAVASCRIPT);
|
||||
}
|
||||
|
||||
virtual nsIScriptContext *GetContext() {
|
||||
return GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the global JSObject is finalized
|
||||
* Set a new language context for this global. The native global for the
|
||||
* context is created by the context's GetNativeGlobal() method.
|
||||
*/
|
||||
|
||||
virtual void OnFinalize(JSObject *aJSObject) = 0;
|
||||
virtual nsresult SetScriptContext(PRUint32 lang, nsIScriptContext *aContext) = 0;
|
||||
|
||||
/**
|
||||
* Called when the global script for a language is finalized, typically as
|
||||
* part of its GC process. By the time this call is made, the
|
||||
* nsIScriptContext for the language has probably already been removed.
|
||||
* After this call, the passed object is dead - which should generally be the
|
||||
* same object the global is using for a global for that language.
|
||||
*/
|
||||
|
||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal) = 0;
|
||||
|
||||
/**
|
||||
* Called to enable/disable scripts.
|
||||
*/
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) = 0;
|
||||
|
||||
/**
|
||||
* Set a new arguments array for this window. This will be set on
|
||||
/** Set a new arguments object for this window. This will be set on
|
||||
* the window right away (if there's an existing document) and it
|
||||
* will also be installed on the window when the next document is
|
||||
* loaded. If argc is nonzero, argv must be non-null.
|
||||
*
|
||||
* @param aArgc the number of args
|
||||
* @param aArgv the pointer to the args. This may be cast to jsval* and the
|
||||
* args are found at
|
||||
* ((jsval*)aArgv)[0], ..., ((jsval*)aArgv)[aArgc - 1]
|
||||
* loaded. Each language impl is responsible for converting to
|
||||
* an array of args as appropriate for that language.
|
||||
*/
|
||||
virtual nsresult SetNewArguments(PRUint32 aArgc, void* aArgv) = 0;
|
||||
virtual nsresult SetNewArguments(nsIArray *aArguments) = 0;
|
||||
|
||||
/** Handle a script error. Generally called by a script context.
|
||||
*/
|
||||
virtual nsresult HandleScriptError(nsScriptErrorEvent *aErrorEvent,
|
||||
nsEventStatus *aEventStatus) {
|
||||
return NS_HandleScriptError(this, aErrorEvent, aEventStatus);
|
||||
}
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptGlobalObject,
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsAString.h"
|
||||
|
||||
class nsScriptObjectHolder;
|
||||
|
||||
#define NS_ISCRIPTOBJECTOWNER_IID \
|
||||
{ /* 8f6bca7e-ce42-11d1-b724-00600891d8c9 */ \
|
||||
0x8f6bca7e, 0xce42, 0x11d1, \
|
||||
|
@ -117,25 +119,25 @@ public:
|
|||
* @param aBody the handler script body
|
||||
* @param aURL the URL or filename for error messages
|
||||
* @param aLineNo the starting line number of the script for error messages
|
||||
* @param aHandler the compiled, bound handler object
|
||||
* @param aHandler the holder for the compiled, bound handler object
|
||||
*/
|
||||
virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
|
||||
void* aTarget,
|
||||
nsISupports* aTarget,
|
||||
nsIAtom *aName,
|
||||
const nsAString& aBody,
|
||||
const char* aURL,
|
||||
PRUint32 aLineNo,
|
||||
void** aHandler) = 0;
|
||||
nsScriptObjectHolder &aHandler) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve an already-compiled event handler that can be bound to a
|
||||
* target object using a script context.
|
||||
*
|
||||
* @param aName the name of the event handler to retrieve
|
||||
* @param aHandler the compiled event handler
|
||||
* @param aHandler the holder for the compiled event handler.
|
||||
*/
|
||||
virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
|
||||
void** aHandler) = 0;
|
||||
nsScriptObjectHolder &aHandler) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptEventHandlerOwner,
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* ***** 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is mozilla.org.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Hammond (initial development)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef nsIScriptRuntime_h__
|
||||
#define nsIScriptRuntime_h__
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
// {47032A4D-0C22-4125-94B7-864A4B744335}
|
||||
#define NS_ISCRIPTRUNTIME_IID \
|
||||
{ 0x47032a4d, 0xc22, 0x4125, { 0x94, 0xb7, 0x86, 0x4a, 0x4b, 0x74, 0x43, 0x35 } }
|
||||
|
||||
|
||||
/**
|
||||
* A singleton language environment for an application. Responsible for
|
||||
* initializing and cleaning up the global language environment, and a factory
|
||||
* for language contexts
|
||||
*/
|
||||
class nsIScriptRuntime : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTRUNTIME_IID)
|
||||
/*
|
||||
* Return the language ID of this script language
|
||||
*/
|
||||
virtual PRUint32 GetScriptTypeID() = 0;
|
||||
|
||||
/*
|
||||
* Called as the language factory is shutting down.
|
||||
*/
|
||||
virtual void ShutDown() = 0;
|
||||
|
||||
/* Parses a "version string" for the language into a bit-mask used by
|
||||
* the language implementation. If the specified version is not supported
|
||||
* an error should be returned. If the specified version is blank, a default
|
||||
* version should be assumed
|
||||
*/
|
||||
virtual nsresult ParseVersion(const nsString &aVersionStr, PRUint32 *verFlags) = 0;
|
||||
|
||||
/* Factory for a new context for this language */
|
||||
virtual nsresult CreateContext(nsIScriptContext **ret) = 0;
|
||||
|
||||
/* Memory managment for script objects returned from various
|
||||
* nsIScriptContext methods. These are identical to those in
|
||||
* nsIScriptContext, but are useful when a script context is not known.
|
||||
*/
|
||||
virtual nsresult DropScriptObject(void *object) = 0;
|
||||
virtual nsresult HoldScriptObject(void *object) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptRuntime, NS_ISCRIPTRUNTIME_IID)
|
||||
|
||||
/* helper functions */
|
||||
nsresult NS_GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aRuntime);
|
||||
|
||||
nsresult NS_GetScriptRuntimeByID(PRUint32 aLanguageID,
|
||||
nsIScriptRuntime **aRuntime);
|
||||
|
||||
#endif // nsIScriptRuntime_h__
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=80: */
|
||||
/* ***** 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 ***** */
|
||||
#ifndef nsIScriptTimeoutHandler_h___
|
||||
#define nsIScriptTimeoutHandler_h___
|
||||
|
||||
class nsIArray;
|
||||
|
||||
#define NS_ISCRIPTTIMEOUTHANDLER_IID \
|
||||
{ /* {260C0DAB-0DCF-4c75-B820-46C31005718D} */ \
|
||||
0x260c0dab, 0xdcf, 0x4c75, \
|
||||
{ 0xb8, 0x20, 0x46, 0xc3, 0x10, 0x5, 0x71, 0x8d } }
|
||||
|
||||
/**
|
||||
* Abstraction of the script objects etc required to do timeouts in a
|
||||
* language agnostic way.
|
||||
*/
|
||||
|
||||
class nsIScriptTimeoutHandler : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTTIMEOUTHANDLER_IID)
|
||||
|
||||
// Get the script-type (language) implementing this timeout.
|
||||
virtual PRUint32 GetScriptTypeID() = 0;
|
||||
|
||||
// Get a script object for the language suitable for passing back to
|
||||
// the language's context as an event handler. If this returns nsnull,
|
||||
// GetHandlerText() will be called to get the string.
|
||||
virtual void *GetScriptObject() = 0;
|
||||
|
||||
// Get the handler text of not a compiled object.
|
||||
virtual const PRUnichar *GetHandlerText() = 0;
|
||||
|
||||
// Get the location of the script.
|
||||
virtual void GetLocation(const char **aFileName, PRUint32 *aLineNo) = 0;
|
||||
|
||||
// If a script object, get the argv suitable for passing back to the
|
||||
// script context.
|
||||
virtual nsIArray *GetArgv() = 0;
|
||||
|
||||
// Get the language version for this timeout.
|
||||
virtual PRUint32 GetScriptVersion() = 0;
|
||||
|
||||
// Set the "secret" final lateness arg. This will be called before
|
||||
// GetArgv(), which should reflect this lateness value.
|
||||
virtual void SetLateness(PRIntervalTime aHowLate) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptTimeoutHandler,
|
||||
NS_ISCRIPTTIMEOUTHANDLER_IID)
|
||||
|
||||
#endif // nsIScriptTimeoutHandler_h___
|
|
@ -92,6 +92,7 @@ CPPSRCS = \
|
|||
nsDOMException.cpp \
|
||||
nsDOMWindowUtils.cpp \
|
||||
nsJSEnvironment.cpp \
|
||||
nsJSTimeoutHandler.cpp \
|
||||
nsFocusController.cpp \
|
||||
nsGlobalWindow.cpp \
|
||||
nsGlobalWindowCommands.cpp \
|
||||
|
|
|
@ -6427,7 +6427,7 @@ nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
|||
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
|
||||
NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED);
|
||||
|
||||
sgo->OnFinalize(obj);
|
||||
sgo->OnFinalize(nsIProgrammingLanguage::JAVASCRIPT, obj);
|
||||
|
||||
return nsEventReceiverSH::Finalize(wrapper, cx, obj);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "jsapi.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
|
||||
class nsIDOMWindow;
|
||||
class nsIDOMNSHTMLOptionCollection;
|
||||
|
|
|
@ -59,13 +59,17 @@
|
|||
#include "nsJSEventListener.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsCRT.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIXULPrototypeCache.h"
|
||||
#endif
|
||||
|
||||
nsDOMScriptObjectFactory::nsDOMScriptObjectFactory()
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsDOMScriptObjectFactory::nsDOMScriptObjectFactory() :
|
||||
mLoadedAllLanguages(PR_FALSE)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
|
@ -86,6 +90,8 @@ nsDOMScriptObjectFactory::nsDOMScriptObjectFactory()
|
|||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_DOM_XPATH);
|
||||
xs->RegisterExceptionProvider(this, NS_ERROR_MODULE_XPCONNECT);
|
||||
}
|
||||
// And pre-create the javascript language.
|
||||
NS_CreateJSRuntime(getter_AddRefs(mLanguageArray[NS_STID_INDEX(nsIProgrammingLanguage::JAVASCRIPT)]));
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMScriptObjectFactory)
|
||||
|
@ -99,12 +105,106 @@ NS_INTERFACE_MAP_END
|
|||
NS_IMPL_ADDREF(nsDOMScriptObjectFactory)
|
||||
NS_IMPL_RELEASE(nsDOMScriptObjectFactory)
|
||||
|
||||
/**
|
||||
* Notes about language registration (for language other than js):
|
||||
* - All language are expected to register (at least) 2 contract IDs
|
||||
* @mozilla.org/script-language;1?id=%d
|
||||
* using the language ID as defined in nsIProgrammingLanguage, and
|
||||
* @mozilla.org/script-language;1?script-type=%s
|
||||
* using the "mime-type" of the script language
|
||||
*
|
||||
* Theoretically, a language could register multiple script-type
|
||||
* names, although this is discouraged - each language should have one,
|
||||
* canonical name.
|
||||
*
|
||||
* The most common case is that languages are looked up by ID. For this
|
||||
* reason, we keep an array of languages indexed by this ID - the registry
|
||||
* is only looked the first request for a language ID.
|
||||
*
|
||||
* The registry is looked up and getService called for each query by name.
|
||||
* (As services are cached by CID, multiple contractIDs will still work
|
||||
* correctly)
|
||||
**/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::NewScriptContext(nsIScriptGlobalObject *aGlobal,
|
||||
nsIScriptContext **aContext)
|
||||
nsDOMScriptObjectFactory::GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aLanguage)
|
||||
{
|
||||
return NS_CreateScriptContext(aGlobal, aContext);
|
||||
// Note that many callers have optimized detection for JS (along with
|
||||
// supporting various alternate names for JS), so don't call this.
|
||||
// One exception is for the new "script-type" attribute on a node - and
|
||||
// there is no need to support backwards compatible names.
|
||||
// As JS is the default language, this is still rarely called for JS -
|
||||
// only when a node explicitly sets JS - so that is done last.
|
||||
nsCAutoString contractid(NS_LITERAL_CSTRING(
|
||||
"@mozilla.org/script-language;1?script-type="));
|
||||
// Arbitrarily use utf8 encoding should the name have extended chars
|
||||
AppendUTF16toUTF8(aLanguageName, contractid);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> lang =
|
||||
do_GetService(contractid.get(), &rv);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (aLanguageName.Equals(NS_LITERAL_STRING("application/javascript")))
|
||||
return GetScriptRuntimeByID(nsIProgrammingLanguage::JAVASCRIPT, aLanguage);
|
||||
// Not JS and nothing else we know about.
|
||||
NS_WARNING("No script language registered for this mime-type");
|
||||
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
||||
}
|
||||
// And stash it away in our array for fast lookup by ID.
|
||||
PRUint32 lang_ndx = NS_STID_INDEX(lang->GetScriptTypeID());
|
||||
if (mLanguageArray[lang_ndx] == nsnull) {
|
||||
mLanguageArray[lang_ndx] = lang;
|
||||
} else {
|
||||
// All languages are services - we should have an identical object!
|
||||
NS_ASSERTION(mLanguageArray[lang_ndx] == lang,
|
||||
"Got a different language for this ID???");
|
||||
}
|
||||
*aLanguage = lang;
|
||||
NS_IF_ADDREF(*aLanguage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::GetScriptRuntimeByID(PRUint32 aLanguageID,
|
||||
nsIScriptRuntime **aLanguage)
|
||||
{
|
||||
if (!NS_STID_VALID(aLanguageID)) {
|
||||
NS_WARNING("Unknown script language");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
*aLanguage = mLanguageArray[NS_STID_INDEX(aLanguageID)];
|
||||
if (!*aLanguage) {
|
||||
nsCAutoString contractid(NS_LITERAL_CSTRING(
|
||||
"@mozilla.org/script-language;1?id="));
|
||||
char langIdStr[25]; // space for an int.
|
||||
sprintf(langIdStr, "%d", aLanguageID);
|
||||
contractid += langIdStr;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> lang = do_GetService(contractid.get(), &rv);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to get the script language");
|
||||
return rv;
|
||||
}
|
||||
*aLanguage = lang;
|
||||
}
|
||||
NS_IF_ADDREF(*aLanguage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::GetIDForScriptType(const nsAString &aLanguageName,
|
||||
PRUint32 *aScriptTypeID)
|
||||
{
|
||||
nsCOMPtr<nsIScriptRuntime> languageRuntime;
|
||||
nsresult rv;
|
||||
rv = GetScriptRuntime(aLanguageName, getter_AddRefs(languageRuntime));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
*aScriptTypeID = languageRuntime->GetScriptTypeID();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -184,7 +284,14 @@ nsDOMScriptObjectFactory::Observe(nsISupports *aSubject,
|
|||
|
||||
nsGlobalWindow::ShutDown();
|
||||
nsDOMClassInfo::ShutDown();
|
||||
nsJSEnvironment::ShutDown();
|
||||
|
||||
PRUint32 i;
|
||||
NS_STID_FOR_INDEX(i) {
|
||||
if (mLanguageArray[i] != nsnull) {
|
||||
mLanguageArray[i]->ShutDown();
|
||||
mLanguageArray[i] = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIExceptionService> xs =
|
||||
do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
|
||||
|
@ -262,3 +369,38 @@ nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
|
|||
aHasClassInterface,
|
||||
aConstructorCID);
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsDOMScriptObjectFactory::Startup()
|
||||
{
|
||||
nsJSRuntime::Startup();
|
||||
// nsDOMScriptObjectFactory is a service - assuming that reinitialzing
|
||||
// xpcom also recreates all services, then everything else should
|
||||
// reinitialize correctly.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Factories
|
||||
nsresult NS_GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aLanguage)
|
||||
{
|
||||
nsresult rv;
|
||||
*aLanguage = nsnull;
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = \
|
||||
do_GetService(kDOMScriptObjectFactoryCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return factory->GetScriptRuntime(aLanguageName, aLanguage);
|
||||
}
|
||||
|
||||
nsresult NS_GetScriptRuntimeByID(PRUint32 aScriptTypeID,
|
||||
nsIScriptRuntime **aLanguage)
|
||||
{
|
||||
nsresult rv;
|
||||
*aLanguage = nsnull;
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = \
|
||||
do_GetService(kDOMScriptObjectFactoryCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return factory->GetScriptRuntimeByID(aScriptTypeID, aLanguage);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIExceptionService.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptGlobalObject.h" // for misplaced NS_STID_ macros.
|
||||
|
||||
class nsDOMScriptObjectFactory : public nsIDOMScriptObjectFactory,
|
||||
public nsIObserver,
|
||||
|
@ -70,8 +72,14 @@ public:
|
|||
NS_DECL_NSIEXCEPTIONPROVIDER
|
||||
|
||||
// nsIDOMScriptObjectFactory
|
||||
NS_IMETHOD NewScriptContext(nsIScriptGlobalObject *aGlobal,
|
||||
nsIScriptContext **aContext);
|
||||
NS_IMETHOD GetScriptRuntime(const nsAString &aLanguageName,
|
||||
nsIScriptRuntime **aLanguage);
|
||||
|
||||
NS_IMETHOD GetScriptRuntimeByID(PRUint32 aLanguageID,
|
||||
nsIScriptRuntime **aLanguage);
|
||||
|
||||
NS_IMETHOD GetIDForScriptType(const nsAString &aLanguageName,
|
||||
PRUint32 *aLanguageID);
|
||||
|
||||
NS_IMETHOD NewScriptGlobalObject(PRBool aIsChrome,
|
||||
nsIScriptGlobalObject **aGlobal);
|
||||
|
@ -86,4 +94,10 @@ public:
|
|||
PRUint32 aScriptableFlags,
|
||||
PRBool aHasClassInterface,
|
||||
const nsCID *aConstructorCID);
|
||||
|
||||
static nsresult Startup();
|
||||
|
||||
protected:
|
||||
PRBool mLoadedAllLanguages;
|
||||
nsCOMPtr<nsIScriptRuntime> mLanguageArray[NS_STID_ARRAY_UBOUND];
|
||||
};
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -73,6 +73,7 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptTimeoutHandler.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
@ -103,6 +104,7 @@ class nsIContent;
|
|||
class nsPresContext;
|
||||
class nsIDOMEvent;
|
||||
class nsIScrollableView;
|
||||
class nsIArray;
|
||||
|
||||
typedef struct nsTimeout nsTimeout;
|
||||
|
||||
|
@ -122,6 +124,12 @@ enum OpenAllowValue {
|
|||
allowWhitelisted // allowed: it's whitelisted or popup blocking is disabled
|
||||
};
|
||||
|
||||
extern nsresult
|
||||
NS_CreateJSTimeoutHandler(nsIScriptContext *aContext,
|
||||
PRBool aIsInterval,
|
||||
PRInt32 *aInterval,
|
||||
nsIScriptTimeoutHandler **aRet);
|
||||
|
||||
//*****************************************************************************
|
||||
// nsGlobalWindow: Global Object for Scripting
|
||||
//*****************************************************************************
|
||||
|
@ -165,14 +173,23 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIScriptGlobalObject
|
||||
virtual void SetContext(nsIScriptContext *aContext);
|
||||
virtual nsIScriptContext *GetContext();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
|
||||
virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID);
|
||||
|
||||
virtual nsIScriptContext *GetScriptContext(PRUint32 lang);
|
||||
virtual void *GetScriptGlobal(PRUint32 lang);
|
||||
|
||||
// Set a new script language context for this global. The native global
|
||||
// for the context is created by the context's GetNativeGlobal() method.
|
||||
virtual nsresult SetScriptContext(PRUint32 lang, nsIScriptContext *aContext);
|
||||
|
||||
virtual void SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner);
|
||||
virtual nsIScriptGlobalObjectOwner *GetGlobalObjectOwner();
|
||||
virtual JSObject *GetGlobalJSObject();
|
||||
virtual void OnFinalize(JSObject *aJSObject);
|
||||
virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal);
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||
virtual nsresult SetNewArguments(PRUint32 aArgc, void* aArgv);
|
||||
virtual nsresult SetNewArguments(nsIArray *aArguments);
|
||||
|
||||
// nsIScriptObjectPrincipal
|
||||
virtual nsIPrincipal* GetPrincipal();
|
||||
|
@ -278,6 +295,16 @@ public:
|
|||
return mContext;
|
||||
}
|
||||
|
||||
nsIScriptContext *GetScriptContextInternal(PRUint32 aLangID)
|
||||
{
|
||||
NS_ASSERTION(NS_STID_VALID(aLangID), "Invalid language");
|
||||
if (mOuterWindow) {
|
||||
return GetOuterWindowInternal()->mScriptContexts[NS_STID_INDEX(aLangID)];
|
||||
}
|
||||
|
||||
return mScriptContexts[NS_STID_INDEX(aLangID)];
|
||||
}
|
||||
|
||||
nsGlobalWindow *GetOuterWindowInternal()
|
||||
{
|
||||
return NS_STATIC_CAST(nsGlobalWindow *, GetOuterWindow());
|
||||
|
@ -312,7 +339,7 @@ protected:
|
|||
void CleanUp();
|
||||
void ClearControllers();
|
||||
|
||||
void FreeInnerObjects(JSContext *cx);
|
||||
void FreeInnerObjects(nsIScriptContext *cx);
|
||||
|
||||
nsresult SetNewDocument(nsIDocument *aDocument,
|
||||
nsISupports *aState,
|
||||
|
@ -380,7 +407,7 @@ protected:
|
|||
PRBool aDialog,
|
||||
PRBool aCalledNoScript,
|
||||
PRBool aDoJSFixups,
|
||||
jsval *argv, PRUint32 argc,
|
||||
nsIArray *argv,
|
||||
nsISupports *aExtraArgument,
|
||||
nsIDOMWindow **aReturn);
|
||||
|
||||
|
@ -388,9 +415,19 @@ protected:
|
|||
static void ClearWindowScope(nsISupports* aWindow);
|
||||
|
||||
// Timeout Functions
|
||||
// Language agnostic timeout function (all args passed)
|
||||
nsresult SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
|
||||
PRInt32 interval,
|
||||
PRBool aIsInterval, PRInt32 *aReturn);
|
||||
nsresult ClearTimeoutOrInterval(PRInt32 aTimerID);
|
||||
|
||||
// JS specific timeout functions (JS args grabbed from context).
|
||||
nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn);
|
||||
void RunTimeout(nsTimeout *aTimeout);
|
||||
nsresult ClearTimeoutOrInterval();
|
||||
|
||||
// The timeout implementation functions.
|
||||
void RunTimeout(nsTimeout *aTimeout);
|
||||
|
||||
void ClearAllTimeouts();
|
||||
void InsertTimeoutIntoList(nsTimeout **aInsertionPoint, nsTimeout *aTimeout);
|
||||
static void TimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
@ -500,7 +537,8 @@ protected:
|
|||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
nsCOMPtr<nsIDOMWindowInternal> mOpener;
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
JSObject* mArguments;
|
||||
nsCOMPtr<nsIArray> mArguments;
|
||||
nsCOMPtr<nsIArray> mArgumentsLast;
|
||||
nsRefPtr<nsNavigator> mNavigator;
|
||||
nsRefPtr<nsScreen> mScreen;
|
||||
nsRefPtr<nsHistory> mHistory;
|
||||
|
@ -515,15 +553,19 @@ protected:
|
|||
nsRefPtr<nsLocation> mLocation;
|
||||
nsString mStatus;
|
||||
nsString mDefaultStatus;
|
||||
// index 0->language_id 1, so index MAX-1 == language_id MAX
|
||||
nsCOMPtr<nsIScriptContext> mScriptContexts[NS_STID_ARRAY_UBOUND];
|
||||
void * mScriptGlobals[NS_STID_ARRAY_UBOUND];
|
||||
nsGlobalWindowObserver* mObserver;
|
||||
|
||||
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference
|
||||
nsCOMPtr<nsIDOMCrypto> mCrypto;
|
||||
nsCOMPtr<nsIDOMPkcs11> mPkcs11;
|
||||
|
||||
|
||||
nsCOMPtr<nsIDOMStorageList> gGlobalStorageList;
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
|
||||
nsCOMPtr<nsISupports> mInnerWindowHolders[NS_STID_ARRAY_UBOUND];
|
||||
nsCOMPtr<nsIPrincipal> mOpenerScriptPrincipal; // strong; used to determine
|
||||
// whether to clear scope
|
||||
|
||||
|
@ -576,8 +618,9 @@ protected:
|
|||
};
|
||||
|
||||
/*
|
||||
* Timeout struct that holds information about each JavaScript
|
||||
* timeout.
|
||||
* Timeout struct that holds information about each script
|
||||
* timeout. Holds a strong reference to an nsIScriptTimeoutHandler, which
|
||||
* abstracts the language specific cruft.
|
||||
*/
|
||||
struct nsTimeout
|
||||
{
|
||||
|
@ -609,23 +652,15 @@ struct nsTimeout
|
|||
MOZ_COUNT_DTOR(nsTimeout);
|
||||
}
|
||||
|
||||
void Release(nsIScriptContext* aContext);
|
||||
void AddRef();
|
||||
nsrefcnt Release();
|
||||
nsrefcnt AddRef();
|
||||
|
||||
// Window for which this timeout fires
|
||||
nsGlobalWindow *mWindow;
|
||||
|
||||
// The JS expression to evaluate or function to call, if !mExpr
|
||||
JSString *mExpr;
|
||||
JSObject *mFunObj;
|
||||
nsRefPtr<nsGlobalWindow> mWindow;
|
||||
|
||||
// The actual timer object
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
// Function actual arguments and argument count
|
||||
jsval *mArgv;
|
||||
PRUint16 mArgc;
|
||||
|
||||
// True if the timeout was cleared
|
||||
PRPackedBool mCleared;
|
||||
|
||||
|
@ -645,12 +680,6 @@ struct nsTimeout
|
|||
// Principal with which to execute
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
// filename, line number and JS language version string of the
|
||||
// caller of setTimeout()
|
||||
char *mFileName;
|
||||
PRUint32 mLineNo;
|
||||
const char *mVersion;
|
||||
|
||||
// stack depth at which timeout is firing
|
||||
PRUint32 mFiringDepth;
|
||||
|
||||
|
@ -662,6 +691,9 @@ struct nsTimeout
|
|||
// another timeout
|
||||
PopupControlState mPopupState;
|
||||
|
||||
// The language-specific information about the callback.
|
||||
nsCOMPtr<nsIScriptTimeoutHandler> mScriptHandler;
|
||||
|
||||
private:
|
||||
// reference count for shared usage
|
||||
PRInt32 mRefCnt;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,9 +38,9 @@
|
|||
#define nsJSEnvironment_h___
|
||||
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIXPCScriptNotify.h"
|
||||
|
@ -58,12 +58,15 @@ public:
|
|||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual PRUint32 GetScriptTypeID()
|
||||
{ return nsIProgrammingLanguage::JAVASCRIPT; }
|
||||
|
||||
virtual nsresult EvaluateString(const nsAString& aScript,
|
||||
void *aScopeObject,
|
||||
nsIPrincipal *principal,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
PRUint32 aVersion,
|
||||
nsAString *aRetValue,
|
||||
PRBool* aIsUndefined);
|
||||
virtual nsresult EvaluateStringWithValue(const nsAString& aScript,
|
||||
|
@ -71,7 +74,7 @@ public:
|
|||
nsIPrincipal *aPrincipal,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
PRUint32 aVersion,
|
||||
void* aRetValue,
|
||||
PRBool* aIsUndefined);
|
||||
|
||||
|
@ -81,25 +84,29 @@ public:
|
|||
nsIPrincipal *principal,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
const char* aVersion,
|
||||
void** aScriptObject);
|
||||
PRUint32 aVersion,
|
||||
nsScriptObjectHolder &aScriptObject);
|
||||
virtual nsresult ExecuteScript(void* aScriptObject,
|
||||
void *aScopeObject,
|
||||
nsAString* aRetValue,
|
||||
PRBool* aIsUndefined);
|
||||
virtual nsresult CompileEventHandler(void *aTarget,
|
||||
nsIAtom *aName,
|
||||
const char *aEventName,
|
||||
|
||||
virtual nsresult CompileEventHandler(nsIAtom *aName,
|
||||
PRUint32 aArgCount,
|
||||
const char** aArgNames,
|
||||
const nsAString& aBody,
|
||||
const char *aURL,
|
||||
PRUint32 aLineNo,
|
||||
PRBool aShared,
|
||||
void** aHandler);
|
||||
virtual nsresult CallEventHandler(JSObject *aTarget, JSObject *aHandler,
|
||||
uintN argc, jsval *argv, jsval* rval);
|
||||
virtual nsresult BindCompiledEventHandler(void *aTarget,
|
||||
const char *aURL, PRUint32 aLineNo,
|
||||
nsScriptObjectHolder &aHandler);
|
||||
virtual nsresult CallEventHandler(nsISupports* aTarget, void *aScope,
|
||||
void* aHandler,
|
||||
nsIArray *argv, nsIVariant **rv);
|
||||
virtual nsresult BindCompiledEventHandler(nsISupports *aTarget,
|
||||
void *aScope,
|
||||
nsIAtom *aName,
|
||||
void *aHandler);
|
||||
virtual nsresult GetBoundEventHandler(nsISupports* aTarget, void *aScope,
|
||||
nsIAtom* aName,
|
||||
nsScriptObjectHolder &aHandler);
|
||||
virtual nsresult CompileFunction(void* aTarget,
|
||||
const nsACString& aName,
|
||||
PRUint32 aArgCount,
|
||||
|
@ -110,11 +117,21 @@ public:
|
|||
PRBool aShared,
|
||||
void** aFunctionObject);
|
||||
|
||||
virtual void SetDefaultLanguageVersion(const char* aVersion);
|
||||
virtual void SetDefaultLanguageVersion(PRUint32 aVersion);
|
||||
virtual nsIScriptGlobalObject *GetGlobalObject();
|
||||
virtual void *GetNativeContext();
|
||||
virtual void *GetNativeGlobal();
|
||||
virtual nsresult CreateNativeGlobalForInner(
|
||||
nsIScriptGlobalObject *aGlobal,
|
||||
PRBool aIsChrome,
|
||||
void **aNativeGlobal,
|
||||
nsISupports **aHolder);
|
||||
virtual nsresult ConnectToInner(nsIScriptGlobalObject *aNewInner,
|
||||
void *aOuterGlobal);
|
||||
virtual nsresult InitContext(nsIScriptGlobalObject *aGlobalObject);
|
||||
virtual PRBool IsContextInitialized();
|
||||
virtual void FinalizeContext();
|
||||
|
||||
virtual void GC();
|
||||
|
||||
virtual void ScriptEvaluated(PRBool aTerminated);
|
||||
|
@ -125,15 +142,26 @@ public:
|
|||
virtual PRBool GetScriptsEnabled();
|
||||
virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts);
|
||||
|
||||
virtual nsresult SetProperty(void *aTarget, const char *aPropName, nsISupports *aVal);
|
||||
|
||||
virtual PRBool GetProcessingScriptTag();
|
||||
virtual void SetProcessingScriptTag(PRBool aResult);
|
||||
|
||||
virtual void SetGCOnDestruction(PRBool aGCOnDestruction);
|
||||
|
||||
virtual nsresult InitClasses(JSObject *aGlobalObj);
|
||||
virtual nsresult InitClasses(void *aGlobalObj);
|
||||
virtual void ClearScope(void* aGlobalObj, PRBool bClearPolluters);
|
||||
|
||||
virtual void WillInitializeContext();
|
||||
virtual void DidInitializeContext();
|
||||
virtual void DidSetDocument(nsIDOMDocument *aDocdoc, void *aGlobal) {;}
|
||||
|
||||
virtual nsresult Serialize(nsIObjectOutputStream* aStream, void *aScriptObject);
|
||||
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
|
||||
nsScriptObjectHolder &aResult);
|
||||
|
||||
virtual nsresult DropScriptObject(void *object);
|
||||
virtual nsresult HoldScriptObject(void *object);
|
||||
|
||||
NS_DECL_NSIXPCSCRIPTNOTIFY
|
||||
|
||||
|
@ -145,8 +173,21 @@ protected:
|
|||
// aHolder should be holding our global object
|
||||
nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder);
|
||||
|
||||
// Helper to convert xpcom datatypes to jsvals.
|
||||
nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
|
||||
void *aScope,
|
||||
PRUint32 *aArgc, void **aArgv,
|
||||
void **aMarkp);
|
||||
|
||||
nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv);
|
||||
|
||||
void FireGCTimer();
|
||||
|
||||
// given an nsISupports object (presumably an event target or some other
|
||||
// DOM object), get (or create) the JSObject wrapping it.
|
||||
nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript,
|
||||
JSObject **aRet);
|
||||
|
||||
private:
|
||||
JSContext *mContext;
|
||||
PRUint32 mNumEvaluations;
|
||||
|
@ -232,25 +273,60 @@ private:
|
|||
|
||||
class nsIJSRuntimeService;
|
||||
|
||||
class nsJSEnvironment
|
||||
class nsJSRuntime : public nsIScriptRuntime
|
||||
{
|
||||
private:
|
||||
public:
|
||||
// let people who can see us use our runtime for convenience.
|
||||
static JSRuntime *sRuntime;
|
||||
|
||||
public:
|
||||
// called from the module Ctor to initialize statics
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIScriptRuntime
|
||||
virtual void ShutDown();
|
||||
|
||||
virtual PRUint32 GetScriptTypeID() {
|
||||
return nsIProgrammingLanguage::JAVASCRIPT;
|
||||
}
|
||||
|
||||
virtual nsresult CreateContext(nsIScriptContext **ret);
|
||||
|
||||
virtual nsresult ParseVersion(const nsString &aVersionStr, PRUint32 *flags);
|
||||
|
||||
virtual nsresult DropScriptObject(void *object);
|
||||
virtual nsresult HoldScriptObject(void *object);
|
||||
|
||||
// Private stuff.
|
||||
// called by the nsDOMScriptObjectFactory to initialize statics
|
||||
static void Startup();
|
||||
|
||||
// Setup all the statics etc - safe to call multiple times after Startup()
|
||||
static nsresult Init();
|
||||
|
||||
static nsresult CreateNewContext(nsIScriptContext **aContext);
|
||||
|
||||
static void ShutDown();
|
||||
};
|
||||
|
||||
/* factory function */
|
||||
nsresult NS_CreateScriptContext(nsIScriptGlobalObject *aGlobal,
|
||||
nsIScriptContext **aContext);
|
||||
// An interface for fast and native conversion to/from nsIArray. If an object
|
||||
// supports this interface, JS can reach directly in for the argv, and avoid
|
||||
// nsISupports conversion. If this interface is not supported, the object will
|
||||
// be queried for nsIArray, and everything converted via xpcom objects.
|
||||
#define NS_IJSARGARRAY_IID \
|
||||
{ /*{E96FB2AE-CB4F-44a0-81F8-D91C80AFE9A3} */ \
|
||||
0xe96fb2ae, 0xcb4f, 0x44a0, \
|
||||
{ 0x81, 0xf8, 0xd9, 0x1c, 0x80, 0xaf, 0xe9, 0xa3 } }
|
||||
|
||||
class nsIJSArgArray: public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSARGARRAY_IID)
|
||||
// Bug 312003 describes why this must be "void **", but after calling argv
|
||||
// may be cast to jsval* and the args found at:
|
||||
// ((jsval*)argv)[0], ..., ((jsval*)argv)[argc - 1]
|
||||
virtual nsresult GetArgs(PRUint32 *argc, void **argv) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID)
|
||||
|
||||
/* factory functions */
|
||||
nsresult NS_CreateJSRuntime(nsIScriptRuntime **aRuntime);
|
||||
|
||||
/* prototypes */
|
||||
void JS_DLL_CALLBACK NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=80: */
|
||||
/* ***** 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.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mark Hammond <mhammond@skippinet.com.au>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 "nsCOMPtr.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIScriptTimeoutHandler.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
static const char kSetIntervalStr[] = "setInterval";
|
||||
static const char kSetTimeoutStr[] = "setTimeout";
|
||||
|
||||
// Our JS nsIScriptTimeoutHandler implementation.
|
||||
class nsJSScriptTimeoutHandler: public nsIScriptTimeoutHandler
|
||||
{
|
||||
public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsJSScriptTimeoutHandler();
|
||||
~nsJSScriptTimeoutHandler();
|
||||
|
||||
virtual const PRUnichar *GetHandlerText();
|
||||
virtual void *GetScriptObject() {
|
||||
return mFunObj;
|
||||
}
|
||||
virtual void GetLocation(const char **aFileName, PRUint32 *aLineNo) {
|
||||
*aFileName = mFileName.get();
|
||||
*aLineNo = mLineNo;
|
||||
}
|
||||
|
||||
virtual PRUint32 GetScriptTypeID() {
|
||||
return nsIProgrammingLanguage::JAVASCRIPT;
|
||||
}
|
||||
virtual PRUint32 GetScriptVersion() {
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
virtual nsIArray *GetArgv() {
|
||||
return mArgv;
|
||||
}
|
||||
// Called by the timeout mechanism so the secret 'lateness' arg can be
|
||||
// added.
|
||||
virtual void SetLateness(PRIntervalTime aHowLate);
|
||||
|
||||
nsresult Init(nsIScriptContext *aContext, PRBool aIsInterval,
|
||||
PRInt32 *aInterval);
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
|
||||
// filename, line number and JS language version string of the
|
||||
// caller of setTimeout()
|
||||
nsCAutoString mFileName;
|
||||
PRUint32 mLineNo;
|
||||
PRUint32 mVersion;
|
||||
nsCOMPtr<nsIArray> mArgv;
|
||||
|
||||
// The JS expression to evaluate or function to call, if !mExpr
|
||||
JSString *mExpr;
|
||||
JSObject *mFunObj;
|
||||
};
|
||||
|
||||
|
||||
// nsJSScriptTimeoutHandler
|
||||
// QueryInterface implementation for nsJSScriptTimeoutHandler
|
||||
NS_INTERFACE_MAP_BEGIN(nsJSScriptTimeoutHandler)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(nsJSScriptTimeoutHandler)
|
||||
NS_IMPL_RELEASE(nsJSScriptTimeoutHandler)
|
||||
|
||||
nsJSScriptTimeoutHandler::nsJSScriptTimeoutHandler() :
|
||||
mLineNo(0),
|
||||
mVersion(nsnull),
|
||||
mExpr(nsnull),
|
||||
mFunObj(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
nsJSScriptTimeoutHandler::~nsJSScriptTimeoutHandler()
|
||||
{
|
||||
if (mExpr || mFunObj) {
|
||||
nsIScriptContext *scx = mContext;
|
||||
JSRuntime *rt = nsnull;
|
||||
|
||||
if (scx) {
|
||||
JSContext *cx;
|
||||
cx = (JSContext *)scx->GetNativeContext();
|
||||
rt = ::JS_GetRuntime(cx);
|
||||
} else {
|
||||
// XXX The timeout *must* be unrooted, even if !scx. This can be
|
||||
// done without a JS context using the JSRuntime. This is safe
|
||||
// enough, but it would be better to drop all a window's
|
||||
// timeouts before its context is cleared. Bug 50705 describes a
|
||||
// situation where we're not. In that case, at the time the
|
||||
// context is cleared, a timeout (actually an Interval) is still
|
||||
// active, but temporarily removed from the window's list of
|
||||
// timers (placed instead on the timer manager's list). This
|
||||
// makes the nearly handy ClearAllTimeouts routine useless, so
|
||||
// we settled on using the JSRuntime rather than relying on the
|
||||
// window having a context. It would be good to remedy this
|
||||
// workable but clumsy situation someday.
|
||||
|
||||
nsCOMPtr<nsIJSRuntimeService> rtsvc =
|
||||
do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
|
||||
if (rtsvc) {
|
||||
rtsvc->GetRuntime(&rt);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rt) {
|
||||
// most unexpected. not much choice but to bail.
|
||||
|
||||
NS_ERROR("nsTimeout::Release() with no JSRuntime. eek!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (mExpr) {
|
||||
::JS_RemoveRootRT(rt, &mExpr);
|
||||
} else if (mFunObj) {
|
||||
::JS_RemoveRootRT(rt, &mFunObj);
|
||||
} else {
|
||||
NS_WARNING("No func and no expr - roots may not have been removed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSScriptTimeoutHandler::Init(nsIScriptContext *aContext, PRBool aIsInterval,
|
||||
PRInt32 *aInterval)
|
||||
{
|
||||
if (!aContext) {
|
||||
// This window was already closed, or never properly initialized,
|
||||
// don't let a timer be scheduled on such a window.
|
||||
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
mContext = aContext;
|
||||
|
||||
nsCOMPtr<nsIXPCNativeCallContext> ncc;
|
||||
nsresult rv = nsContentUtils::XPConnect()->
|
||||
GetCurrentNativeCallContext(getter_AddRefs(ncc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!ncc)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
JSContext *cx = nsnull;
|
||||
|
||||
rv = ncc->GetJSContext(&cx);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 argc;
|
||||
jsval *argv = nsnull;
|
||||
|
||||
ncc->GetArgc(&argc);
|
||||
ncc->GetArgvPtr(&argv);
|
||||
|
||||
JSString *expr = nsnull;
|
||||
JSObject *funobj = nsnull;
|
||||
int32 interval = 0;
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
if (argc < 1) {
|
||||
::JS_ReportError(cx, "Function %s requires at least 1 parameter",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
|
||||
return ncc->SetExceptionWasThrown(PR_TRUE);
|
||||
}
|
||||
|
||||
if (argc > 1 && !::JS_ValueToECMAInt32(cx, argv[1], &interval)) {
|
||||
::JS_ReportError(cx,
|
||||
"Second argument to %s must be a millisecond interval",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
|
||||
return ncc->SetExceptionWasThrown(PR_TRUE);
|
||||
}
|
||||
|
||||
switch (::JS_TypeOfValue(cx, argv[0])) {
|
||||
case JSTYPE_FUNCTION:
|
||||
funobj = JSVAL_TO_OBJECT(argv[0]);
|
||||
break;
|
||||
|
||||
case JSTYPE_STRING:
|
||||
case JSTYPE_OBJECT:
|
||||
expr = ::JS_ValueToString(cx, argv[0]);
|
||||
if (!expr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
argv[0] = STRING_TO_JSVAL(expr);
|
||||
break;
|
||||
|
||||
default:
|
||||
::JS_ReportError(cx, "useless %s call (missing quotes around argument?)",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
|
||||
return ncc->SetExceptionWasThrown(PR_TRUE);
|
||||
}
|
||||
|
||||
if (expr) {
|
||||
if (!::JS_AddNamedRoot(cx, &mExpr, "timeout.mExpr")) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mExpr = expr;
|
||||
} else if (funobj) {
|
||||
if (!::JS_AddNamedRoot(cx, &mFunObj, "timeout.mFunObj")) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mFunObj = funobj;
|
||||
|
||||
/* Create our arg array - leave an extra slot for a secret final argument
|
||||
that indicates to the called function how "late" the timeout is. We
|
||||
will fill that in when SetLateness is called.
|
||||
*/
|
||||
nsCOMPtr<nsIArray> array;
|
||||
rv = NS_CreateJSArgv(cx, argc-1, nsnull, getter_AddRefs(array));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PRUint32 dummy;
|
||||
jsval *jsargv = nsnull;
|
||||
nsCOMPtr<nsIJSArgArray> jsarray(do_QueryInterface(array));
|
||||
jsarray->GetArgs(&dummy, NS_REINTERPRET_CAST(void **, &jsargv));
|
||||
// must have worked - we own the impl! :)
|
||||
NS_ASSERTION(jsargv, "No argv!");
|
||||
for (PRInt32 i = 2; (PRUint32)i < argc; ++i) {
|
||||
jsargv[i - 2] = argv[i];
|
||||
}
|
||||
// final arg slot remains null, array has rooted vals.
|
||||
mArgv = array;
|
||||
|
||||
// Get the calling location.
|
||||
const char *filename;
|
||||
if (nsJSUtils::GetCallingLocation(cx, &filename, &mLineNo)) {
|
||||
mFileName.Assign(filename);
|
||||
|
||||
if (mFileName.IsEmpty()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
NS_WARNING("No func and no expr - why are we here?");
|
||||
}
|
||||
*aInterval = interval;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsJSScriptTimeoutHandler::SetLateness(PRIntervalTime aHowLate)
|
||||
{
|
||||
nsCOMPtr<nsIJSArgArray> jsarray(do_QueryInterface(mArgv));
|
||||
if (jsarray) {
|
||||
PRUint32 argc;
|
||||
jsval *jsargv;
|
||||
jsarray->GetArgs(&argc, NS_REINTERPRET_CAST(void **, &jsargv));
|
||||
if (jsargv && argc)
|
||||
jsargv[argc-1] = INT_TO_JSVAL((jsint) aHowLate);
|
||||
} else {
|
||||
NS_ERROR("How can our argv not handle this?");
|
||||
}
|
||||
}
|
||||
|
||||
const PRUnichar *
|
||||
nsJSScriptTimeoutHandler::GetHandlerText()
|
||||
{
|
||||
NS_ASSERTION(mExpr, "No expression, so no handler text!");
|
||||
return NS_REINTERPRET_CAST(const PRUnichar *,
|
||||
::JS_GetStringChars(mExpr));
|
||||
}
|
||||
|
||||
nsresult NS_CreateJSTimeoutHandler(nsIScriptContext *aContext,
|
||||
PRBool aIsInterval,
|
||||
PRInt32 *aInterval,
|
||||
nsIScriptTimeoutHandler **aRet)
|
||||
{
|
||||
*aRet = nsnull;
|
||||
nsJSScriptTimeoutHandler *handler = new nsJSScriptTimeoutHandler();
|
||||
if (!handler)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = handler->Init(aContext, aIsInterval, aInterval);
|
||||
if (NS_FAILED(rv)) {
|
||||
delete handler;
|
||||
return rv;
|
||||
}
|
||||
return handler->QueryInterface(NS_GET_IID(nsIScriptTimeoutHandler),
|
||||
NS_REINTERPRET_CAST(void **, aRet));
|
||||
}
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsIDOMGCParticipant.h"
|
||||
#include "nsIWeakReference.h"
|
||||
|
||||
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
|
||||
|
||||
JSBool
|
||||
nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
|
||||
|
@ -198,7 +199,7 @@ nsJSUtils::GetStaticScriptContext(JSContext* aContext, JSObject* aObj)
|
|||
if (!nativeGlobal)
|
||||
return nsnull;
|
||||
|
||||
return nativeGlobal->GetContext();
|
||||
return nativeGlobal->GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT);
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject *
|
||||
|
|
|
@ -269,6 +269,20 @@ nsWindowRoot::GetFocusController(nsIFocusController** aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowRoot::GetScriptTypeID(PRUint32 *aScriptType)
|
||||
{
|
||||
NS_ERROR("No default script type here - ask some element");
|
||||
return nsIProgrammingLanguage::UNKNOWN;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowRoot::SetScriptTypeID(PRUint32 aScriptType)
|
||||
{
|
||||
NS_ERROR("Can't change default script type for a document");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -39,42 +39,56 @@
|
|||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMScriptObjectHolder.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
||||
#include "nspr.h" // PR_fprintf
|
||||
|
||||
PRInt32 nsIJSEventListener::sNumJSEventListeners = 0;
|
||||
|
||||
class EventListenerCounter
|
||||
{
|
||||
public:
|
||||
~EventListenerCounter() {
|
||||
if (nsIJSEventListener::sNumJSEventListeners) {
|
||||
PR_fprintf(PR_STDERR,"WARNING: LEAKED %d nsIJSEventListeners\n",
|
||||
nsIJSEventListener::sNumJSEventListeners);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static EventListenerCounter sEventListenerCounter;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* nsJSEventListener implementation
|
||||
*/
|
||||
nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
|
||||
JSObject *aScopeObject,
|
||||
nsISupports *aObject)
|
||||
: nsIJSEventListener(aContext, aScopeObject, aObject),
|
||||
void *aScopeObject,
|
||||
nsISupports *aTarget)
|
||||
: nsIJSEventListener(aContext, aScopeObject, aTarget),
|
||||
mReturnResult(nsReturnResult_eNotSet)
|
||||
{
|
||||
if (aScopeObject && aContext) {
|
||||
JSContext *cx = (JSContext *)aContext->GetNativeContext();
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
::JS_LockGCThing(cx, aScopeObject);
|
||||
}
|
||||
// mScopeObject is the "script global" for a context - this
|
||||
// does not need explicit memory management so long we we don't
|
||||
// outlive the context - which we don't.
|
||||
}
|
||||
|
||||
nsJSEventListener::~nsJSEventListener()
|
||||
{
|
||||
if (mScopeObject && mContext) {
|
||||
JSContext *cx = (JSContext *)mContext->GetNativeContext();
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
::JS_UnlockGCThing(cx, mScopeObject);
|
||||
}
|
||||
// as above, no need to "drop" our reference...
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsJSEventListener)
|
||||
|
@ -98,16 +112,15 @@ nsJSEventListener::SetEventName(nsIAtom* aName)
|
|||
nsresult
|
||||
nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
jsval funval;
|
||||
jsval arg;
|
||||
jsval *argv = &arg;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIArray> iargv;
|
||||
PRInt32 argc = 0;
|
||||
void *stackPtr; // For JS_[Push|Pop]Arguments()
|
||||
nsAutoString eventString;
|
||||
// XXX This doesn't seem like the correct context on which to execute
|
||||
// the event handler. Might need to get one from the JS thread context
|
||||
// stack.
|
||||
JSContext* cx = (JSContext*)mContext->GetNativeContext();
|
||||
nsCOMPtr<nsIAtom> atomName;
|
||||
|
||||
if (!mEventName) {
|
||||
if (NS_OK != aEvent->GetType(eventString)) {
|
||||
|
@ -124,36 +137,20 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
}
|
||||
//}
|
||||
eventString.Assign(NS_LITERAL_STRING("on") + eventString);
|
||||
atomName = do_GetAtom(eventString);
|
||||
}
|
||||
else {
|
||||
mEventName->ToString(eventString);
|
||||
atomName = mEventName;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsIXPConnect *xpc = nsContentUtils::XPConnect();
|
||||
|
||||
// root
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||
rv = xpc->WrapNative(cx, mScopeObject, mTarget, NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(wrapper));
|
||||
nsScriptObjectHolder funcval(mContext);
|
||||
rv = mContext->GetBoundEventHandler(mTarget, mScopeObject, atomName,
|
||||
funcval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject* obj = nsnull;
|
||||
rv = wrapper->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
if (!JS_LookupUCProperty(cx, obj,
|
||||
NS_REINTERPRET_CAST(const jschar *,
|
||||
eventString.get()),
|
||||
eventString.Length(), &funval)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (JS_TypeOfValue(cx, funval) != JSTYPE_FUNCTION) {
|
||||
if (!funcval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool handledScriptError = PR_FALSE;
|
||||
if (eventString.EqualsLiteral("onerror")) {
|
||||
|
@ -165,36 +162,58 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
if (event->message == NS_SCRIPT_ERROR) {
|
||||
nsScriptErrorEvent *scriptEvent =
|
||||
NS_STATIC_CAST(nsScriptErrorEvent*, event);
|
||||
// Create a temp argv for the error event.
|
||||
nsCOMPtr<nsIMutableArray> tempargv =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Append the event args.
|
||||
nsCOMPtr<nsIWritableVariant>
|
||||
var(do_CreateInstance(NS_VARIANT_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsWString(scriptEvent->errorMsg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = tempargv->AppendElement(var, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// filename
|
||||
var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsWString(scriptEvent->fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = tempargv->AppendElement(var, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// line number
|
||||
var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = var->SetAsUint32(scriptEvent->lineNr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = tempargv->AppendElement(var, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// And set the real argv
|
||||
iargv = do_QueryInterface(tempargv);
|
||||
|
||||
argv = ::JS_PushArguments(cx, &stackPtr, "WWi", scriptEvent->errorMsg,
|
||||
scriptEvent->fileName, scriptEvent->lineNr);
|
||||
NS_ENSURE_TRUE(argv, NS_ERROR_OUT_OF_MEMORY);
|
||||
argc = 3;
|
||||
handledScriptError = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!handledScriptError) {
|
||||
rv = xpc->WrapNative(cx, obj, aEvent, NS_GET_IID(nsIDOMEvent),
|
||||
getter_AddRefs(wrapper));
|
||||
nsCOMPtr<nsIMutableArray> tempargv =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_TRUE(tempargv != nsnull, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = tempargv->AppendElement(aEvent, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject *eventObj = nsnull;
|
||||
rv = wrapper->GetJSObject(&eventObj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
argv[0] = OBJECT_TO_JSVAL(eventObj);
|
||||
argc = 1;
|
||||
iargv = do_QueryInterface(tempargv);
|
||||
}
|
||||
|
||||
jsval rval;
|
||||
rv = mContext->CallEventHandler(obj, JSVAL_TO_OBJECT(funval), argc, argv,
|
||||
&rval);
|
||||
|
||||
if (argv != &arg)
|
||||
::JS_PopArguments(cx, stackPtr);
|
||||
nsCOMPtr<nsIVariant> vrv;
|
||||
rv = mContext->CallEventHandler(mTarget, mScopeObject, funcval, iargv,
|
||||
getter_AddRefs(vrv));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRUint16 dataType = nsIDataType::VTYPE_VOID;
|
||||
if (vrv)
|
||||
vrv->GetDataType(&dataType);
|
||||
if (eventString.EqualsLiteral("onbeforeunload")) {
|
||||
nsCOMPtr<nsIPrivateDOMEvent> priv(do_QueryInterface(aEvent));
|
||||
NS_ENSURE_TRUE(priv, NS_ERROR_UNEXPECTED);
|
||||
|
@ -207,24 +226,38 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
nsBeforePageUnloadEvent *beforeUnload =
|
||||
NS_STATIC_CAST(nsBeforePageUnloadEvent *, event);
|
||||
|
||||
if (!JSVAL_IS_VOID(rval)) {
|
||||
if (dataType != nsIDataType::VTYPE_VOID) {
|
||||
aEvent->PreventDefault();
|
||||
|
||||
// Set the text in the beforeUnload event as long as it wasn't
|
||||
// already set (through event.returnValue, which takes
|
||||
// precedence over a value returned from a JS function in IE)
|
||||
if (JSVAL_IS_STRING(rval) && beforeUnload->text.IsEmpty()) {
|
||||
beforeUnload->text = nsDependentJSString(JSVAL_TO_STRING(rval));
|
||||
if ((dataType == nsIDataType::VTYPE_DOMSTRING ||
|
||||
dataType == nsIDataType::VTYPE_CHAR_STR ||
|
||||
dataType == nsIDataType::VTYPE_WCHAR_STR ||
|
||||
dataType == nsIDataType::VTYPE_STRING_SIZE_IS ||
|
||||
dataType == nsIDataType::VTYPE_WSTRING_SIZE_IS ||
|
||||
dataType == nsIDataType::VTYPE_CSTRING ||
|
||||
dataType == nsIDataType::VTYPE_ASTRING)
|
||||
&& beforeUnload->text.IsEmpty()) {
|
||||
vrv->GetAsDOMString(beforeUnload->text);
|
||||
}
|
||||
}
|
||||
} else if (JSVAL_IS_BOOLEAN(rval)) {
|
||||
} else if (dataType == nsIDataType::VTYPE_BOOL ||
|
||||
dataType == nsIDataType::VTYPE_INT8 ||
|
||||
dataType == nsIDataType::VTYPE_INT16 ||
|
||||
dataType == nsIDataType::VTYPE_INT32 ||
|
||||
dataType == nsIDataType::VTYPE_UINT8 ||
|
||||
dataType == nsIDataType::VTYPE_UINT16 ||
|
||||
dataType == nsIDataType::VTYPE_UINT32) {
|
||||
// If the handler returned false and its sense is not reversed,
|
||||
// or the handler returned true and its sense is reversed from
|
||||
// the usual (false means cancel), then prevent default.
|
||||
|
||||
if (JSVAL_TO_BOOLEAN(rval) ==
|
||||
(mReturnResult == nsReturnResult_eReverseReturnResult))
|
||||
PRBool brv;
|
||||
if (NS_SUCCEEDED(vrv->GetAsBool(&brv)) &&
|
||||
brv == (mReturnResult == nsReturnResult_eReverseReturnResult)) {
|
||||
aEvent->PreventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,15 +269,14 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
*/
|
||||
|
||||
nsresult
|
||||
NS_NewJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject,
|
||||
nsISupports *aObject, nsIDOMEventListener ** aReturn)
|
||||
NS_NewJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
|
||||
nsISupports*aTarget, nsIDOMEventListener ** aReturn)
|
||||
{
|
||||
nsJSEventListener* it =
|
||||
new nsJSEventListener(aContext, aScopeObject, aObject);
|
||||
new nsJSEventListener(aContext, aScopeObject, aTarget);
|
||||
if (!it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aReturn = it);
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -46,12 +46,13 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
//nsIDOMMouseListener interface
|
||||
// nsJSEventListener interface
|
||||
// misnamed - JS no longer has exclusive rights over this interface!
|
||||
class nsJSEventListener : public nsIDOMEventListener,
|
||||
public nsIJSEventListener
|
||||
{
|
||||
public:
|
||||
nsJSEventListener(nsIScriptContext *aContext, JSObject *aScopeObject,
|
||||
nsJSEventListener(nsIScriptContext *aContext, void *aScopeObject,
|
||||
nsISupports* aObject);
|
||||
virtual ~nsJSEventListener();
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "nsXPIDLString.h"
|
||||
#include "prprf.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIContentViewer.h"
|
||||
|
|
|
@ -46,6 +46,7 @@ interface nsIDOMWindow;
|
|||
interface nsISimpleEnumerator;
|
||||
interface nsIWebBrowserChrome;
|
||||
interface nsIDocShellTreeItem;
|
||||
interface nsIArray;
|
||||
|
||||
%{C++
|
||||
#include "jspubtd.h"
|
||||
|
@ -84,9 +85,7 @@ interface nsPIWindowWatcher : nsISupports
|
|||
aUrl in it (if aUrl is not null) and return it.
|
||||
@param aFeatures window features from JS window.open. can be null.
|
||||
@param aDialog use dialog defaults (see nsIDOMWindowInternal::openDialog)
|
||||
@param argc count of argv arguments
|
||||
@param argv extra JS arguments, if any
|
||||
(see nsIDOMWindowInternal::openDialog)
|
||||
@param aArgs Window argument
|
||||
@return the new window
|
||||
|
||||
@note This method may examine the JS context stack for purposes of
|
||||
|
@ -99,7 +98,7 @@ interface nsPIWindowWatcher : nsISupports
|
|||
*/
|
||||
nsIDOMWindow openWindowJS(in nsIDOMWindow aParent, in string aUrl,
|
||||
in string aName, in string aFeatures, in boolean aDialog,
|
||||
in PRUint32 argc, in jsvalptr argv);
|
||||
in nsIArray aArgs);
|
||||
|
||||
/**
|
||||
* Find a named docshell tree item amongst all windows registered
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsWWJSUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
nsIScriptGlobalObject *
|
||||
nsWWJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
|
||||
|
|
|
@ -66,9 +66,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebBrowser.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
|
@ -81,6 +79,7 @@
|
|||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIWindowProvider.h"
|
||||
#include "nsIMutableArray.h"
|
||||
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
|
@ -316,25 +315,6 @@ nsresult JSContextAutoPopper::Push(JSContext *cx)
|
|||
return mContext ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
************************** AutoFree ****************************
|
||||
****************************************************************/
|
||||
|
||||
class AutoFree {
|
||||
public:
|
||||
AutoFree(void *aPtr) : mPtr(aPtr) {
|
||||
}
|
||||
~AutoFree() {
|
||||
if (mPtr)
|
||||
nsMemory::Free(mPtr);
|
||||
}
|
||||
void Invalidate() {
|
||||
mPtr = 0;
|
||||
}
|
||||
private:
|
||||
void *mPtr;
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
*********************** nsWindowWatcher ************************
|
||||
****************************************************************/
|
||||
|
@ -378,29 +358,26 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow *aParent,
|
|||
nsISupports *aArguments,
|
||||
nsIDOMWindow **_retval)
|
||||
{
|
||||
PRUint32 argc;
|
||||
jsval *argv = nsnull;
|
||||
JSContext *cx;
|
||||
void *mark;
|
||||
|
||||
// This kungFuDeathGrip is filled when we are using aParent's context. It
|
||||
// prevents the context from being destroyed before we're truly done with
|
||||
// it.
|
||||
nsCOMPtr<nsIScriptContext> kungFuDeathGrip;
|
||||
|
||||
nsresult rv = ConvertSupportsTojsvals(aParent, aArguments, &argc, &argv, &cx,
|
||||
&mark, getter_AddRefs(kungFuDeathGrip));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRBool dialog = argc == 0 ? PR_FALSE : PR_TRUE;
|
||||
rv = OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, dialog, argc,
|
||||
argv, PR_FALSE, _retval);
|
||||
|
||||
if (argv) {
|
||||
js_FreeStack(cx, mark);
|
||||
nsCOMPtr<nsIArray> argsArray;
|
||||
PRUint32 argc = 0;
|
||||
if (aArguments) {
|
||||
// If aArguments is not already an array, make it one.
|
||||
argsArray = do_QueryInterface(aArguments);
|
||||
if (argsArray == nsnull) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> tempArray =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
tempArray->AppendElement(aArguments, PR_FALSE);
|
||||
argsArray = do_QueryInterface(tempArray);
|
||||
NS_ENSURE_TRUE(argsArray != nsnull, NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
argsArray->GetLength(&argc);
|
||||
}
|
||||
|
||||
return rv;
|
||||
PRBool dialog = argc == 0 ? PR_FALSE : PR_TRUE;
|
||||
return OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, dialog,
|
||||
argsArray, PR_FALSE, _retval);
|
||||
}
|
||||
|
||||
struct SizeSpec {
|
||||
|
@ -450,11 +427,10 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
|
|||
const char *aName,
|
||||
const char *aFeatures,
|
||||
PRBool aDialog,
|
||||
PRUint32 argc,
|
||||
jsval *argv,
|
||||
nsIArray *argv,
|
||||
nsIDOMWindow **_retval)
|
||||
{
|
||||
return OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, aDialog, argc,
|
||||
return OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, aDialog,
|
||||
argv, PR_TRUE, _retval);
|
||||
}
|
||||
|
||||
|
@ -464,8 +440,7 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
|
|||
const char *aName,
|
||||
const char *aFeatures,
|
||||
PRBool aDialog,
|
||||
PRUint32 argc,
|
||||
jsval *argv,
|
||||
nsIArray *argv,
|
||||
PRBool aCalledFromJS,
|
||||
nsIDOMWindow **_retval)
|
||||
{
|
||||
|
@ -692,12 +667,12 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
|
|||
}
|
||||
}
|
||||
|
||||
if (aDialog && argc > 0) {
|
||||
rv = AttachArguments(*_retval, argc, argv);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (aDialog && argv > 0) {
|
||||
// Set the args on the new object.
|
||||
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_QueryInterface(*_retval));
|
||||
NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_UNEXPECTED);
|
||||
rv = scriptGlobal->SetNewArguments(argv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
/* allow a window that we found by name to keep its name (important for cases
|
||||
|
@ -1842,342 +1817,6 @@ nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem *aDocShellItem,
|
|||
treeOwnerAsWin->SetVisibility(PR_TRUE);
|
||||
}
|
||||
|
||||
// attach the given array of JS values to the given window, as a property array
|
||||
// named "arguments"
|
||||
nsresult
|
||||
nsWindowWatcher::AttachArguments(nsIDOMWindow *aWindow,
|
||||
PRUint32 argc, jsval *argv)
|
||||
{
|
||||
if (argc == 0)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIScriptGlobalObject> scriptGlobal(do_QueryInterface(aWindow));
|
||||
NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// Just ask the global to attach the args for us
|
||||
return scriptGlobal->SetNewArguments(argc, NS_STATIC_CAST(void*, argv));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWindowWatcher::ConvertSupportsTojsvals(nsIDOMWindow *aWindow,
|
||||
nsISupports *aArgs,
|
||||
PRUint32 *aArgc, jsval **aArgv,
|
||||
JSContext **aUsedContext,
|
||||
void **aMarkp,
|
||||
nsIScriptContext **aScriptContext)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
*aArgv = nsnull;
|
||||
*aArgc = 0;
|
||||
|
||||
// copy the elements in aArgsArray into the JS array
|
||||
// window.arguments in the new window
|
||||
|
||||
if (!aArgs)
|
||||
return NS_OK;
|
||||
|
||||
PRUint32 argCtr, argCount;
|
||||
nsCOMPtr<nsISupportsArray> argsArray(do_QueryInterface(aArgs));
|
||||
|
||||
if (argsArray) {
|
||||
argsArray->Count(&argCount);
|
||||
if (argCount == 0)
|
||||
return NS_OK;
|
||||
} else
|
||||
argCount = 1; // the nsISupports which is not an array
|
||||
|
||||
JSContext *cx;
|
||||
JSContextAutoPopper contextGuard;
|
||||
|
||||
cx = GetJSContextFromWindow(aWindow);
|
||||
if (cx) {
|
||||
// Our caller needs to hold a strong ref to keep this context alive.
|
||||
*aScriptContext = GetScriptContextFromJSContext(cx);
|
||||
NS_ASSERTION(*aScriptContext,
|
||||
"The window's context doesn't have a script context?");
|
||||
NS_ADDREF(*aScriptContext);
|
||||
} else {
|
||||
*aScriptContext = nsnull;
|
||||
}
|
||||
if (!cx)
|
||||
cx = GetJSContextFromCallStack();
|
||||
if (!cx) {
|
||||
rv = contextGuard.Push();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
cx = contextGuard.get();
|
||||
}
|
||||
|
||||
jsval *argv = js_AllocStack(cx, argCount, aMarkp);
|
||||
NS_ENSURE_TRUE(argv, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (argsArray)
|
||||
for (argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) {
|
||||
nsCOMPtr<nsISupports> s(dont_AddRef(argsArray->ElementAt(argCtr)));
|
||||
rv = AddSupportsTojsvals(s, cx, argv + argCtr);
|
||||
}
|
||||
else
|
||||
rv = AddSupportsTojsvals(aArgs, cx, argv);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
js_FreeStack(cx, *aMarkp);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aUsedContext = cx;
|
||||
*aArgv = argv;
|
||||
*aArgc = argCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWindowWatcher::AddInterfaceTojsvals(nsISupports *aArg,
|
||||
JSContext *cx,
|
||||
jsval *aArgv)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||
rv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx), aArg,
|
||||
NS_GET_IID(nsISupports), getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject *obj;
|
||||
rv = wrapper->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aArgv = OBJECT_TO_JSVAL(obj);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWindowWatcher::AddSupportsTojsvals(nsISupports *aArg,
|
||||
JSContext *cx, jsval *aArgv)
|
||||
{
|
||||
if (!aArg) {
|
||||
*aArgv = JSVAL_NULL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupportsPrimitive> argPrimitive(do_QueryInterface(aArg));
|
||||
if (!argPrimitive)
|
||||
return AddInterfaceTojsvals(aArg, cx, aArgv);
|
||||
|
||||
PRUint16 type;
|
||||
argPrimitive->GetType(&type);
|
||||
|
||||
switch(type) {
|
||||
case nsISupportsPrimitive::TYPE_CSTRING : {
|
||||
nsCOMPtr<nsISupportsCString> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCAutoString data;
|
||||
|
||||
p->GetData(data);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSString *str = ::JS_NewStringCopyN(cx, data.get(), data.Length());
|
||||
NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*aArgv = STRING_TO_JSVAL(str);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_STRING : {
|
||||
nsCOMPtr<nsISupportsString> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAutoString data;
|
||||
|
||||
p->GetData(data);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
// cast is probably safe since wchar_t and jschar are expected
|
||||
// to be equivalent; both unsigned 16-bit entities
|
||||
JSString *str =
|
||||
::JS_NewUCStringCopyN(cx,
|
||||
NS_REINTERPRET_CAST(const jschar *,data.get()),
|
||||
data.Length());
|
||||
NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*aArgv = STRING_TO_JSVAL(str);
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRBOOL : {
|
||||
nsCOMPtr<nsISupportsPRBool> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRBool data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = BOOLEAN_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRUINT8 : {
|
||||
nsCOMPtr<nsISupportsPRUint8> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRUint8 data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = INT_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRUINT16 : {
|
||||
nsCOMPtr<nsISupportsPRUint16> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRUint16 data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = INT_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRUINT32 : {
|
||||
nsCOMPtr<nsISupportsPRUint32> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRUint32 data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = INT_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_CHAR : {
|
||||
nsCOMPtr<nsISupportsChar> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
char data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSString *str = ::JS_NewStringCopyN(cx, &data, 1);
|
||||
NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*aArgv = STRING_TO_JSVAL(str);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRINT16 : {
|
||||
nsCOMPtr<nsISupportsPRInt16> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRInt16 data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = INT_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_PRINT32 : {
|
||||
nsCOMPtr<nsISupportsPRInt32> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRInt32 data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
*aArgv = INT_TO_JSVAL(data);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_FLOAT : {
|
||||
nsCOMPtr<nsISupportsFloat> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
float data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
jsdouble *d = ::JS_NewDouble(cx, data);
|
||||
|
||||
*aArgv = DOUBLE_TO_JSVAL(d);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_DOUBLE : {
|
||||
nsCOMPtr<nsISupportsDouble> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
double data;
|
||||
|
||||
p->GetData(&data);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
jsdouble *d = ::JS_NewDouble(cx, data);
|
||||
|
||||
*aArgv = DOUBLE_TO_JSVAL(d);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_INTERFACE_POINTER : {
|
||||
nsCOMPtr<nsISupportsInterfacePointer> p(do_QueryInterface(argPrimitive));
|
||||
NS_ENSURE_TRUE(p, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsISupports> data;
|
||||
nsIID *iid = nsnull;
|
||||
|
||||
p->GetData(getter_AddRefs(data));
|
||||
p->GetDataIID(&iid);
|
||||
NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
|
||||
|
||||
AutoFree iidGuard(iid); // Free iid upon destruction.
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
|
||||
rv = xpc->WrapNative(cx, ::JS_GetGlobalObject(cx), data,
|
||||
*iid, getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject *obj;
|
||||
rv = wrapper->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aArgv = OBJECT_TO_JSVAL(obj);
|
||||
|
||||
break;
|
||||
}
|
||||
case nsISupportsPrimitive::TYPE_ID :
|
||||
case nsISupportsPrimitive::TYPE_PRUINT64 :
|
||||
case nsISupportsPrimitive::TYPE_PRINT64 :
|
||||
case nsISupportsPrimitive::TYPE_PRTIME :
|
||||
case nsISupportsPrimitive::TYPE_VOID : {
|
||||
NS_WARNING("Unsupported primitive type used");
|
||||
*aArgv = JSVAL_NULL;
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
NS_WARNING("Unknown primitive type used");
|
||||
*aArgv = JSVAL_NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowWatcher::GetWindowTreeItem(nsIDOMWindow *inWindow,
|
||||
nsIDocShellTreeItem **outTreeItem)
|
||||
|
|
|
@ -104,8 +104,7 @@ private:
|
|||
const char *aName,
|
||||
const char *aFeatures,
|
||||
PRBool aDialog,
|
||||
PRUint32 argc,
|
||||
jsval *argv,
|
||||
nsIArray *argv,
|
||||
PRBool aCalledFromJS,
|
||||
nsIDOMWindow **_retval);
|
||||
|
||||
|
@ -134,18 +133,6 @@ private:
|
|||
static void SizeOpenedDocShellItem(nsIDocShellTreeItem *aDocShellItem,
|
||||
nsIDOMWindow *aParent,
|
||||
const SizeSpec & aSizeSpec);
|
||||
static nsresult AttachArguments(nsIDOMWindow *aWindow,
|
||||
PRUint32 argc, jsval *argv);
|
||||
static nsresult ConvertSupportsTojsvals(nsIDOMWindow *aWindow,
|
||||
nsISupports *aArgs,
|
||||
PRUint32 *aArgc, jsval **aArgv,
|
||||
JSContext **aUsedContext,
|
||||
void **aMarkp,
|
||||
nsIScriptContext **aScriptContext);
|
||||
static nsresult AddSupportsTojsvals(nsISupports *aArg,
|
||||
JSContext *cx, jsval *aArgv);
|
||||
static nsresult AddInterfaceTojsvals(nsISupports *aArg,
|
||||
JSContext *cx, jsval *aArgv);
|
||||
static void GetWindowTreeItem(nsIDOMWindow *inWindow,
|
||||
nsIDocShellTreeItem **outTreeItem);
|
||||
static void GetWindowTreeOwner(nsIDOMWindow *inWindow,
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "nsICSSStyleSheet.h"
|
||||
#include "nsDOMAttribute.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsDOMScriptObjectFactory.h"
|
||||
#include "nsEventListenerManager.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsGenericElement.h" // for nsDOMEventRTTearoff
|
||||
|
@ -62,7 +63,6 @@
|
|||
#include "nsGlobalWindow.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsImageFrame.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsLayoutStylesheetCache.h"
|
||||
#include "nsNodeInfo.h"
|
||||
|
@ -118,7 +118,7 @@ nsLayoutStatics::Initialize()
|
|||
|
||||
nsresult rv;
|
||||
|
||||
nsJSEnvironment::Startup();
|
||||
nsDOMScriptObjectFactory::Startup();
|
||||
rv = nsContentUtils::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize nsContentUtils");
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
static NS_DEFINE_CID(kJVMManagerCID, NS_JVMMANAGER_CID);
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
|
|
|
@ -65,6 +65,10 @@ interface nsIProgrammingLanguage : nsISupports
|
|||
const PRUint32 JAVA = 5;
|
||||
const PRUint32 ZX81_BASIC = 6; // it could happen :)
|
||||
const PRUint32 JAVASCRIPT2 = 7;
|
||||
const PRUint32 RUBY = 8;
|
||||
const PRUint32 PHP = 9;
|
||||
const PRUint32 TCL = 10;
|
||||
// This list can grow indefinitely. Just don't ever change an existing item.
|
||||
const PRUint32 MAX = 10; // keep this as the largest index.
|
||||
|
||||
};
|
||||
|
|
|
@ -141,7 +141,7 @@ typedef PRUint32 NSFastLoadOID; // nsFastLoadFooter::mObjectMap index
|
|||
|
||||
#define MFL_FILE_VERSION_0 0
|
||||
#define MFL_FILE_VERSION_1 1000
|
||||
#define MFL_FILE_VERSION 4 // fix to note singletons in object map
|
||||
#define MFL_FILE_VERSION 5 // multiple script languages
|
||||
|
||||
/**
|
||||
* Compute Fletcher's 16-bit checksum over aLength bytes starting at aBuffer,
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsInstallTrigger.h"
|
||||
#include "nsXPITriggerInfo.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
|
Загрузка…
Ссылка в новой задаче