Bug 807226 part 2. Change event handlers to store WebIDL callback functions. r=smaug

This commit is contained in:
Boris Zbarsky 2012-11-09 08:00:25 -08:00
parent 3fff1fa34b
commit bf51164dc8
9 changed files with 313 additions and 72 deletions

View File

@ -525,7 +525,7 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
JSContext* aCx,
JSObject* aScopeObject,
nsIAtom* aName,
JSObject *aHandler,
const nsEventHandler& aHandler,
bool aPermitUntrustedEvents,
nsListenerStruct **aListenerStruct)
{
@ -551,8 +551,9 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
// If we don't have a script context, we're setting an event handler from
// a component or other odd scope. Ask XPConnect if it can make us an
// nsIDOMEventListener.
MOZ_ASSERT(aHandler.HasEventHandler());
rv = nsContentUtils::XPConnect()->WrapJS(aCx,
aHandler,
aHandler.Ptr()->Callable(),
NS_GET_IID(nsIDOMEventListener),
getter_AddRefs(listener));
}
@ -574,9 +575,10 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
if (scriptListener) {
scriptListener->SetHandler(aHandler);
} else {
MOZ_ASSERT(aHandler.HasEventHandler());
nsCOMPtr<nsIDOMEventListener> listener;
rv = nsContentUtils::XPConnect()->WrapJS(aCx,
aHandler,
aHandler.Ptr()->Callable(),
NS_GET_IID(nsIDOMEventListener),
getter_AddRefs(listener));
if (NS_SUCCEEDED(rv)) {
@ -587,7 +589,7 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
if (NS_SUCCEEDED(rv) && ls) {
// Set flag to indicate possible need for compilation later
ls->mHandlerIsString = !aHandler;
ls->mHandlerIsString = !aHandler.HasEventHandler();
if (aPermitUntrustedEvents) {
ls->mFlags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
}
@ -708,7 +710,7 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
JSObject* scope = global->GetGlobalJSObject();
nsListenerStruct *ls;
rv = SetEventHandlerInternal(context, nullptr, scope, aName, nullptr,
rv = SetEventHandlerInternal(context, nullptr, scope, aName, nsEventHandler(),
aPermitUntrustedEvents, &ls);
NS_ENSURE_SUCCESS(rv, rv);
@ -745,11 +747,14 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
nsresult result = NS_OK;
nsIJSEventListener *listener = aListenerStruct->GetJSListener();
NS_ASSERTION(!listener->GetHandler(), "What is there to compile?");
NS_ASSERTION(!listener->GetHandler().HasEventHandler(),
"What is there to compile?");
nsIScriptContext *context = listener->GetEventContext();
nsScriptObjectHolder<JSObject> handler(context);
nsCOMPtr<nsPIDOMWindow> win; // Will end up non-null if mTarget is a window
if (aListenerStruct->mHandlerIsString) {
// OK, we didn't find an existing compiled event handler. Flag us
// as not a string so we don't keep trying to compile strings
@ -799,7 +804,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
if (content) {
doc = content->OwnerDoc();
} else {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
win = do_QueryInterface(mTarget);
if (win) {
doc = do_QueryInterface(win->GetExtantDocument());
}
@ -849,7 +854,46 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
nsScriptObjectHolder<JSObject> boundHandler(context);
context->BindCompiledEventHandler(mTarget, listener->GetEventScope(),
handler.get(), boundHandler);
listener->SetHandler(boundHandler.get());
if (listener->EventName() == nsGkAtoms::onerror && win) {
bool ok;
JSAutoRequest ar(context->GetNativeContext());
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
new OnErrorEventHandlerNonNull(context->GetNativeContext(),
listener->GetEventScope(),
boundHandler.get(), &ok);
if (!ok) {
// JS_WrapObject failed, which means OOM allocating the JSObject.
return NS_ERROR_OUT_OF_MEMORY;
}
listener->SetHandler(handlerCallback);
} else if (listener->EventName() == nsGkAtoms::onbeforeunload) {
// XXXbz Should we really do the special beforeunload handler on
// non-Window objects? Per spec, we shouldn't even be compiling the
// beforeunload content attribute on random elements! See bug 807226.
bool ok;
JSAutoRequest ar(context->GetNativeContext());
nsRefPtr<BeforeUnloadEventHandlerNonNull> handlerCallback =
new BeforeUnloadEventHandlerNonNull(context->GetNativeContext(),
listener->GetEventScope(),
boundHandler.get(), &ok);
if (!ok) {
// JS_WrapObject failed, which means OOM allocating the JSObject.
return NS_ERROR_OUT_OF_MEMORY;
}
listener->SetHandler(handlerCallback);
} else {
bool ok;
JSAutoRequest ar(context->GetNativeContext());
nsRefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(context->GetNativeContext(),
listener->GetEventScope(),
boundHandler.get(), &ok);
if (!ok) {
// JS_WrapObject failed, which means OOM allocating the JSObject.
return NS_ERROR_OUT_OF_MEMORY;
}
listener->SetHandler(handlerCallback);
}
}
return result;
@ -1153,28 +1197,49 @@ nsEventListenerManager::SetEventHandlerToJsval(nsIAtom* aEventName,
const jsval& v,
bool aExpectScriptContext)
{
JSObject *handler;
JSObject *callable;
if (JSVAL_IS_PRIMITIVE(v) ||
!JS_ObjectIsCallable(cx, handler = JSVAL_TO_OBJECT(v))) {
!JS_ObjectIsCallable(cx, callable = JSVAL_TO_OBJECT(v))) {
RemoveEventHandler(aEventName);
return NS_OK;
}
// Now ensure that we're working in the compartment of aScope from now on.
JSAutoCompartment ac(cx, aScope);
// Rewrap the handler into the new compartment, if needed.
jsval tempVal = v;
if (!JS_WrapValue(cx, &tempVal)) {
return NS_ERROR_UNEXPECTED;
nsEventHandler handler;
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
if (aEventName == nsGkAtoms::onerror && win) {
bool ok;
nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
new OnErrorEventHandlerNonNull(cx, aScope, callable, &ok);
if (!ok) {
return NS_ERROR_OUT_OF_MEMORY;
}
handler.SetHandler(handlerCallback);
} else if (aEventName == nsGkAtoms::onbeforeunload) {
MOZ_ASSERT(win,
"Should not have onbeforeunload handlers on non-Window objects");
bool ok;
nsRefPtr<BeforeUnloadEventHandlerNonNull> handlerCallback =
new BeforeUnloadEventHandlerNonNull(cx, aScope, callable, &ok);
if (!ok) {
return NS_ERROR_OUT_OF_MEMORY;
}
handler.SetHandler(handlerCallback);
} else {
bool ok;
nsRefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(cx, aScope, callable, &ok);
if (!ok) {
return NS_ERROR_OUT_OF_MEMORY;
}
handler.SetHandler(handlerCallback);
}
handler = &tempVal.toObject();
// We might not have a script context, e.g. if we're setting a listener
// on a dead Window.
nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(aScope);
NS_ENSURE_TRUE(context || !aExpectScriptContext, NS_ERROR_FAILURE);
JSAutoCompartment ac(cx, aScope);
JSObject *scope = ::JS_GetGlobalForObject(cx, aScope);
// Untrusted events are always permitted for non-chrome script
// handlers.
@ -1201,7 +1266,12 @@ nsEventListenerManager::GetEventHandler(nsIAtom *aEventName, jsval *vp)
CompileEventHandlerInternal(ls, true, nullptr);
}
*vp = OBJECT_TO_JSVAL(listener->GetHandler());
const nsEventHandler& handler = listener->GetHandler();
if (handler.HasEventHandler()) {
*vp = OBJECT_TO_JSVAL(handler.Ptr()->Callable());
} else {
*vp = JS::NullValue();
}
}
size_t
@ -1228,7 +1298,9 @@ nsEventListenerManager::MarkForCC()
const nsListenerStruct& ls = mListeners.ElementAt(i);
nsIJSEventListener* jsl = ls.GetJSListener();
if (jsl) {
xpc_UnmarkGrayObject(jsl->GetHandler());
if (jsl->GetHandler().HasEventHandler()) {
xpc_UnmarkGrayObject(jsl->GetHandler().Ptr()->Callable());
}
xpc_UnmarkGrayObject(jsl->GetEventScope());
} else if (ls.mListenerType == eWrappedJSListener) {
xpc_TryUnmarkWrappedGrayObject(ls.mListener);

View File

@ -261,16 +261,16 @@ protected:
nsListenerStruct* FindEventHandler(uint32_t aEventType, nsIAtom* aTypeAtom);
/**
* Set the "inline" event listener for aName to aHandler. aHandler
* may be null to indicate that we should lazily get and compile the
* string for this listener. The nsListenerStruct that results, if
* any, is returned in aListenerStruct.
* Set the "inline" event listener for aName to aHandler. aHandler may be
* have no actual handler set to indicate that we should lazily get and
* compile the string for this listener. The nsListenerStruct that results,
* if any, is returned in aListenerStruct.
*/
nsresult SetEventHandlerInternal(nsIScriptContext *aContext,
JSContext* aCx,
JSObject* aScopeGlobal,
nsIAtom* aName,
JSObject *aHandler,
const nsEventHandler& aHandler,
bool aPermitUntrustedEvents,
nsListenerStruct **aListenerStruct);

View File

@ -83,7 +83,7 @@ nsEventListenerInfo::GetJSVal(JSContext* aCx, mozilla::Maybe<JSAutoCompartment>&
nsCOMPtr<nsIJSEventListener> jsl = do_QueryInterface(mListener);
if (jsl) {
JSObject *handler = jsl->GetHandler();
JSObject *handler = jsl->GetHandler().Ptr()->Callable();
if (handler) {
aAc.construct(aCx, handler);
*aJSVal = OBJECT_TO_JSVAL(handler);

View File

@ -45,8 +45,10 @@
#include "nsXBLSerialize.h"
#include "nsEventDispatcher.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/EventHandlerBinding.h"
using namespace mozilla;
using namespace mozilla::dom;
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
@ -294,11 +296,22 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventTarget* aTarget,
handler.get(), boundHandler);
NS_ENSURE_SUCCESS(rv, rv);
bool ok;
JSAutoRequest ar(boundContext->GetNativeContext());
nsRefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(boundContext->GetNativeContext(),
scope, boundHandler.get(), &ok);
if (!ok) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsEventHandler eventHandler(handlerCallback);
// Execute it.
nsCOMPtr<nsIJSEventListener> eventListener;
rv = NS_NewJSEventListener(boundContext, scope,
scriptTarget, onEventAtom,
boundHandler.get(),
eventHandler,
getter_AddRefs(eventListener));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -10,13 +10,150 @@
#include "jsapi.h"
#include "xpcpublic.h"
#include "nsIDOMEventListener.h"
class nsIAtom;
#include "nsIAtom.h"
#include "mozilla/dom/EventHandlerBinding.h"
#define NS_IJSEVENTLISTENER_IID \
{ 0x92f9212b, 0xa6aa, 0x4867, \
{ 0x93, 0x8a, 0x56, 0xbe, 0x17, 0x67, 0x4f, 0xd4 } }
class nsEventHandler
{
public:
typedef mozilla::dom::EventHandlerNonNull EventHandlerNonNull;
typedef mozilla::dom::BeforeUnloadEventHandlerNonNull
BeforeUnloadEventHandlerNonNull;
typedef mozilla::dom::OnErrorEventHandlerNonNull OnErrorEventHandlerNonNull;
typedef mozilla::dom::CallbackFunction CallbackFunction;
enum HandlerType {
eUnset = 0,
eNormal = 0x1,
eOnError = 0x2,
eOnBeforeUnload = 0x3,
eTypeBits = 0x3
};
nsEventHandler() :
mBits(0)
{}
nsEventHandler(EventHandlerNonNull* aHandler)
{
Assign(aHandler, eNormal);
}
nsEventHandler(OnErrorEventHandlerNonNull* aHandler)
{
Assign(aHandler, eOnError);
}
nsEventHandler(BeforeUnloadEventHandlerNonNull* aHandler)
{
Assign(aHandler, eOnBeforeUnload);
}
nsEventHandler(const nsEventHandler& aOther)
{
if (aOther.HasEventHandler()) {
// Have to make sure we take our own ref
Assign(aOther.Ptr(), aOther.Type());
} else {
mBits = 0;
}
}
~nsEventHandler()
{
ReleaseHandler();
}
HandlerType Type() const {
return HandlerType(mBits & eTypeBits);
}
bool HasEventHandler() const
{
return !!Ptr();
}
void SetHandler(const nsEventHandler& aHandler)
{
if (aHandler.HasEventHandler()) {
ReleaseHandler();
Assign(aHandler.Ptr(), aHandler.Type());
} else {
ForgetHandler();
}
}
EventHandlerNonNull* EventHandler() const
{
MOZ_ASSERT(Type() == eNormal && Ptr());
return reinterpret_cast<EventHandlerNonNull*>(Ptr());
}
void SetHandler(EventHandlerNonNull* aHandler)
{
ReleaseHandler();
Assign(aHandler, eNormal);
}
BeforeUnloadEventHandlerNonNull* BeforeUnloadEventHandler() const
{
MOZ_ASSERT(Type() == eOnBeforeUnload);
return reinterpret_cast<BeforeUnloadEventHandlerNonNull*>(Ptr());
}
void SetHandler(BeforeUnloadEventHandlerNonNull* aHandler)
{
ReleaseHandler();
Assign(aHandler, eOnBeforeUnload);
}
OnErrorEventHandlerNonNull* OnErrorEventHandler() const
{
MOZ_ASSERT(Type() == eOnError);
return reinterpret_cast<OnErrorEventHandlerNonNull*>(Ptr());
}
void SetHandler(OnErrorEventHandlerNonNull* aHandler)
{
ReleaseHandler();
Assign(aHandler, eOnError);
}
CallbackFunction* Ptr() const
{
// Have to cast eTypeBits so we don't have to worry about
// promotion issues after the bitflip.
return reinterpret_cast<CallbackFunction*>(mBits & ~uintptr_t(eTypeBits));
}
void ForgetHandler()
{
ReleaseHandler();
mBits = 0;
}
private:
void operator=(const nsEventHandler&) MOZ_DELETE;
void ReleaseHandler()
{
nsISupports* ptr = Ptr();
NS_IF_RELEASE(ptr);
}
void Assign(nsISupports* aHandler, HandlerType aType) {
MOZ_ASSERT(aHandler, "Must have handler");
NS_ADDREF(aHandler);
mBits = uintptr_t(aHandler) | uintptr_t(aType);
}
uintptr_t mBits;
};
// Implemented by script event listeners. Used to retrieve the
// script object corresponding to the event target and the handler itself.
// (Note this interface is now used to store script objects for all
@ -30,8 +167,10 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
nsIJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports *aTarget, JSObject *aHandler)
: mContext(aContext), mScopeObject(aScopeObject), mHandler(aHandler)
nsISupports *aTarget, nsIAtom* aType,
const nsEventHandler& aHandler)
: mContext(aContext), mScopeObject(aScopeObject), mEventName(aType),
mHandler(aHandler)
{
nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
mTarget = base.get();
@ -57,21 +196,35 @@ public:
return xpc_UnmarkGrayObject(mScopeObject);
}
JSObject *GetHandler() const
const nsEventHandler& GetHandler() const
{
return xpc_UnmarkGrayObject(mHandler);
return mHandler;
}
// Set a handler for this event listener. Must not be called if
// there is already a handler! The handler must already be bound to
// the right target.
virtual void SetHandler(JSObject *aHandler) = 0;
nsIAtom* EventName() const
{
return mEventName;
}
// Set a handler for this event listener. The handler must already
// be bound to the right target.
void SetHandler(const nsEventHandler& aHandler)
{
mHandler.SetHandler(aHandler);
}
void SetHandler(mozilla::dom::EventHandlerNonNull* aHandler)
{
mHandler.SetHandler(aHandler);
}
void SetHandler(mozilla::dom::BeforeUnloadEventHandlerNonNull* aHandler)
{
mHandler.SetHandler(aHandler);
}
void SetHandler(mozilla::dom::OnErrorEventHandlerNonNull* aHandler)
{
mHandler.SetHandler(aHandler);
}
// Among the sub-classes that inherit (directly or indirectly) from nsINode,
// measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - nsIJSEventListener: mEventName
//
virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
return 0;
@ -82,8 +235,10 @@ public:
// - mTarget
//
// The following members are not measured:
// - mScopeObject, mHandler: because they're measured by the JS memory
// - mScopeObject: because they're measured by the JS memory
// reporters
// - mHandler: may be shared with others
// - mEventName: shared with others
}
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
@ -99,7 +254,8 @@ protected:
nsCOMPtr<nsIScriptContext> mContext;
JSObject* mScopeObject;
nsISupports* mTarget;
JSObject *mHandler;
nsCOMPtr<nsIAtom> mEventName;
nsEventHandler mHandler;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
@ -107,7 +263,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
/* factory function. aHandler must already be bound to aTarget */
nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
JSObject* aScopeObject, nsISupports* aTarget,
nsIAtom* aType, JSObject* aHandler,
nsIAtom* aType, const nsEventHandler& aHandler,
nsIJSEventListener **aReturn);
#endif // nsIJSEventListener_h__

View File

@ -78,6 +78,12 @@ public:
return mCallable;
}
bool HasGrayCallable() const
{
// Play it safe in case this gets called after unlink.
return mCallable && xpc_IsGrayGCThing(mCallable);
}
protected:
void DropCallback()
{

View File

@ -38,6 +38,8 @@ public:
static EventListenerCounter sEventListenerCounter;
#endif
using namespace mozilla::dom;
/*
* nsJSEventListener implementation
*/
@ -45,9 +47,8 @@ nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
JSObject* aScopeObject,
nsISupports *aTarget,
nsIAtom* aType,
JSObject *aHandler)
: nsIJSEventListener(aContext, aScopeObject, aTarget, aHandler),
mEventName(aType)
const nsEventHandler& aHandler)
: nsIJSEventListener(aContext, aScopeObject, aTarget, aType, aHandler)
{
// aScopeObject is the inner window's JS object, which we need to lock
// until we are done with it.
@ -70,6 +71,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
tmp->mScopeObject = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
}
tmp->mHandler.ForgetHandler();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
if (MOZ_UNLIKELY(cb.WantDebugInfo()) && tmp->mEventName) {
@ -82,12 +84,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsJSEventListener, tmp->mRefCnt.get())
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mHandler.Ptr())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScopeObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mHandler)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsJSEventListener)
@ -131,7 +133,8 @@ nsJSEventListener::IsBlackForCC()
{
if (mContext &&
(!mScopeObject || !xpc_IsGrayGCThing(mScopeObject)) &&
(!mHandler || !xpc_IsGrayGCThing(mHandler))) {
(!mHandler.HasEventHandler() ||
!mHandler.Ptr()->HasGrayCallable())) {
nsIScriptGlobalObject* sgo =
static_cast<nsJSContext*>(mContext.get())->GetCachedGlobalObject();
return sgo && sgo->IsBlackForCC();
@ -143,7 +146,7 @@ nsresult
nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTarget);
if (!target || !mContext || !mHandler)
if (!target || !mContext || !mHandler.HasEventHandler())
return NS_ERROR_FAILURE;
nsresult rv;
@ -208,9 +211,9 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
#endif
nsCOMPtr<nsIVariant> vrv;
xpc_UnmarkGrayObject(mScopeObject);
xpc_UnmarkGrayObject(mHandler);
rv = mContext->CallEventHandler(mTarget, mScopeObject, mHandler, iargv,
getter_AddRefs(vrv));
rv = mContext->CallEventHandler(mTarget, mScopeObject,
mHandler.Ptr()->Callable(),
iargv, getter_AddRefs(vrv));
if (NS_SUCCEEDED(rv)) {
uint16_t dataType = nsIDataType::VTYPE_VOID;
@ -257,18 +260,6 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
return rv;
}
/* virtual */ void
nsJSEventListener::SetHandler(JSObject *aHandler)
{
// Technically we should drop the old mHandler and hold the new
// one... except for JS this is a no-op, and we're really not
// pretending very hard to support anything else. And since we
// can't in fact only drop one script object (we'd have to drop
// mScope too, and then re-hold it), let's just not worry about it
// all.
mHandler = aHandler;
}
/*
* Factory functions
*/
@ -276,7 +267,8 @@ nsJSEventListener::SetHandler(JSObject *aHandler)
nsresult
NS_NewJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports*aTarget, nsIAtom* aEventType,
JSObject* aHandler, nsIJSEventListener** aReturn)
const nsEventHandler& aHandler,
nsIJSEventListener** aReturn)
{
NS_ENSURE_ARG(aEventType);
nsJSEventListener* it =

View File

@ -21,7 +21,8 @@ class nsJSEventListener : public nsIJSEventListener
{
public:
nsJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports* aTarget, nsIAtom* aType, JSObject* aHandler);
nsISupports* aTarget, nsIAtom* aType,
const nsEventHandler& aHandler);
virtual ~nsJSEventListener();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -30,7 +31,6 @@ public:
NS_DECL_NSIDOMEVENTLISTENER
// nsIJSEventListener
virtual void SetHandler(JSObject *aHandler);
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
{
@ -41,8 +41,6 @@ public:
protected:
bool IsBlackForCC();
nsCOMPtr<nsIAtom> mEventName;
};
#endif //nsJSEventListener_h__

View File

@ -15,5 +15,9 @@ callback EventHandlerNonNull = any (Event event);
typedef EventHandlerNonNull? EventHandler;
[TreatNonCallableAsNull]
callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column);
callback BeforeUnloadEventHandlerNonNull = DOMString? (Event event);
typedef BeforeUnloadEventHandlerNonNull? BeforeUnloadEventHandler;
[TreatNonCallableAsNull]
callback OnErrorEventHandlerNonNull = boolean ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column);
typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;