Bug 942432 - Remove nsIJSEventListener::mContext, r=bz

This commit is contained in:
Olli Pettay 2013-11-27 11:12:41 +02:00
parent 42b94f81b1
commit 37ed427ba1
6 changed files with 78 additions and 98 deletions

View File

@ -574,14 +574,13 @@ nsEventListenerManager::FindEventHandler(uint32_t aEventType,
}
nsListenerStruct*
nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
JS::Handle<JSObject*> aScopeObject,
nsEventListenerManager::SetEventHandlerInternal(JS::Handle<JSObject*> aScopeObject,
nsIAtom* aName,
const nsAString& aTypeString,
const nsEventHandler& aHandler,
bool aPermitUntrustedEvents)
{
MOZ_ASSERT((aContext && aScopeObject) || aHandler.HasEventHandler(),
MOZ_ASSERT(aScopeObject || aHandler.HasEventHandler(),
"Must have one or the other!");
MOZ_ASSERT(aName || !aTypeString.IsEmpty());
@ -595,7 +594,7 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
flags.mListenerIsJSListener = true;
nsCOMPtr<nsIJSEventListener> scriptListener;
NS_NewJSEventListener(aContext, aScopeObject, mTarget, aName,
NS_NewJSEventListener(aScopeObject, mTarget, aName,
aHandler, getter_AddRefs(scriptListener));
if (!aName && aTypeString.EqualsLiteral("error")) {
@ -614,7 +613,7 @@ nsEventListenerManager::SetEventHandlerInternal(nsIScriptContext *aContext,
bool same = scriptListener->GetHandler() == aHandler;
// Possibly the same listener, but update still the context and scope.
scriptListener->SetHandler(aHandler, aContext, aScopeObject);
scriptListener->SetHandler(aHandler, aScopeObject);
if (mTarget && !same) {
mTarget->EventListenerRemoved(aName);
mTarget->EventListenerAdded(aName);
@ -651,31 +650,9 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIScriptGlobalObject> global;
if (node) {
// Try to get context from doc
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
// if that's the XBL document?
doc = node->OwnerDoc();
MOZ_ASSERT(!doc->IsLoadedAsData(), "Should not get in here at all");
// We want to allow compiling an event handler even in an unloaded
// document, so use GetScopeObject here, not GetScriptHandlingObject.
global = do_QueryInterface(doc->GetScopeObject());
} else {
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
if (win) {
doc = win->GetDoc();
global = do_QueryInterface(win);
} else {
global = do_QueryInterface(mTarget);
}
}
nsCOMPtr<nsIScriptGlobalObject> global =
GetScriptGlobalAndDocument(getter_AddRefs(doc));
if (!global) {
// This can happen; for example this document might have been
@ -754,13 +731,14 @@ nsEventListenerManager::SetEventHandler(nsIAtom *aName,
JS::Rooted<JSObject*> scope(context->GetNativeContext(),
global->GetGlobalJSObject());
nsListenerStruct* ls = SetEventHandlerInternal(context, scope, aName,
nsListenerStruct* ls = SetEventHandlerInternal(scope, aName,
EmptyString(),
nsEventHandler(),
aPermitUntrustedEvents);
if (!aDeferCompilation) {
return CompileEventHandlerInternal(ls, true, &aBody);
nsCxPusher pusher;
return CompileEventHandlerInternal(ls, pusher, &aBody);
}
return NS_OK;
@ -789,7 +767,7 @@ nsEventListenerManager::RemoveEventHandler(nsIAtom* aName,
nsresult
nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
bool aNeedsCxPush,
nsCxPusher& aPusher,
const nsAString* aBody)
{
NS_PRECONDITION(aListenerStruct->GetJSListener(),
@ -803,14 +781,19 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
NS_ASSERTION(!listener->GetHandler().HasEventHandler(),
"What is there to compile?");
nsIScriptContext *context = listener->GetEventContext();
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIScriptGlobalObject> global =
GetScriptGlobalAndDocument(getter_AddRefs(doc));
NS_ENSURE_STATE(global);
nsIScriptContext* context = global->GetScriptContext();
NS_ENSURE_STATE(context);
JSContext *cx = context->GetNativeContext();
JS::Rooted<JSObject*> handler(cx);
nsCOMPtr<nsPIDOMWindow> win; // Will end up non-null if mTarget is a window
nsCxPusher pusher;
if (aNeedsCxPush) {
if (aPusher.GetCurrentScriptContext() != context) {
pusher.Push(cx);
}
@ -859,16 +842,6 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
uint32_t lineNo = 0;
nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener"));
nsCOMPtr<nsIDocument> doc;
if (content) {
doc = content->OwnerDoc();
} else {
win = do_QueryInterface(mTarget);
if (win) {
doc = win->GetExtantDoc();
}
}
if (doc) {
nsIURI *uri = doc->GetDocumentURI();
if (uri) {
@ -904,6 +877,7 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
}
if (handler) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
// Bind it
JS::Rooted<JSObject*> boundHandler(cx);
JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
@ -942,11 +916,7 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
// compiled the event handler itself
if ((aListenerStruct->mListenerType == eJSEventListener) &&
aListenerStruct->mHandlerIsString) {
nsIJSEventListener *jslistener = aListenerStruct->GetJSListener();
result = CompileEventHandlerInternal(aListenerStruct,
jslistener->GetEventContext() !=
aPusher->GetCurrentScriptContext(),
nullptr);
result = CompileEventHandlerInternal(aListenerStruct, *aPusher, nullptr);
aListenerStruct = nullptr;
}
@ -1197,8 +1167,9 @@ nsEventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
// If this is a script handler and we haven't yet
// compiled the event handler itself go ahead and compile it
if ((ls.mListenerType == eJSEventListener) && ls.mHandlerIsString) {
nsCxPusher pusher;
CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls),
true, nullptr);
pusher, nullptr);
}
nsAutoString eventType;
if (ls.mAllEvents) {
@ -1244,7 +1215,7 @@ nsEventListenerManager::SetEventHandler(nsIAtom* aEventName,
// Untrusted events are always permitted for non-chrome script
// handlers.
SetEventHandlerInternal(nullptr, JS::NullPtr(), aEventName,
SetEventHandlerInternal(JS::NullPtr(), aEventName,
aTypeString, nsEventHandler(aHandler),
!mIsMainThreadELM ||
!nsContentUtils::IsCallerChrome());
@ -1261,7 +1232,7 @@ nsEventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
// Untrusted events are always permitted for non-chrome script
// handlers.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nsGkAtoms::onerror,
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onerror,
EmptyString(), nsEventHandler(aHandler),
!nsContentUtils::IsCallerChrome());
} else {
@ -1271,7 +1242,7 @@ nsEventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
}
// Untrusted events are always permitted.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nullptr,
SetEventHandlerInternal(JS::NullPtr(), nullptr,
NS_LITERAL_STRING("error"),
nsEventHandler(aHandler), true);
}
@ -1287,7 +1258,7 @@ nsEventListenerManager::SetEventHandler(OnBeforeUnloadEventHandlerNonNull* aHand
// Untrusted events are always permitted for non-chrome script
// handlers.
SetEventHandlerInternal(nullptr, JS::NullPtr(), nsGkAtoms::onbeforeunload,
SetEventHandlerInternal(JS::NullPtr(), nsGkAtoms::onbeforeunload,
EmptyString(), nsEventHandler(aHandler),
!mIsMainThreadELM ||
!nsContentUtils::IsCallerChrome());
@ -1307,7 +1278,8 @@ nsEventListenerManager::GetEventHandlerInternal(nsIAtom *aEventName,
nsIJSEventListener *listener = ls->GetJSListener();
if (ls->mHandlerIsString) {
CompileEventHandlerInternal(ls, true, nullptr);
nsCxPusher pusher;
CompileEventHandlerInternal(ls, pusher, nullptr);
}
const nsEventHandler& handler = listener->GetHandler();
@ -1359,3 +1331,33 @@ nsEventListenerManager::MarkForCC()
mRefCnt.RemovePurple();
}
}
already_AddRefed<nsIScriptGlobalObject>
nsEventListenerManager::GetScriptGlobalAndDocument(nsIDocument** aDoc)
{
nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
nsCOMPtr<nsIDocument> doc;
nsCOMPtr<nsIScriptGlobalObject> global;
if (node) {
// Try to get context from doc
// XXX sXBL/XBL2 issue -- do we really want the owner here? What
// if that's the XBL document?
doc = node->OwnerDoc();
MOZ_ASSERT(!doc->IsLoadedAsData(), "Should not get in here at all");
// We want to allow compiling an event handler even in an unloaded
// document, so use GetScopeObject here, not GetScriptHandlingObject.
global = do_QueryInterface(doc->GetScopeObject());
} else {
nsCOMPtr<nsPIDOMWindow> win = GetTargetAsInnerWindow();
if (win) {
doc = win->GetExtantDoc();
global = do_QueryInterface(win);
} else {
global = do_QueryInterface(mTarget);
}
}
doc.forget(aDoc);
return global.forget();
}

View File

@ -427,7 +427,7 @@ protected:
* will look for it on mTarget.
*/
nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
bool aNeedsCxPush,
nsCxPusher& aPusher,
const nsAString* aBody);
/**
@ -444,8 +444,7 @@ protected:
* allowed to be null. The nsListenerStruct that results, if any, is returned
* in aListenerStruct.
*/
nsListenerStruct* SetEventHandlerInternal(nsIScriptContext *aContext,
JS::Handle<JSObject*> aScopeGlobal,
nsListenerStruct* SetEventHandlerInternal(JS::Handle<JSObject*> aScopeGlobal,
nsIAtom* aName,
const nsAString& aTypeString,
const nsEventHandler& aHandler,
@ -538,6 +537,9 @@ protected:
bool ListenerCanHandle(nsListenerStruct* aLs, mozilla::WidgetEvent* aEvent);
already_AddRefed<nsIScriptGlobalObject>
GetScriptGlobalAndDocument(nsIDocument** aDoc);
uint32_t mMayHavePaintEventListener : 1;
uint32_t mMayHaveMutationListeners : 1;
uint32_t mMayHaveCapturingListeners : 1;

View File

@ -328,7 +328,7 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
// Execute it.
nsCOMPtr<nsIJSEventListener> eventListener;
rv = NS_NewJSEventListener(nullptr, globalObject,
rv = NS_NewJSEventListener(globalObject,
scriptTarget, onEventAtom,
eventHandler,
getter_AddRefs(eventListener));

View File

@ -14,8 +14,8 @@
#include "mozilla/dom/EventHandlerBinding.h"
#define NS_IJSEVENTLISTENER_IID \
{ 0x92f9212b, 0xa6aa, 0x4867, \
{ 0x93, 0x8a, 0x56, 0xbe, 0x17, 0x67, 0x4f, 0xd4 } }
{ 0x5077b12a, 0x5a1f, 0x4583, \
{ 0xbb, 0xa7, 0x78, 0x84, 0x94, 0x0e, 0x5e, 0xff } }
class nsEventHandler
{
@ -172,22 +172,15 @@ class nsIJSEventListener : public nsIDOMEventListener
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSEVENTLISTENER_IID)
nsIJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsIJSEventListener(JSObject* aScopeObject,
nsISupports *aTarget, nsIAtom* aType,
const nsEventHandler& aHandler)
: mContext(aContext), mScopeObject(aScopeObject), mEventName(aType),
mHandler(aHandler)
: mScopeObject(aScopeObject), mEventName(aType), mHandler(aHandler)
{
nsCOMPtr<nsISupports> base = do_QueryInterface(aTarget);
mTarget = base.get();
}
// Can return null if we already have a handler.
nsIScriptContext *GetEventContext() const
{
return mContext;
}
nsISupports *GetEventTarget() const
{
return mTarget;
@ -226,11 +219,10 @@ public:
// Set a handler for this event listener. The handler must already
// be bound to the right target.
void SetHandler(const nsEventHandler& aHandler, nsIScriptContext* aContext,
void SetHandler(const nsEventHandler& aHandler,
JS::Handle<JSObject*> aScopeObject)
{
mHandler.SetHandler(aHandler);
mContext = aContext;
UpdateScopeObject(aScopeObject);
}
void SetHandler(mozilla::dom::EventHandlerNonNull* aHandler)
@ -252,7 +244,6 @@ public:
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:
// - mContext
// - mTarget
//
// The following members are not measured:
@ -277,7 +268,6 @@ protected:
// the hold/drop stuff, so have to do it in nsJSEventListener.
virtual void UpdateScopeObject(JS::Handle<JSObject*> aScopeObject) = 0;
nsCOMPtr<nsIScriptContext> mContext;
JS::Heap<JSObject*> mScopeObject;
nsISupports* mTarget;
nsCOMPtr<nsIAtom> mEventName;
@ -289,8 +279,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSEventListener, NS_IJSEVENTLISTENER_IID)
/* factory function. aHandler must already be bound to aTarget.
aContext is allowed to be null if aHandler is already set up.
*/
nsresult NS_NewJSEventListener(nsIScriptContext *aContext,
JSObject* aScopeObject, nsISupports* aTarget,
nsresult NS_NewJSEventListener(JSObject* aScopeObject, nsISupports* aTarget,
nsIAtom* aType, const nsEventHandler& aHandler,
nsIJSEventListener **aReturn);

View File

@ -42,12 +42,11 @@ using namespace mozilla::dom;
/*
* nsJSEventListener implementation
*/
nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
JSObject* aScopeObject,
nsJSEventListener::nsJSEventListener(JSObject* aScopeObject,
nsISupports *aTarget,
nsIAtom* aType,
const nsEventHandler& aHandler)
: nsIJSEventListener(aContext, aScopeObject, aTarget, aType, aHandler)
: nsIJSEventListener(aScopeObject, aTarget, aType, aHandler)
{
if (mScopeObject) {
mozilla::HoldJSObjects(this);
@ -81,7 +80,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSEventListener)
if (tmp->mScopeObject) {
tmp->mScopeObject = nullptr;
mozilla::DropJSObjects(tmp);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
}
tmp->mHandler.ForgetHandler();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -95,7 +93,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsJSEventListener, tmp->mRefCnt.get())
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mHandler.Ptr())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -148,13 +145,7 @@ nsJSEventListener::IsBlackForCC()
if ((!mScopeObject || !xpc_IsGrayGCThing(mScopeObject)) &&
(!mHandler.HasEventHandler() ||
!mHandler.Ptr()->HasGrayCallable())) {
if (!mContext) {
// Well, we certainly won't be marking it, so move on!
return true;
}
nsIScriptGlobalObject* sgo =
static_cast<nsJSContext*>(mContext.get())->GetCachedGlobalObject();
return sgo && sgo->IsBlackForCC();
return true;
}
return false;
}
@ -264,17 +255,14 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
*/
nsresult
NS_NewJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
NS_NewJSEventListener(JSObject* aScopeObject,
nsISupports*aTarget, nsIAtom* aEventType,
const nsEventHandler& aHandler,
nsIJSEventListener** aReturn)
{
MOZ_ASSERT(aContext || aHandler.HasEventHandler(),
"Must have a handler if we don't have an nsIScriptContext");
NS_ENSURE_ARG(aEventType || !NS_IsMainThread());
nsJSEventListener* it =
new nsJSEventListener(aContext, aScopeObject, aTarget, aEventType,
aHandler);
new nsJSEventListener(aScopeObject, aTarget, aEventType, aHandler);
NS_ADDREF(*aReturn = it);
return NS_OK;

View File

@ -21,9 +21,8 @@
class nsJSEventListener : public nsIJSEventListener
{
public:
nsJSEventListener(nsIScriptContext* aContext, JSObject* aScopeObject,
nsISupports* aTarget, nsIAtom* aType,
const nsEventHandler& aHandler);
nsJSEventListener(JSObject* aScopeObject, nsISupports* aTarget,
nsIAtom* aType, const nsEventHandler& aHandler);
virtual ~nsJSEventListener();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS