- Rename "FunctionObject" or shorthands to "EventHandler" to make nsIScriptContext more scripting-language-neutral.

- Allow nsIScriptContext::BindEventHandler to take a null void* handler argument, to remove the binding by nullifying it (for hyatt's XML-driven-key-mapping work). 
- Try to GetCompiledEventHandler (and if we don't, and compile it, Put too) for the load event and other non-deferred (XUL window-level) event listeners. 
- Improve doc comments and whitespace.
This commit is contained in:
brendan%mozilla.org 1999-12-07 22:14:17 +00:00
Родитель 147cebd2d6
Коммит c939085774
10 изменённых файлов: 130 добавлений и 83 удалений

Просмотреть файл

@ -552,9 +552,28 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
rv = aScriptObjectOwner->GetScriptObject(aContext, (void**)&scriptObject);
if (NS_FAILED(rv))
return rv;
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, nsnull);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner = do_QueryInterface(aScriptObjectOwner);
void *handler = nsnull;
PRBool done = PR_FALSE;
if (handlerOwner) {
rv = handlerOwner->GetCompiledEventHandler(aName, &handler);
if (NS_SUCCEEDED(rv) && handler) {
rv = aContext->BindCompiledEventHandler(scriptObject, aName, handler);
if (NS_FAILED(rv))
return rv;
done = PR_TRUE;
}
}
if (!done) {
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, &handler);
if (NS_FAILED(rv))
return rv;
if (handlerOwner)
handlerOwner->SetCompiledEventHandler(aName, handler);
}
}
return SetJSEventListener(aContext, aScriptObjectOwner, aName, aIID, aDeferCompilation);
}

Просмотреть файл

@ -63,8 +63,8 @@ public:
* Compile and execute a script.
*
* @param aScript a string representing the script to be executed
* @param aObj a JavaScript JSObject for the scope to execute in, or nsnull
* to use a default scope
* @param aScopeObject a JavaScript JSObject 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
* @param aLineNo the starting line number for the script for error messages
@ -77,7 +77,7 @@ public:
*
**/
NS_IMETHOD EvaluateString(const nsString& aScript,
void *aObj,
void *aScopeObject,
nsIPrincipal *aPrincipal,
const char *aURL,
PRUint32 aLineNo,
@ -105,9 +105,9 @@ public:
**/
NS_IMETHOD CompileScript(const PRUnichar* aText,
PRInt32 aTextLength,
void *aScopeObject,
nsIPrincipal *aPrincipal,
const char *aURL,
void* aScopeObject,
nsIPrincipal* aPrincipal,
const char* aURL,
PRUint32 aLineNo,
const char* aVersion,
void** aScriptObject) = 0;
@ -127,66 +127,65 @@ public:
*
*/
NS_IMETHOD ExecuteScript(void* aScriptObject,
void *aScopeObject,
void* aScopeObject,
nsString* aRetValue,
PRBool* aIsUndefined) = 0;
/**
* Compile the event handler named by atom aName, with function body aBody
* 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.
* into a function object returned if ok via *aHandler. Bind the lowercase
* ASCII name to the function in its parent object aTarget.
*
* @param aObj an object telling the scope in which to bind the compiled
* event handler function.
* @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!
* @param aBody the event handler function's body
* @param aFunObj the out parameter in which a void pointer to the compiled
* @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 care.
* caller doesn't need to store the handler for later use.
*
* @return NS_OK if the function body was valid and got compiled
*/
NS_IMETHOD CompileEventHandler(void *aObj,
nsIAtom *aName,
NS_IMETHOD CompileEventHandler(void* aTarget,
nsIAtom* aName,
const nsString& aBody,
void** aFunObj) = 0;
void** aHandler) = 0;
/**
* 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 aTarget an object telling the scope in which to bind 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.
**/
NS_IMETHOD CallFunctionObject(void *aObj, void *aFunObj,
PRUint32 argc, void *argv,
PRBool *aBoolResult) = 0;
NS_IMETHOD CallEventHandler(void* aTarget, void* aHandler,
PRUint32 argc, void* argv,
PRBool* aBoolResult) = 0;
/**
* Bind an already-compiled event handler function to a name in the given
* scope object. The same restrictions on aName (lowercase ASCII, not too
* long) applies here as for CompileEventHandler.
*
* @param aObj an object telling the scope in which to bind the compiled
* event handler function
* @param aTarget an object telling the scope in which to bind the compiled
* 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 aFunObj the function object to name, created by an earlier call to
* @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
*/
NS_IMETHOD BindCompiledEventHandler(void *aObj,
nsIAtom *aName,
void *aFunObj) = 0;
NS_IMETHOD BindCompiledEventHandler(void* aTarget,
nsIAtom* aName,
void* aHandler) = 0;
/**
* Set the default scripting language version for this context, which must

Просмотреть файл

@ -49,6 +49,10 @@ public:
};
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 *aTarget,
void *aHandler);
#endif // nsIScriptEventListener_h__

Просмотреть файл

@ -1853,9 +1853,9 @@ GlobalWindowImpl::RunTimeout(nsTimeoutImpl *aTimeout)
lateness = PR_IntervalToMilliseconds(lateness);
timeout->argv[timeout->argc] = INT_TO_JSVAL((jsint)lateness);
PRBool aBoolResult;
rv = mContext->CallFunctionObject(mScriptObject, timeout->funobj,
timeout->argc + 1, timeout->argv,
&aBoolResult);
rv = mContext->CallEventHandler(mScriptObject, timeout->funobj,
timeout->argc + 1, timeout->argv,
&aBoolResult);
}
if (NS_FAILED(rv)) {
NS_RELEASE(temp);

Просмотреть файл

@ -198,7 +198,7 @@ nsJSContext::EvaluateString(const nsString& aScript,
NS_IMETHODIMP
nsJSContext::EvaluateString(const nsString& aScript,
void *jsObj,
void *aScopeObject,
nsIPrincipal *aPrincipal,
const char *aURL,
PRUint32 aLineNo,
@ -207,8 +207,8 @@ nsJSContext::EvaluateString(const nsString& aScript,
PRBool* aIsUndefined)
{
nsresult rv;
if (!jsObj)
jsObj = JS_GetGlobalObject(mContext);
if (!aScopeObject)
aScopeObject = JS_GetGlobalObject(mContext);
// Safety first: get an object representing the script's principals, i.e.,
// the entities who signed this script, or the fully-qualified-domain-name
@ -275,7 +275,7 @@ nsJSContext::EvaluateString(const nsString& aScript,
mRef = nsnull;
mTerminationFunc = nsnull;
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
(JSObject *)jsObj,
(JSObject *)aScopeObject,
jsprin,
(jschar*)aScript.GetUnicode(),
aScript.Length(),
@ -470,8 +470,8 @@ AtomToEventHandlerName(nsIAtom *aName, char *charName, PRUint32 charNameSize)
}
NS_IMETHODIMP
nsJSContext::CompileEventHandler(void *aObj, nsIAtom *aName, const nsString& aBody,
void** aFunObj)
nsJSContext::CompileEventHandler(void *aTarget, nsIAtom *aName, const nsString& aBody,
void** aHandler)
{
JSPrincipals *jsprin = nsnull;
@ -490,26 +490,27 @@ nsJSContext::CompileEventHandler(void *aObj, nsIAtom *aName, const nsString& aBo
char charName[64];
AtomToEventHandlerName(aName, charName, sizeof charName);
JSFunction* fun = JS_CompileUCFunctionForPrincipals(mContext,
(JSObject*)aObj, jsprin,
charName, 1, gEventArgv,
(jschar*)aBody.GetUnicode(),
aBody.Length(),
//XXXbe filename, lineno:
nsnull, 0);
JSFunction* fun =
JS_CompileUCFunctionForPrincipals(mContext,
(JSObject*)aTarget, jsprin,
charName, 1, gEventArgv,
(jschar*)aBody.GetUnicode(),
aBody.Length(),
//XXXbe filename, lineno:
nsnull, 0);
if (jsprin)
JSPRINCIPALS_DROP(mContext, jsprin);
if (!fun)
return NS_ERROR_FAILURE;
if (aFunObj)
*aFunObj = (void*) JS_GetFunctionObject(fun);
if (aHandler)
*aHandler = (void*) JS_GetFunctionObject(fun);
return NS_OK;
}
NS_IMETHODIMP
nsJSContext::CallFunctionObject(void *aObj, void *aFunObj, PRUint32 argc,
void *argv, PRBool *aBoolResult)
nsJSContext::CallEventHandler(void *aTarget, void *aHandler, PRUint32 argc,
void *argv, PRBool *aBoolResult)
{
// This one's a lot easier than EvaluateString because we don't have to
// hassle with principals: they're already compiled into the JS function.
@ -519,7 +520,7 @@ nsJSContext::CallFunctionObject(void *aObj, void *aFunObj, PRUint32 argc,
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
jsval funval = OBJECT_TO_JSVAL(aFunObj);
jsval funval = OBJECT_TO_JSVAL(aHandler);
JSFunction* fun = JS_ValueToFunction(mContext, funval);
PRBool ok;
@ -542,7 +543,7 @@ nsJSContext::CallFunctionObject(void *aObj, void *aFunObj, PRUint32 argc,
jsval val;
if (ok) {
ok = JS_CallFunctionValue(mContext, (JSObject *)aObj, funval,
ok = JS_CallFunctionValue(mContext, (JSObject *)aTarget, funval,
argc, (jsval *)argv, &val);
}
*aBoolResult = ok
@ -558,16 +559,16 @@ nsJSContext::CallFunctionObject(void *aObj, void *aFunObj, PRUint32 argc,
}
NS_IMETHODIMP
nsJSContext::BindCompiledEventHandler(void *aObj, nsIAtom *aName, void *aFunObj)
nsJSContext::BindCompiledEventHandler(void *aTarget, nsIAtom *aName, void *aHandler)
{
char charName[64];
AtomToEventHandlerName(aName, charName, sizeof charName);
JSObject *funobj = (JSObject*) aFunObj;
JSObject *target = (JSObject*) aObj;
JSObject *funobj = (JSObject*) aHandler;
JSObject *target = (JSObject*) aTarget;
// Make sure the handler function is parented by its event target object
if (JS_GetParent(mContext, funobj) != target) {
if (funobj && JS_GetParent(mContext, funobj) != target) {
funobj = JS_CloneFunctionObject(mContext, funobj, target);
if (!funobj)
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -60,7 +60,7 @@ public:
nsString& aRetValue,
PRBool* aIsUndefined);
NS_IMETHOD EvaluateString(const nsString& aScript,
void *aObj,
void *aScopeObject,
nsIPrincipal *principal,
const char *aURL,
PRUint32 aLineNo,
@ -69,7 +69,7 @@ public:
PRBool* aIsUndefined);
NS_IMETHOD CompileScript(const PRUnichar* aText,
PRInt32 aTextLength,
void *aScopeObj,
void *aScopeObject,
nsIPrincipal *principal,
const char *aURL,
PRUint32 aLineNo,
@ -79,16 +79,17 @@ public:
void *aScopeObject,
nsString* aRetValue,
PRBool* aIsUndefined);
NS_IMETHOD CompileEventHandler(void *aObj,
NS_IMETHOD CompileEventHandler(void *aTarget,
nsIAtom *aName,
const nsString& aBody,
void** aFunObj);
NS_IMETHOD CallFunctionObject(void *aObj, void *aFunObj,
PRUint32 argc, void *argv,
PRBool *aBoolResult);
NS_IMETHOD BindCompiledEventHandler(void *aObj,
nsIAtom *aName,
void *aFunObj);
void** aHandler);
NS_IMETHOD CallEventHandler(void *aTarget, void *aHandler,
PRUint32 argc, void *argv,
PRBool *aBoolResult);
NS_IMETHOD BindCompiledEventHandler(void *aTarget,
nsIAtom *aName,
void *aHandler);
NS_IMETHOD SetDefaultLanguageVersion(const char* aVersion);
NS_IMETHOD_(nsIScriptGlobalObject*) GetGlobalObject();
NS_IMETHOD_(void*) GetNativeContext();
@ -96,7 +97,7 @@ public:
NS_IMETHOD InitContext(nsIScriptGlobalObject *aGlobalObject);
NS_IMETHOD IsContextInitialized();
NS_IMETHOD AddNamedReference(void *aSlot, void *aScriptObject,
const char *aName);
const char *aName);
NS_IMETHOD RemoveReference(void *aSlot, void *aScriptObject);
NS_IMETHOD GC();
NS_IMETHOD GetNameSpaceManager(nsIScriptNameSpaceManager** aInstancePtr);

Просмотреть файл

@ -32,12 +32,12 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
/*
* nsJSDOMEventListener implementation
*/
nsJSDOMEventListener::nsJSDOMEventListener(JSContext *aContext, JSObject *aScopeObj, JSObject *aFunObj)
nsJSDOMEventListener::nsJSDOMEventListener(JSContext *aContext, JSObject *aTarget, JSObject *aHandler)
{
NS_INIT_REFCNT();
mContext = aContext;
mScopeObj = aScopeObj;
mFunObj = aFunObj;
mTarget = aTarget;
mHandler = aHandler;
}
nsJSDOMEventListener::~nsJSDOMEventListener()
@ -83,7 +83,7 @@ nsresult nsJSDOMEventListener::HandleEvent(nsIDOMEvent* aEvent)
argv[0] = OBJECT_TO_JSVAL(eventObj);
PRBool jsBoolResult;
if (NS_FAILED(mScriptCX->CallFunctionObject(mScopeObj, mFunObj, 1, argv, &jsBoolResult))) {
if (NS_FAILED(mScriptCX->CallEventHandler(mTarget, mHandler, 1, argv, &jsBoolResult))) {
return NS_ERROR_FAILURE;
}
return jsBoolResult ? NS_OK : NS_ERROR_FAILURE;
@ -98,11 +98,15 @@ nsresult nsJSDOMEventListener::CheckIfEqual(nsIScriptEventListener *aListener)
* Factory functions
*/
extern "C" NS_DOM nsresult NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult, nsIScriptContext *aContext, void* aScopeObj, void *aFunObj)
extern "C" NS_DOM nsresult
NS_NewScriptEventListener(nsIDOMEventListener ** aInstancePtrResult,
nsIScriptContext *aContext,
void* aTarget,
void *aHandler)
{
JSContext *mCX = (JSContext*)aContext->GetNativeContext();
nsJSDOMEventListener* it = new nsJSDOMEventListener(mCX, (JSObject*)aScopeObj, (JSObject*)aFunObj);
nsJSDOMEventListener* it = new nsJSDOMEventListener(mCX, (JSObject*)aTarget, (JSObject*)aHandler);
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 *aScopeObj, JSObject *aFunObj);
nsJSDOMEventListener(JSContext *aContext, JSObject *aTarget, JSObject *aHandler);
virtual ~nsJSDOMEventListener();
NS_DECL_ISUPPORTS
@ -44,8 +44,8 @@ public:
protected:
JSContext *mContext;
JSObject *mScopeObj;
JSObject *mFunObj;
JSObject *mTarget;
JSObject *mHandler;
};

Просмотреть файл

@ -125,7 +125,7 @@ nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
argv[0] = OBJECT_TO_JSVAL(eventObj);
PRBool jsBoolResult;
result = mContext->CallFunctionObject(obj, (void*) JSVAL_TO_OBJECT(funval), 1, argv, &jsBoolResult);
result = mContext->CallEventHandler(obj, (void*) JSVAL_TO_OBJECT(funval), 1, argv, &jsBoolResult);
if (NS_FAILED(result)) {
return result;
}

Просмотреть файл

@ -552,9 +552,28 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
rv = aScriptObjectOwner->GetScriptObject(aContext, (void**)&scriptObject);
if (NS_FAILED(rv))
return rv;
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, nsnull);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner = do_QueryInterface(aScriptObjectOwner);
void *handler = nsnull;
PRBool done = PR_FALSE;
if (handlerOwner) {
rv = handlerOwner->GetCompiledEventHandler(aName, &handler);
if (NS_SUCCEEDED(rv) && handler) {
rv = aContext->BindCompiledEventHandler(scriptObject, aName, handler);
if (NS_FAILED(rv))
return rv;
done = PR_TRUE;
}
}
if (!done) {
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, &handler);
if (NS_FAILED(rv))
return rv;
if (handlerOwner)
handlerOwner->SetCompiledEventHandler(aName, handler);
}
}
return SetJSEventListener(aContext, aScriptObjectOwner, aName, aIID, aDeferCompilation);
}