Bug 941876 part 1. Pass in the element we're compiling the event handler for to the event listener manager, so it knows which element to associate with the compiled script. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 26 Nov 2013 11:44:37 -0500
changeset 164889 bb4066993a6a3c523728b8a0fc3c9ad12c95b840
parent 164888 f88b13e2ae0acddbe78c7de8df85d227e4ce0ece
child 164890 fbb3ea68c86e34e02f2e6b75b0f0f1cada0a07fd
push id38851
push userbzbarsky@mozilla.com
push dateThu, 23 Jan 2014 20:18:36 +0000
treeherdermozilla-inbound@fbb3ea68c86e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs941876
milestone29.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 941876 part 1. Pass in the element we're compiling the event handler for to the event listener manager, so it knows which element to associate with the compiled script. r=smaug
content/base/src/Element.cpp
dom/events/nsEventListenerManager.cpp
dom/events/nsEventListenerManager.h
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -1621,17 +1621,18 @@ Element::SetEventHandler(nsIAtom* aEvent
                                                                    &defer);
   if (!manager) {
     return NS_OK;
   }
 
   defer = defer && aDefer; // only defer if everyone agrees...
   manager->SetEventHandler(aEventName, aValue,
                            nsIProgrammingLanguage::JAVASCRIPT,
-                           defer, !nsContentUtils::IsChromeDoc(ownerDoc));
+                           defer, !nsContentUtils::IsChromeDoc(ownerDoc),
+                           this);
   return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 
 const nsAttrName*
 Element::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
--- a/dom/events/nsEventListenerManager.cpp
+++ b/dom/events/nsEventListenerManager.cpp
@@ -622,17 +622,18 @@ nsEventListenerManager::SetEventHandlerI
   return ls;
 }
 
 nsresult
 nsEventListenerManager::SetEventHandler(nsIAtom *aName,
                                         const nsAString& aBody,
                                         uint32_t aLanguage,
                                         bool aDeferCompilation,
-                                        bool aPermitUntrustedEvents)
+                                        bool aPermitUntrustedEvents,
+                                        Element* aElement)
 {
   NS_PRECONDITION(aLanguage != nsIProgrammingLanguage::UNKNOWN,
                   "Must know the language for the script event listener");
 
   // |aPermitUntrustedEvents| is set to False for chrome - events
   // *generated* from an unknown source are not allowed.
   // However, for script languages with no 'sandbox', we want to reject
   // such scripts based on the source of their code, not just the source
@@ -728,17 +729,17 @@ nsEventListenerManager::SetEventHandler(
                               global->GetGlobalJSObject());
 
   nsListenerStruct* ls = SetEventHandlerInternal(scope, aName,
                                                  EmptyString(),
                                                  nsEventHandler(),
                                                  aPermitUntrustedEvents);
 
   if (!aDeferCompilation) {
-    return CompileEventHandlerInternal(ls, &aBody);
+    return CompileEventHandlerInternal(ls, &aBody, aElement);
   }
 
   return NS_OK;
 }
 
 void
 nsEventListenerManager::RemoveEventHandler(nsIAtom* aName,
                                            const nsAString& aTypeString)
@@ -757,17 +758,18 @@ nsEventListenerManager::RemoveEventHandl
     if (mTarget && aName) {
       mTarget->EventListenerRemoved(aName);
     }
   }
 }
 
 nsresult
 nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
-                                                    const nsAString* aBody)
+                                                    const nsAString* aBody,
+                                                    Element* aElement)
 {
   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;
 
@@ -904,17 +906,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) {
-    result = CompileEventHandlerInternal(aListenerStruct, nullptr);
+    result = CompileEventHandlerInternal(aListenerStruct, nullptr, nullptr);
     aListenerStruct = nullptr;
   }
 
   if (NS_SUCCEEDED(result)) {
     if (mIsMainThreadELM) {
       nsContentUtils::EnterMicroTask();
     }
     // nsIDOMEvent::currentTarget is set in nsEventDispatcher.
@@ -1137,17 +1139,18 @@ 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) {
-      CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls), nullptr);
+      CompileEventHandlerInternal(const_cast<nsListenerStruct*>(&ls), nullptr,
+                                  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
@@ -1246,17 +1249,17 @@ nsEventListenerManager::GetEventHandlerI
 
   if (!ls) {
     return nullptr;
   }
 
   nsIJSEventListener *listener = ls->GetJSListener();
     
   if (ls->mHandlerIsString) {
-    CompileEventHandlerInternal(ls, nullptr);
+    CompileEventHandlerInternal(ls, nullptr, nullptr);
   }
 
   const nsEventHandler& handler = listener->GetHandler();
   if (handler.HasEventHandler()) {
     return &handler;
   }
 
   return nullptr;
--- a/dom/events/nsEventListenerManager.h
+++ b/dom/events/nsEventListenerManager.h
@@ -27,16 +27,17 @@ struct nsListenerStruct;
 class nsEventListenerManager;
 
 template<class T> class nsCOMArray;
 
 namespace mozilla {
 namespace dom {
 
 class EventTarget;
+class Element;
 
 typedef CallbackObjectHolder<EventListener, nsIDOMEventListener>
   EventListenerHolder;
 
 struct EventListenerFlags
 {
   friend struct ::nsListenerStruct;
   friend class  ::nsEventListenerManager;
@@ -278,24 +279,27 @@ public:
                                  const nsAString& type,
                                  const mozilla::dom::EventListenerFlags& aFlags);
 
   /**
    * Sets the current "inline" event listener for aName to be a
    * function compiled from aFunc if !aDeferCompilation.  If
    * aDeferCompilation, then we assume that we can get the string from
    * mTarget later and compile lazily.
+   *
+   * aElement, if not null, is the element the string is associated with.
    */
   // XXXbz does that play correctly with nodes being adopted across
   // documents?  Need to double-check the spec here.
   nsresult SetEventHandler(nsIAtom *aName,
                            const nsAString& aFunc,
                            uint32_t aLanguage,
                            bool aDeferCompilation,
-                           bool aPermitUntrustedEvents);
+                           bool aPermitUntrustedEvents,
+                           mozilla::dom::Element* aElement);
   /**
    * Remove the current "inline" event listener for aName.
    */
   void RemoveEventHandler(nsIAtom *aName, const nsAString& aTypeString);
 
   void HandleEvent(nsPresContext* aPresContext,
                    mozilla::WidgetEvent* aEvent, 
                    nsIDOMEvent** aDOMEvent,
@@ -415,20 +419,22 @@ protected:
 
   nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
                               nsIDOMEvent* aDOMEvent,
                               mozilla::dom::EventTarget* aCurrentTarget);
 
   /**
    * 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.
+   * will look for it on mTarget.  If aBody is provided, aElement should be
+   * as well; otherwise it will also be inferred from mTarget.
    */
   nsresult CompileEventHandlerInternal(nsListenerStruct *aListenerStruct,
-                                       const nsAString* aBody);
+                                       const nsAString* aBody,
+                                       mozilla::dom::Element* aElement);
 
   /**
    * Find the nsListenerStruct for the "inline" event listener for aTypeAtom.
    */
   nsListenerStruct* FindEventHandler(uint32_t aEventType, nsIAtom* aTypeAtom,
                                      const nsAString& aTypeString);
 
   /**