зеркало из https://github.com/mozilla/gecko-dev.git
Bug 20786. Use function object, rather than function, as the thing which is executed, ensuring that the correct bindings are used when the function is shared across several contexts. This checkin is really brendan@mozilla.org; I'm just landing the code.
This commit is contained in:
Родитель
6461895004
Коммит
ec2655c506
|
@ -133,27 +133,40 @@ public:
|
|||
|
||||
/**
|
||||
* Compile the event handler named by atom aName, with function body aBody
|
||||
* into a function returned on success via *aFunction. Bind the lowercase
|
||||
* into a function object returned if ok via *aFunObj. Bind the lowercase
|
||||
* ASCII name to the function in scope aObj, or in the context's global if
|
||||
* aObj is null.
|
||||
*
|
||||
* @param aObj an object telling the scope in which to bind the compiled
|
||||
* event handler function, or nsnull to use a default scope
|
||||
* event handler function.
|
||||
* @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 aBody the event handler function's body
|
||||
* @param aFunction the out parameter in which a void pointer to the compiled
|
||||
* function is returned on success; may be null, meaning "don't care"
|
||||
* @param aFunObj 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 care.
|
||||
*
|
||||
* @return NS_OK if the function body was valid and got compiled
|
||||
*/
|
||||
NS_IMETHOD CompileEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aFunction) = 0;
|
||||
void** aFunObj) = 0;
|
||||
|
||||
NS_IMETHOD CallFunction(void *aObj, void *aFunction,
|
||||
/**
|
||||
* Call the function object with given args and return its boolean result,
|
||||
* or true if the result isn't boolean.
|
||||
*
|
||||
* @param aObj an object telling the scope in which to bind the compiled
|
||||
* event handler function.
|
||||
* @param aFunObj 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.
|
||||
**/
|
||||
NS_IMETHOD CallFunctionObject(void *aObj, void *aFunObj,
|
||||
PRUint32 argc, void *argv,
|
||||
PRBool *aBoolResult) = 0;
|
||||
|
||||
|
@ -167,13 +180,13 @@ public:
|
|||
* @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 aFunction the function to name, created by an earlier call to
|
||||
* @param aFunObj the function object to name, created by an earlier call to
|
||||
* CompileEventHandler
|
||||
* @return NS_OK if the function was successfully bound to the name
|
||||
*/
|
||||
NS_IMETHOD BindCompiledEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
void *aFunction) = 0;
|
||||
void *aFunObj) = 0;
|
||||
|
||||
/**
|
||||
* Set the default scripting language version for this context, which must
|
||||
|
|
|
@ -1853,8 +1853,7 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
|
|||
lateness = PR_IntervalToMilliseconds(lateness);
|
||||
timeout->argv[timeout->argc] = INT_TO_JSVAL((jsint)lateness);
|
||||
PRBool aBoolResult;
|
||||
JSFunction* fun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(timeout->funobj));
|
||||
rv = mContext->CallFunction(mScriptObject, fun,
|
||||
rv = mContext->CallFunctionObject(mScriptObject, timeout->funobj,
|
||||
timeout->argc + 1, timeout->argv,
|
||||
&aBoolResult);
|
||||
}
|
||||
|
|
|
@ -471,7 +471,7 @@ AtomToEventHandlerName(nsIAtom *aName, char *charName, PRUint32 charNameSize)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::CompileEventHandler(void *aObj, nsIAtom *aName, const nsString& aBody,
|
||||
void** aFunction)
|
||||
void** aFunObj)
|
||||
{
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
|
@ -502,13 +502,13 @@ nsJSContext::CompileEventHandler(void *aObj, nsIAtom *aName, const nsString& aBo
|
|||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
if (!fun)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (aFunction)
|
||||
*aFunction = (void*) fun;
|
||||
if (aFunObj)
|
||||
*aFunObj = (void*) JS_GetFunctionObject(fun);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::CallFunction(void *aObj, void *aFunction, PRUint32 argc,
|
||||
nsJSContext::CallFunctionObject(void *aObj, void *aFunObj, PRUint32 argc,
|
||||
void *argv, PRBool *aBoolResult)
|
||||
{
|
||||
// This one's a lot easier than EvaluateString because we don't have to
|
||||
|
@ -519,8 +519,11 @@ nsJSContext::CallFunction(void *aObj, void *aFunction, PRUint32 argc,
|
|||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
jsval funval = OBJECT_TO_JSVAL(aFunObj);
|
||||
JSFunction* fun = JS_ValueToFunction(mContext, funval);
|
||||
|
||||
PRBool ok;
|
||||
rv = securityManager->CanExecuteFunction((JSFunction *)aFunction, &ok);
|
||||
rv = securityManager->CanExecuteFunction(fun, &ok);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -533,7 +536,7 @@ nsJSContext::CallFunction(void *aObj, void *aFunction, PRUint32 argc,
|
|||
|
||||
jsval val;
|
||||
if (ok) {
|
||||
ok = JS_CallFunction(mContext, (JSObject *)aObj, (JSFunction *)aFunction,
|
||||
ok = JS_CallFunctionValue(mContext, (JSObject *)aObj, funval,
|
||||
argc, (jsval *)argv, &val);
|
||||
}
|
||||
*aBoolResult = ok
|
||||
|
@ -549,17 +552,13 @@ nsJSContext::CallFunction(void *aObj, void *aFunction, PRUint32 argc,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::BindCompiledEventHandler(void *aObj, nsIAtom *aName, void *aFunction)
|
||||
nsJSContext::BindCompiledEventHandler(void *aObj, nsIAtom *aName, void *aFunObj)
|
||||
{
|
||||
char charName[64];
|
||||
AtomToEventHandlerName(aName, charName, sizeof charName);
|
||||
|
||||
JSObject *funobj = JS_GetFunctionObject((JSFunction *)aFunction);
|
||||
if (!funobj)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!::JS_DefineProperty(mContext, (JSObject *)aObj, charName,
|
||||
OBJECT_TO_JSVAL(funobj), nsnull, nsnull,
|
||||
OBJECT_TO_JSVAL(aFunObj), nsnull, nsnull,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -82,13 +82,13 @@ public:
|
|||
NS_IMETHOD CompileEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aFunction);
|
||||
NS_IMETHOD CallFunction(void *aObj, void *aFunction,
|
||||
void** aFunObj);
|
||||
NS_IMETHOD CallFunctionObject(void *aObj, void *aFunObj,
|
||||
PRUint32 argc, void *argv,
|
||||
PRBool *aBoolResult);
|
||||
NS_IMETHOD BindCompiledEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
void *aFunction);
|
||||
void *aFunObj);
|
||||
NS_IMETHOD SetDefaultLanguageVersion(const char* aVersion);
|
||||
NS_IMETHOD_(nsIScriptGlobalObject*) GetGlobalObject();
|
||||
NS_IMETHOD_(void*) GetNativeContext();
|
||||
|
|
|
@ -184,7 +184,7 @@ nsJSUtils::nsLookupGlobalName(nsISupports* aSupports,
|
|||
nsresult result;
|
||||
|
||||
if (JSVAL_IS_STRING(aId)) {
|
||||
JSString* jsstring = JS_ValueToString(aContext, aId);
|
||||
JSString* jsstring = JSVAL_TO_STRING(aId);
|
||||
nsAutoString name(JS_GetStringChars(jsstring));
|
||||
nsIScriptNameSpaceManager* manager;
|
||||
nsIScriptContext* scriptContext = (nsIScriptContext*)JS_GetContextPrivate(aContext);
|
||||
|
@ -441,11 +441,10 @@ nsJSUtils::nsConvertJSValToFunc(nsIDOMEventListener** aListener,
|
|||
*aListener = nsnull;
|
||||
}
|
||||
else if (JSVAL_IS_OBJECT(aValue)) {
|
||||
JSFunction* jsfun = JS_ValueToFunction(aContext, aValue);
|
||||
if (jsfun){
|
||||
if (JS_TypeOfValue(aContext, aValue) == JSTYPE_FUNCTION){
|
||||
nsIScriptContext* scriptContext = (nsIScriptContext*)JS_GetContextPrivate(aContext);
|
||||
|
||||
if (NS_OK == NS_NewScriptEventListener(aListener, scriptContext, (void*)aObj, (void*)jsfun)) {
|
||||
if (NS_OK == NS_NewScriptEventListener(aListener, scriptContext, (void*)aObj, (void*)JSVAL_TO_OBJECT(aValue))) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
else {
|
||||
|
@ -454,7 +453,7 @@ nsJSUtils::nsConvertJSValToFunc(nsIDOMEventListener** aListener,
|
|||
}
|
||||
}
|
||||
else {
|
||||
JS_ReportError(aContext, "Parameter isn't a object");
|
||||
JS_ReportError(aContext, "Parameter isn't a callable object");
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -513,7 +512,7 @@ nsJSUtils::nsGlobalResolve(JSContext* aContext,
|
|||
jsval val;
|
||||
|
||||
if (JSVAL_IS_STRING(aId)) {
|
||||
JSString* jsstring = JS_ValueToString(aContext, aId);
|
||||
JSString* jsstring = JSVAL_TO_STRING(aId);
|
||||
nsAutoString name(JS_GetStringChars(jsstring));
|
||||
nsIScriptNameSpaceManager* manager;
|
||||
nsIScriptContext* scriptContext = (nsIScriptContext*)JS_GetContextPrivate(aContext);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "nsString.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
static NS_DEFINE_IID(kIScriptEventListenerIID, NS_ISCRIPTEVENTLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
|
||||
|
@ -31,12 +32,12 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|||
/*
|
||||
* nsJSDOMEventListener implementation
|
||||
*/
|
||||
nsJSDOMEventListener::nsJSDOMEventListener(JSContext *aContext, JSObject *aObj, JSFunction *aFun)
|
||||
nsJSDOMEventListener::nsJSDOMEventListener(JSContext *aContext, JSObject *aScopeObj, JSObject *aFunObj)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mContext = aContext;
|
||||
mJSObj = aObj;
|
||||
mJSFun = aFun;
|
||||
mScopeObj = aScopeObj;
|
||||
mFunObj = aFunObj;
|
||||
}
|
||||
|
||||
nsJSDOMEventListener::~nsJSDOMEventListener()
|
||||
|
@ -82,7 +83,7 @@ nsresult nsJSDOMEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
|
||||
argv[0] = OBJECT_TO_JSVAL(eventObj);
|
||||
PRBool jsBoolResult;
|
||||
if (NS_FAILED(mScriptCX->CallFunction(mJSObj, mJSFun, 1, argv, &jsBoolResult))) {
|
||||
if (NS_FAILED(mScriptCX->CallFunctionObject(mScopeObj, mFunObj, 1, argv, &jsBoolResult))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return jsBoolResult ? NS_OK : NS_ERROR_FAILURE;
|
||||
|
@ -97,11 +98,11 @@ nsresult nsJSDOMEventListener::CheckIfEqual(nsIScriptEventListener *aListener)
|
|||
* Factory functions
|
||||
*/
|
||||
|
||||
extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void* aObj, void *aFun)
|
||||
extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void* aScopeObj, void *aFunObj)
|
||||
{
|
||||
JSContext *mCX = (JSContext*)aContext->GetNativeContext();
|
||||
|
||||
nsJSDOMEventListener* it = new nsJSDOMEventListener(mCX, (JSObject*)aObj, (JSFunction*)aFun);
|
||||
nsJSDOMEventListener* it = new nsJSDOMEventListener(mCX, (JSObject*)aScopeObj, (JSObject*)aFunObj);
|
||||
if (NULL == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
//nsIDOMMouseListener interface
|
||||
class nsJSDOMEventListener : public nsIDOMEventListener, public nsIScriptEventListener {
|
||||
public:
|
||||
nsJSDOMEventListener(JSContext *aContext, JSObject *aObj, JSFunction *aFun);
|
||||
nsJSDOMEventListener(JSContext *aContext, JSObject *aScopeObj, JSObject *aFunObj);
|
||||
virtual ~nsJSDOMEventListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -44,8 +44,8 @@ public:
|
|||
|
||||
protected:
|
||||
JSContext *mContext;
|
||||
JSObject *mJSObj;
|
||||
JSFunction *mJSFun;
|
||||
JSObject *mScopeObj;
|
||||
JSObject *mFunObj;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -124,13 +124,8 @@ nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
}
|
||||
|
||||
argv[0] = OBJECT_TO_JSVAL(eventObj);
|
||||
JSFunction *jsFun = JS_ValueToFunction(cx, funval);
|
||||
PRBool jsBoolResult;
|
||||
if (!jsFun)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
result = mContext->CallFunction(obj, jsFun, 1, argv, &jsBoolResult);
|
||||
result = mContext->CallFunctionObject(obj, (void*) JSVAL_TO_OBJECT(funval), 1, argv, &jsBoolResult);
|
||||
if (NS_FAILED(result)) {
|
||||
return result;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче