Bug 942432 - Remove nsIJSEventListener::mContext, r=bz
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Wed, 27 Nov 2013 11:12:41 +0200
changeset 157727 8e1efc26dd88376bcb8deb14a12d90e93c81782c
parent 157726 fa7ff2506660600c5399081f4e66220123323c7e
child 157728 2ff280bab60cd4a7cf606c7df27cb79435226e7b
push id36819
push useropettay@mozilla.com
push dateWed, 27 Nov 2013 09:13:06 +0000
treeherdermozilla-inbound@8e1efc26dd88 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs942432
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 942432 - Remove nsIJSEventListener::mContext, r=bz
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/xbl/src/nsXBLPrototypeHandler.cpp
dom/base/nsIJSEventListener.h
dom/src/events/nsJSEventListener.cpp
dom/src/events/nsJSEventListener.h
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -569,38 +569,37 @@ nsEventListenerManager::FindEventHandler
         EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom, aTypeString, false)) {
       return ls;
     }
   }
   return nullptr;
 }
 
 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());
 
   uint32_t eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindEventHandler(eventType, aName, aTypeString);
 
   if (!ls) {
     // If we didn't find a script listener or no listeners existed
     // create and add a new one.
     EventListenerFlags flags;
     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")) {
       eventType = NS_LOAD_ERROR;
     }
 
     EventListenerHolder holder(scriptListener);
     AddEventListenerInternal(holder, eventType, aName, aTypeString, flags,
@@ -609,17 +608,17 @@ nsEventListenerManager::SetEventHandlerI
     ls = FindEventHandler(eventType, aName, aTypeString);
   } else {
     nsIJSEventListener* scriptListener = ls->GetJSListener();
     MOZ_ASSERT(scriptListener,
                "How can we have an event handler with no nsIJSEventListener?");
 
     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);
     }
   }
 
   // Set flag to indicate possible need for compilation later
   ls->mHandlerIsString = !aHandler.HasEventHandler();
@@ -646,41 +645,19 @@ nsEventListenerManager::SetEventHandler(
   // 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(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
     // loaded as data.
     return NS_OK;
   }
 
 #ifdef DEBUG
@@ -749,23 +726,24 @@ nsEventListenerManager::SetEventHandler(
 
   nsIScriptContext* context = global->GetScriptContext();
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   JSAutoRequest ar(context->GetNativeContext());
   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;
 }
 
 void
 nsEventListenerManager::RemoveEventHandler(nsIAtom* aName,
                                            const nsAString& aTypeString)
@@ -784,38 +762,43 @@ nsEventListenerManager::RemoveEventHandl
     if (mTarget) {
       mTarget->EventListenerRemoved(aName);
     }
   }
 }
 
 nsresult
 nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
-                                                    bool aNeedsCxPush,
+                                                    nsCxPusher& aPusher,
                                                     const nsAString* aBody)
 {
   NS_PRECONDITION(aListenerStruct->GetJSListener(),
                   "Why do we not have a JS listener?");
   NS_PRECONDITION(aListenerStruct->mHandlerIsString,
                   "Why are we compiling a non-string JS listener?");
 
   nsresult result = NS_OK;
 
   nsIJSEventListener *listener = aListenerStruct->GetJSListener();
   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);
   }
 
   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
     // which can't be compiled
     aListenerStruct->mHandlerIsString = false;
@@ -854,26 +837,16 @@ nsEventListenerManager::CompileEventHand
         attrName = nsGkAtoms::onend;
 
       content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
       body = &handlerBody;
     }
 
     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) {
         uri->GetSpec(url);
         lineNo = 1;
       }
     }
 
@@ -899,16 +872,17 @@ nsEventListenerManager::CompileEventHand
                                         nsAtomCString(aListenerStruct->mTypeAtom),
                                         argCount, argNames, *body, handlerFun.address());
     NS_ENSURE_SUCCESS(result, result);
     handler = handlerFun;
     NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
   }
 
   if (handler) {
+    nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget);
     // Bind it
     JS::Rooted<JSObject*> boundHandler(cx);
     JS::Rooted<JSObject*> scope(cx, listener->GetEventScope());
     context->BindCompiledEventHandler(mTarget, scope, handler, &boundHandler);
     aListenerStruct = nullptr;
     if (!boundHandler) {
       listener->ForgetHandler();
     } else if (listener->EventName() == nsGkAtoms::onerror && win) {
@@ -937,21 +911,17 @@ nsEventListenerManager::HandleEventSubTy
 {
   nsresult result = NS_OK;
   EventListenerHolder listener(aListenerStruct->mListener);  // strong ref
 
   // If this is a script handler and we haven't yet
   // 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;
   }
 
   if (NS_SUCCEEDED(result)) {
     if (mIsMainThreadELM) {
       nsContentUtils::EnterMicroTask();
     }
     // nsIDOMEvent::currentTarget is set in nsEventDispatcher.
@@ -1192,18 +1162,19 @@ nsEventListenerManager::GetListenerInfo(
   NS_ENSURE_STATE(target);
   aList->Clear();
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     const nsListenerStruct& ls = mListeners.ElementAt(i);
     // 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) {
       eventType.SetIsVoid(true);
     } else {
       eventType.Assign(Substring(nsDependentAtomString(ls.mTypeAtom), 2));
     }
     // EventListenerInfo is defined in XPCOM, so we have to go ahead
@@ -1239,60 +1210,60 @@ nsEventListenerManager::SetEventHandler(
 {
   if (!aHandler) {
     RemoveEventHandler(aEventName, aTypeString);
     return;
   }
 
   // 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());
 }
 
 void
 nsEventListenerManager::SetEventHandler(OnErrorEventHandlerNonNull* aHandler)
 {
   if (mIsMainThreadELM) {
     if (!aHandler) {
       RemoveEventHandler(nsGkAtoms::onerror, EmptyString());
       return;
     }
 
     // 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 {
     if (!aHandler) {
       RemoveEventHandler(nullptr, NS_LITERAL_STRING("error"));
       return;
     }
 
     // Untrusted events are always permitted.
-    SetEventHandlerInternal(nullptr, JS::NullPtr(), nullptr,
+    SetEventHandlerInternal(JS::NullPtr(), nullptr,
                             NS_LITERAL_STRING("error"),
                             nsEventHandler(aHandler), true);
   }
 }
 
 void
 nsEventListenerManager::SetEventHandler(OnBeforeUnloadEventHandlerNonNull* aHandler)
 {
   if (!aHandler) {
     RemoveEventHandler(nsGkAtoms::onbeforeunload, EmptyString());
     return;
   }
 
   // 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());
 }
 
 const nsEventHandler*
 nsEventListenerManager::GetEventHandlerInternal(nsIAtom *aEventName,
                                                 const nsAString& aTypeString)
@@ -1302,17 +1273,18 @@ nsEventListenerManager::GetEventHandlerI
 
   if (!ls) {
     return nullptr;
   }
 
   nsIJSEventListener *listener = ls->GetJSListener();
     
   if (ls->mHandlerIsString) {
-    CompileEventHandlerInternal(ls, true, nullptr);
+    nsCxPusher pusher;
+    CompileEventHandlerInternal(ls, pusher, nullptr);
   }
 
   const nsEventHandler& handler = listener->GetHandler();
   if (handler.HasEventHandler()) {
     return &handler;
   }
 
   return nullptr;
@@ -1354,8 +1326,38 @@ nsEventListenerManager::MarkForCC()
       // Callback() unmarks gray
       ls.mListener.GetWebIDLCallback()->Callback();
     }
   }
   if (mRefCnt.IsPurple()) {
     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();
+}
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -422,35 +422,34 @@ protected:
                               nsCxPusher* aPusher);
 
   /**
    * Compile the "inline" event listener for aListenerStruct.  The
    * body of the listener can be provided in aBody; if this is null we
    * will look for it on mTarget.
    */
   nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
-                                       bool aNeedsCxPush,
+                                       nsCxPusher& aPusher,
                                        const nsAString* aBody);
 
   /**
    * Find the nsListenerStruct for the "inline" event listener for aTypeAtom.
    */
   nsListenerStruct* FindEventHandler(uint32_t aEventType, nsIAtom* aTypeAtom,
                                      const nsAString& aTypeString);
 
   /**
    * 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, but in that case aContext and
    * aScopeGlobal must be non-null.  Otherwise, aContext and aScopeGlobal are
    * 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,
                                             bool aPermitUntrustedEvents);
 
   bool IsDeviceType(uint32_t aType);
   void EnableDevice(uint32_t aType);
   void DisableDevice(uint32_t aType);
@@ -533,16 +532,19 @@ protected:
   void RemoveAllListeners();
   const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
   const EventTypeData* GetTypeDataForEventName(nsIAtom* aName);
   nsPIDOMWindow* GetInnerWindowForTarget();
   already_AddRefed<nsPIDOMWindow> GetTargetAsInnerWindow() const;
 
   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;
   uint32_t mMayHaveSystemGroupListeners : 1;
   uint32_t mMayHaveAudioAvailableEventListener : 1;
   uint32_t mMayHaveTouchEventListener : 1;
   uint32_t mMayHaveMouseEnterLeaveEventListener : 1;
   uint32_t mClearingListeners : 1;
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -323,17 +323,17 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
 
   nsRefPtr<EventHandlerNonNull> handlerCallback =
     new EventHandlerNonNull(bound);
 
   nsEventHandler eventHandler(handlerCallback);
 
   // Execute it.
   nsCOMPtr<nsIJSEventListener> eventListener;
-  rv = NS_NewJSEventListener(nullptr, globalObject,
+  rv = NS_NewJSEventListener(globalObject,
                              scriptTarget, onEventAtom,
                              eventHandler,
                              getter_AddRefs(eventListener));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Handle the event.
   eventListener->HandleEvent(aEvent);
   eventListener->Disconnect();
--- a/dom/base/nsIJSEventListener.h
+++ b/dom/base/nsIJSEventListener.h
@@ -9,18 +9,18 @@
 #include "nsIScriptContext.h"
 #include "xpcpublic.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAtom.h"
 #include "mozilla/MemoryReporting.h"
 #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
 {
 public:
   typedef mozilla::dom::EventHandlerNonNull EventHandlerNonNull;
   typedef mozilla::dom::OnBeforeUnloadEventHandlerNonNull
     OnBeforeUnloadEventHandlerNonNull;
   typedef mozilla::dom::OnErrorEventHandlerNonNull OnErrorEventHandlerNonNull;
@@ -167,32 +167,25 @@ private:
 //
 // Note, mTarget is a raw pointer and the owner of the nsIJSEventListener object
 // is expected to call Disconnect()!
 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;
   }
 
   void Disconnect()
   {
     mTarget = nullptr;
@@ -221,21 +214,20 @@ public:
 
   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, nsIScriptContext* aContext,
+  void SetHandler(const nsEventHandler& aHandler,
                   JS::Handle<JSObject*> aScopeObject)
   {
     mHandler.SetHandler(aHandler);
-    mContext = aContext;
     UpdateScopeObject(aScopeObject);
   }
   void SetHandler(mozilla::dom::EventHandlerNonNull* aHandler)
   {
     mHandler.SetHandler(aHandler);
   }
   void SetHandler(mozilla::dom::OnBeforeUnloadEventHandlerNonNull* aHandler)
   {
@@ -247,17 +239,16 @@ public:
   }
 
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   {
     return 0;
 
     // Measurement of the following members may be added later if DMD finds it
     // is worthwhile:
-    // - mContext
     // - mTarget
     //
     // The following members are not measured:
     // - mScopeObject: because they're measured by the JS memory
     //   reporters
     // - mHandler: may be shared with others
     // - mEventName: shared with others
   }
@@ -272,26 +263,24 @@ protected:
   {
     NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
   }
 
   // Update our mScopeObject; we have to make sure we properly handle
   // 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;
   nsEventHandler mHandler;
 };
 
 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);
 
 #endif // nsIJSEventListener_h__
--- a/dom/src/events/nsJSEventListener.cpp
+++ b/dom/src/events/nsJSEventListener.cpp
@@ -37,22 +37,21 @@ static EventListenerCounter sEventListen
 #endif
 
 using namespace mozilla;
 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);
   }
 }
 
 nsJSEventListener::~nsJSEventListener() 
 {
@@ -76,31 +75,29 @@ nsJSEventListener::UpdateScopeObject(JS:
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
 
 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
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSEventListener)
   if (MOZ_UNLIKELY(cb.WantDebugInfo()) && tmp->mEventName) {
     nsAutoCString name;
     name.AppendLiteral("nsJSEventListener handlerName=");
     name.Append(
       NS_ConvertUTF16toUTF8(nsDependentAtomString(tmp->mEventName)).get());
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name.get());
   } 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
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScopeObject)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -143,23 +140,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSEve
 bool
 nsJSEventListener::IsBlackForCC()
 {
   // We can claim to be black if all the things we reference are
   // effectively black already.
   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;
 }
 
 nsresult
 nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsCOMPtr<EventTarget> target = do_QueryInterface(mTarget);
@@ -259,23 +250,20 @@ nsJSEventListener::HandleEvent(nsIDOMEve
   return NS_OK;
 }
 
 /*
  * Factory functions
  */
 
 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;
 }
--- a/dom/src/events/nsJSEventListener.h
+++ b/dom/src/events/nsJSEventListener.h
@@ -16,19 +16,18 @@
 #include "nsIScriptContext.h"
 #include "nsCycleCollectionParticipant.h"
 
 // nsJSEventListener interface
 // misnamed - JS no longer has exclusive rights over this interface!
 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
 
   // nsIDOMEventListener interface
   NS_DECL_NSIDOMEVENTLISTENER
 
   // nsIJSEventListener