Bug 1184461 - If a listener is not callable, assume it is an event listener object. r=past
☠☠ backed out by 74de6a8e0a0e ☠ ☠
authorEddy Bruel <ejpbruel@mozilla.com
Wed, 03 Aug 2016 14:26:06 +0200
changeset 351503 2b687444223cbaa1f5727b4e8fff13177ab8ef0d
parent 351502 003319dc7a1f79b9bdf600c5d20ca7d19bcb80b0
child 351504 b965a94cd13ecf249b4bc4106c32b99ba420f243
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs1184461
milestone51.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 1184461 - If a listener is not callable, assume it is an event listener object. r=past In ThreadActor._getAllEventListeners, we construct a list of handler functions for each target in the event target chain of a given event target. If a handler is an event handler object, we obtain the handler function from its handleEvent property. Otherwise, the handler function is assumed to be the handler itself. To detect whether a handler is an event handler object, we would check its class name property. This approach is fragile for several reasons: if the handler is a proxy, accessing its class name may cause the debuggee to run. Moreover, since accessing a proxy's class name requires us to enter the compartment of the proxy's handler, if the latter is a security wrapper, accessing its class name will cause security warnings in debug mode. Since a handler is either an event handler object or a function, it should be safe to assume that a handler is an event handler object if and only if it is not callable. Checking whether a proxy is callable cannot cause the debuggee to run. Moreover, it does not require us to enter the compartment of the proxy's handler, thus avoiding the security warnings we mentioned earlier.
devtools/server/actors/script.js
--- a/devtools/server/actors/script.js
+++ b/devtools/server/actors/script.js
@@ -1123,18 +1123,18 @@ const ThreadActor = ActorClassWithSpec(t
         // a JS debugger.
         if (!handler || !handler.listenerObject || !handler.type)
           continue;
         // Create a listener-like object suitable for our purposes.
         let l = Object.create(null);
         l.type = handler.type;
         let listener = handler.listenerObject;
         let listenerDO = this.globalDebugObject.makeDebuggeeValue(listener);
-        // If the listener is an object with a 'handleEvent' method, use that.
-        if (listenerDO.class == "Object" || listenerDO.class == "XULElement") {
+        // If the listener is not callable, assume it is an event handler object.
+        if (!listenerDO.callable) {
           // For some events we don't have permission to access the
           // 'handleEvent' property when running in content scope.
           if (!listenerDO.unwrap()) {
             continue;
           }
           let heDesc;
           while (!heDesc && listenerDO) {
             heDesc = listenerDO.getOwnPropertyDescriptor("handleEvent");