Bug 1226548 - Event listeners tooltip breaks the syntax in popup if there's a comment before event handler in JS code. r=ochameau
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Tue, 26 Apr 2016 13:37:47 +0100
changeset 294905 412f3942777e3f876773da8a6c1eb2522dc1f381
parent 294904 f0210b36ff71d143c1041202f55ad924daa1c8d8
child 294906 fb7111ef84f70cfba9ad445fd9fa492780401a31
push id18938
push usercbook@mozilla.com
push dateTue, 26 Apr 2016 13:05:44 +0000
treeherderfx-team@fb7111ef84f7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1226548
milestone49.0a1
Bug 1226548 - Event listeners tooltip breaks the syntax in popup if there's a comment before event handler in JS code. r=ochameau
devtools/client/inspector/markup/test/browser.ini
devtools/client/inspector/markup/test/browser_markup_events.js
devtools/client/inspector/markup/test/browser_markup_events1.js
devtools/client/inspector/markup/test/browser_markup_events2.js
devtools/client/inspector/markup/test/browser_markup_events3.js
devtools/client/inspector/markup/test/browser_markup_events_jquery_1.0.js
devtools/client/inspector/markup/test/browser_markup_events_jquery_1.1.js
devtools/client/inspector/markup/test/doc_markup_events.html
devtools/client/inspector/markup/test/doc_markup_events1.html
devtools/client/inspector/markup/test/doc_markup_events2.html
devtools/client/inspector/markup/test/doc_markup_events3.html
devtools/server/actors/inspector.js
--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -2,17 +2,19 @@
 tags = devtools
 subsuite = devtools
 support-files =
   actor_events_form.js
   doc_markup_anonymous.html
   doc_markup_dragdrop.html
   doc_markup_dragdrop_autoscroll.html
   doc_markup_edit.html
-  doc_markup_events.html
+  doc_markup_events1.html
+  doc_markup_events2.html
+  doc_markup_events3.html
   doc_markup_events_form.html
   doc_markup_events_jquery.html
   doc_markup_events-overflow.html
   doc_markup_flashing.html
   doc_markup_html_mixed_case.html
   doc_markup_image_and_canvas.html
   doc_markup_image_and_canvas_2.html
   doc_markup_links.html
@@ -57,17 +59,19 @@ skip-if = e10s # scratchpad.xul is not l
 [browser_markup_dragdrop_autoscroll.js]
 [browser_markup_dragdrop_distance.js]
 [browser_markup_dragdrop_draggable.js]
 [browser_markup_dragdrop_dragRootNode.js]
 [browser_markup_dragdrop_escapeKeyPress.js]
 [browser_markup_dragdrop_invalidNodes.js]
 [browser_markup_dragdrop_reorder.js]
 [browser_markup_dragdrop_tooltip.js]
-[browser_markup_events.js]
+[browser_markup_events1.js]
+[browser_markup_events2.js]
+[browser_markup_events3.js]
 [browser_markup_events_form.js]
 [browser_markup_events_jquery_1.0.js]
 [browser_markup_events_jquery_1.1.js]
 [browser_markup_events_jquery_1.2.js]
 [browser_markup_events_jquery_1.3.js]
 [browser_markup_events_jquery_1.4.js]
 [browser_markup_events_jquery_1.6.js]
 [browser_markup_events_jquery_1.7.js]
rename from devtools/client/inspector/markup/test/browser_markup_events.js
rename to devtools/client/inspector/markup/test/browser_markup_events1.js
--- a/devtools/client/inspector/markup/test/browser_markup_events.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events1.js
@@ -3,17 +3,17 @@
  http://creativecommons.org/publicdomain/zero/1.0/ */
 /* import-globals-from helper_events_test_runner.js */
 
 "use strict";
 
 // Test that markup view event bubbles show the correct event info for DOM
 // events.
 
-const TEST_URL = URL_ROOT + "doc_markup_events.html";
+const TEST_URL = URL_ROOT + "doc_markup_events1.html";
 
 loadHelperScript("helper_events_test_runner.js");
 
 const TEST_DATA = [ // eslint-disable-line
   {
     selector: "html",
     expected: [
       {
@@ -27,17 +27,17 @@ const TEST_DATA = [ // eslint-disable-li
       }
     ]
   },
   {
     selector: "#container",
     expected: [
       {
         type: "mouseover",
-        filename: TEST_URL + ":62",
+        filename: TEST_URL + ":45",
         attributes: [
           "Capturing",
           "DOM2"
         ],
         handler: "function mouseoverHandler(event) {\n" +
                  "  if (event.target.id !== \"container\") {\n" +
                  "    let output = document.getElementById(\"output\");\n" +
                  "    output.textContent = event.target.textContent;\n" +
@@ -46,135 +46,57 @@ const TEST_DATA = [ // eslint-disable-li
       }
     ]
   },
   {
     selector: "#multiple",
     expected: [
       {
         type: "click",
-        filename: TEST_URL + ":69",
+        filename: TEST_URL + ":52",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function clickHandler(event) {\n" +
                  "  let output = document.getElementById(\"output\");\n" +
                  "  output.textContent = \"click\";\n" +
                  "}"
       },
       {
         type: "mouseup",
-        filename: TEST_URL + ":78",
+        filename: TEST_URL + ":57",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function mouseupHandler(event) {\n" +
                  "  let output = document.getElementById(\"output\");\n" +
                  "  output.textContent = \"mouseup\";\n" +
                  "}"
       }
     ]
   },
-  {
-    selector: "#DOM0",
-    expected: [
-      {
-        type: "click",
-        filename: TEST_URL,
-        attributes: [
-          "Bubbling",
-          "DOM0"
-        ],
-        handler: "alert('hi')"
-      }
-    ]
-  },
-  {
-    selector: "#handleevent",
-    expected: [
-      {
-        type: "click",
-        filename: TEST_URL + ":89",
-        attributes: [
-          "Bubbling",
-          "DOM2"
-        ],
-        handler: "handleEvent: function(blah) {\n" +
-                 "  alert(\"handleEvent clicked\");\n" +
-                 "}"
-      }
-    ]
-  },
-  {
-    selector: "#fatarrow",
-    expected: [
-      {
-        type: "click",
-        filename: TEST_URL + ":57",
-        attributes: [
-          "Bubbling",
-          "DOM2"
-        ],
-        handler: "event => {\n" +
-                 "  alert(\"Yay for the fat arrow!\");\n" +
-                 "}"
-      }
-    ]
-  },
-  {
-    selector: "#boundhe",
-    expected: [
-      {
-        type: "click",
-        filename: TEST_URL + ":101",
-        attributes: [
-          "Bubbling",
-          "DOM2"
-        ],
-        handler: "handleEvent: function() {\n" +
-                 "  alert(\"boundHandleEvent clicked\");\n" +
-                 "}"
-      }
-    ]
-  },
-  {
-    selector: "#bound",
-    expected: [
-      {
-        type: "click",
-        filename: TEST_URL + ":74",
-        attributes: [
-          "Bubbling",
-          "DOM2"
-        ],
-        handler: "function boundClickHandler(event) {\n" +
-                 "  alert(\"Bound event clicked\");\n" +
-                 "}"
-      }
-    ]
-  },
   // #noevents tests check that dynamically added events are properly displayed
   // in the markupview
   {
     selector: "#noevents",
     expected: []
   },
   {
     selector: "#noevents",
     beforeTest: function* (inspector, testActor) {
       let nodeMutated = inspector.once("markupmutation");
       yield testActor.eval("window.wrappedJSObject.addNoeventsClickHandler();");
       yield nodeMutated;
     },
     expected: [
       {
         type: "click",
-        filename: TEST_URL + ":106",
+        filename: TEST_URL + ":72",
         attributes: [
           "Bubbling",
           "DOM2"
         ],
         handler: "function noeventsClickHandler(event) {\n" +
                  "  alert(\"noevents has an event listener\");\n" +
                  "}"
       }
@@ -185,13 +107,43 @@ const TEST_DATA = [ // eslint-disable-li
     beforeTest: function* (inspector, testActor) {
       let nodeMutated = inspector.once("markupmutation");
       yield testActor.eval(
         "window.wrappedJSObject.removeNoeventsClickHandler();");
       yield nodeMutated;
     },
     expected: []
   },
+  {
+    selector: "#DOM0",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL,
+        attributes: [
+          "Bubbling",
+          "DOM0"
+        ],
+        handler: "alert('DOM0')"
+      }
+    ]
+  },
+  {
+    selector: "#handleevent",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":67",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "handleEvent: function(blah) {\n" +
+                 "  alert(\"handleEvent\");\n" +
+                 "}"
+      }
+    ]
+  }
 ];
 
 add_task(function* () {
   yield runEventPopupTests(TEST_URL, TEST_DATA);
 });
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/browser_markup_events2.js
@@ -0,0 +1,163 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+/* import-globals-from helper_events_test_runner.js */
+
+"use strict";
+
+// Test that markup view event bubbles show the correct event info for DOM
+// events.
+
+const TEST_URL = URL_ROOT + "doc_markup_events2.html";
+
+loadHelperScript("helper_events_test_runner.js");
+
+const TEST_DATA = [ // eslint-disable-line
+  {
+    selector: "#fatarrow",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":39",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "() => {\n" +
+                 "  alert(\"Fat arrow without params!\");\n" +
+                 "}"
+      },
+      {
+        type: "click",
+        filename: TEST_URL + ":43",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "event => {\n" +
+                 "  alert(\"Fat arrow with 1 param!\");\n" +
+                 "}"
+      },
+      {
+        type: "click",
+        filename: TEST_URL + ":47",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "(event, foo, bar) => {\n" +
+                 "  alert(\"Fat arrow with 3 params!\");\n" +
+                 "}"
+      },
+      {
+        type: "click",
+        filename: TEST_URL + ":51",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "b => b"
+      }
+    ]
+  },
+  {
+    selector: "#bound",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":62",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function boundClickHandler(event) {\n" +
+                 "  alert(\"Bound event\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#boundhe",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":85",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "handleEvent: function() {\n" +
+                 "  alert(\"boundHandleEvent\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#comment-inline",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":91",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function functionProceededByInlineComment() {\n" +
+                 "  alert(\"comment-inline\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#comment-streaming",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":96",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function functionProceededByStreamingComment() {\n" +
+                 "  alert(\"comment-streaming\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#anon-object-method",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":71",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "anonObjectMethod: function() {\n" +
+                 "  alert(\"obj.anonObjectMethod\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#object-method",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":75",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "objectMethod: function kay() {\n" +
+                 "  alert(\"obj.objectMethod\");\n" +
+                 "}"
+      }
+    ]
+  }
+];
+
+add_task(function* () {
+  yield runEventPopupTests(TEST_URL, TEST_DATA);
+});
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/browser_markup_events3.js
@@ -0,0 +1,161 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+/* import-globals-from helper_events_test_runner.js */
+
+"use strict";
+
+// Test that markup view event bubbles show the correct event info for DOM
+// events.
+
+const TEST_URL = URL_ROOT + "doc_markup_events3.html";
+
+loadHelperScript("helper_events_test_runner.js");
+
+const TEST_DATA = [ // eslint-disable-line
+  {
+    selector: "#es6-method",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":91",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "es6Method() {\n" +
+                 "  alert(\"obj.es6Method\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#generator",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":96",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function* generator() {\n" +
+                 "  alert(\"generator\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#anon-generator",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":55",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function*() {\n" +
+                 "  alert(\"anonGenerator\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#named-function-expression",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":23",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "let namedFunctionExpression =\n" +
+                 "  function foo() {\n" +
+                 "    alert(\"namedFunctionExpression\");\n" +
+                 "  }"
+      }
+    ]
+  },
+  {
+    selector: "#anon-function-expression",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":27",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "let anonFunctionExpression = function() {\n" +
+                 "  alert(\"anonFunctionExpression\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#returned-function",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":32",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "function bar() {\n" +
+                 "  alert(\"returnedFunction\");\n" +
+                 "}"
+      }
+    ]
+  },
+  {
+    selector: "#constructed-function",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":1",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: ""
+      }
+    ]
+  },
+  {
+    selector: "#constructed-function-with-body-string",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":1",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "alert(\"constructedFuncWithBodyString\");"
+      }
+    ]
+  },
+  {
+    selector: "#multiple-assignment",
+    expected: [
+      {
+        type: "click",
+        filename: TEST_URL + ":42",
+        attributes: [
+          "Bubbling",
+          "DOM2"
+        ],
+        handler: "let multipleAssignment = foo = bar = function multi() {\n" +
+                 "  alert(\"multipleAssignment\");\n" +
+                 "}"
+      }
+    ]
+  },
+];
+
+add_task(function* () {
+  yield runEventPopupTests(TEST_URL, TEST_DATA);
+});
--- a/devtools/client/inspector/markup/test/browser_markup_events_jquery_1.0.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events_jquery_1.0.js
@@ -18,18 +18,17 @@ const TEST_DATA = [
     selector: "html",
     expected: [
       {
         type: "load",
         filename: URL_ROOT + TEST_LIB,
         attributes: [
           "jQuery"
         ],
-        handler: "// Handle when the DOM is ready\n" +
-                 "ready: function() {\n" +
+        handler: "ready: function() {\n" +
                  "  // Make sure that the DOM is not already loaded\n" +
                  "  if (!jQuery.isReady) {\n" +
                  "    // Remember that the DOM is ready\n" +
                  "    jQuery.isReady = true;\n" +
                  "\n" +
                  "    // If there are functions bound, to execute\n" +
                  "    if (jQuery.readyList) {\n" +
                  "      // Execute all of them\n" +
--- a/devtools/client/inspector/markup/test/browser_markup_events_jquery_1.1.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events_jquery_1.1.js
@@ -18,18 +18,17 @@ const TEST_DATA = [
     selector: "html",
     expected: [
       {
         type: "load",
         filename: URL_ROOT + TEST_LIB,
         attributes: [
           "jQuery"
         ],
-        handler: "// Handle when the DOM is ready\n" +
-                 "ready: function() {\n" +
+        handler: "ready: function() {\n" +
                  "  // Make sure that the DOM is not already loaded\n" +
                  "  if (!jQuery.isReady) {\n" +
                  "    // Remember that the DOM is ready\n" +
                  "    jQuery.isReady = true;\n" +
                  "\n" +
                  "    // If there are functions bound, to execute\n" +
                  "    if (jQuery.readyList) {\n" +
                  "      // Execute all of them\n" +
rename from devtools/client/inspector/markup/test/doc_markup_events.html
rename to devtools/client/inspector/markup/test/doc_markup_events1.html
--- a/devtools/client/inspector/markup/test/doc_markup_events.html
+++ b/devtools/client/inspector/markup/test/doc_markup_events1.html
@@ -14,116 +14,83 @@
       display: inline-block;
       margin: 2px;
     }
 
     #output,
     #noevents,
     #DOM0,
     #handleevent,
-    #fatarrow,
-    #bound,
-    #boundhe {
-      border: 1px solid #000;
-      width: 200px;
-      min-height: 1em;
-      cursor: pointer;
-    }
-
     #output,
     #noevents {
       cursor: auto;
     }
 
     #output {
       min-height: 1.5em;
     }
     </style>
     <script type="application/javascript;version=1.8">
       function init() {
         let container = document.getElementById("container");
         let multiple = document.getElementById("multiple");
-        let fatarrow = document.getElementById("fatarrow");
 
         container.addEventListener("mouseover", mouseoverHandler, true);
         multiple.addEventListener("click", clickHandler, false);
         multiple.addEventListener("mouseup", mouseupHandler, false);
 
-        new handleEventClick();
-        new boundHandleEventClick();
-
-        let bound = document.getElementById("bound");
-        boundClickHandler = boundClickHandler.bind(this);
-        bound.addEventListener("click", boundClickHandler);
-
-        fatarrow.addEventListener("click", event => {
-          alert("Yay for the fat arrow!");
-        });
+        let he = new handleEventClick();
+        let handleevent = document.getElementById("handleevent");
+        handleevent.addEventListener("click", he);
       }
 
       function mouseoverHandler(event) {
         if (event.target.id !== "container") {
           let output = document.getElementById("output");
           output.textContent = event.target.textContent;
         }
       }
 
       function clickHandler(event) {
         let output = document.getElementById("output");
         output.textContent = "click";
       }
 
-      function boundClickHandler(event) {
-        alert("Bound event clicked");
-      }
-
       function mouseupHandler(event) {
         let output = document.getElementById("output");
         output.textContent = "mouseup";
       }
 
       function handleEventClick(hehe) {
-        let handleevent = document.getElementById("handleevent");
-        handleevent.addEventListener("click", this);
+
       }
 
       handleEventClick.prototype = {
         handleEvent: function(blah) {
-          alert("handleEvent clicked");
-        }
-      };
-
-      function boundHandleEventClick() {
-        let boundhe = document.getElementById("boundhe");
-        this.handleEvent = this.handleEvent.bind(this);
-        boundhe.addEventListener("click", this);
-      }
-
-      boundHandleEventClick.prototype = {
-        handleEvent: function() {
-          alert("boundHandleEvent clicked");
+          alert("handleEvent");
         }
       };
 
       function noeventsClickHandler(event) {
         alert("noevents has an event listener");
-      };
+      }
 
       function addNoeventsClickHandler() {
         let noevents = document.getElementById("noevents");
         noevents.addEventListener("click", noeventsClickHandler);
-      };
+      }
 
       function removeNoeventsClickHandler() {
         let noevents = document.getElementById("noevents");
         noevents.removeEventListener("click", noeventsClickHandler);
-      };
+      }
     </script>
   </head>
   <body onload="init();">
+    <h1>Events test 1</h1>
     <div id="container">
       <div>1</div>
       <div>2</div>
       <div>3</div>
       <div>4</div>
       <div>5</div>
       <div>6</div>
       <div>7</div>
@@ -134,16 +101,13 @@
       <div>12</div>
       <div>13</div>
       <div>14</div>
       <div>15</div>
       <div>16</div>
       <div id="multiple">multiple</div>
     </div>
     <div id="output"></div>
-    <div id="noevents">No events here</div>
-    <div id="DOM0" onclick="alert('hi')">DOM0 event here</div>
-    <div id="handleevent">handleEvent event here</div>
-    <div id="fatarrow">Fat arrow event</div>
-    <div id="boundhe">Bound handleEvent</div>
-    <div id="bound">Bound event</div>
+    <div id="noevents">noevents</div>
+    <div id="DOM0" onclick="alert('DOM0')">DOM0 event here</div>
+    <div id="handleevent">handleEvent</div>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/doc_markup_events2.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <style>
+    #fatarrow,
+    #bound,
+    #boundhe,
+    #comment-inline,
+    #comment-streaming,
+    #anon-object-method,
+    #object-method {
+      border: 1px solid #000;
+      width: 200px;
+      min-height: 1em;
+      cursor: pointer;
+    }
+    </style>
+    <script type="application/javascript;version=1.8">
+      function init() {
+        let fatarrow = document.getElementById("fatarrow");
+
+        let he = new handleEventClick();
+        let anonObjectMethod = document.getElementById("anon-object-method");
+        anonObjectMethod.addEventListener("click", he.anonObjectMethod);
+
+        let objectMethod = document.getElementById("object-method");
+        objectMethod.addEventListener("click", he.objectMethod);
+
+        let bhe = new boundHandleEventClick();
+        let boundheNode = document.getElementById("boundhe");
+        bhe.handleEvent = bhe.handleEvent.bind(bhe);
+        boundheNode.addEventListener("click", bhe);
+
+        let boundNode = document.getElementById("bound");
+        boundClickHandler = boundClickHandler.bind(this);
+        boundNode.addEventListener("click", boundClickHandler);
+
+        fatarrow.addEventListener("click", () => {
+          alert("Fat arrow without params!");
+        });
+
+        fatarrow.addEventListener("click", event => {
+          alert("Fat arrow with 1 param!");
+        });
+
+        fatarrow.addEventListener("click", (event, foo, bar) => {
+          alert("Fat arrow with 3 params!");
+        });
+
+        fatarrow.addEventListener("click", b => b);
+
+        let inlineCommentNode = document.getElementById("comment-inline");
+        inlineCommentNode
+          .addEventListener("click", functionProceededByInlineComment);
+
+        let streamingCommentNode = document.getElementById("comment-streaming");
+        streamingCommentNode
+          .addEventListener("click", functionProceededByStreamingComment);
+      }
+
+      function boundClickHandler(event) {
+        alert("Bound event");
+      }
+
+      function handleEventClick(hehe) {
+
+      }
+
+      handleEventClick.prototype = {
+        anonObjectMethod: function() {
+          alert("obj.anonObjectMethod");
+        },
+
+        objectMethod: function kay() {
+          alert("obj.objectMethod");
+        },
+      };
+
+      function boundHandleEventClick() {
+
+      }
+
+      boundHandleEventClick.prototype = {
+        handleEvent: function() {
+          alert("boundHandleEvent");
+        }
+      };
+
+      // A function proceeded with an inline comment
+      function functionProceededByInlineComment() {
+        alert("comment-inline");
+      }
+
+      /* A function proceeded with a streaming comment */
+      function functionProceededByStreamingComment() {
+        alert("comment-streaming");
+      }
+    </script>
+  </head>
+  <body onload="init();">
+    <h1>Events test 2</h1>
+    <div id="fatarrow">Fat arrows</div>
+    <div id="boundhe">Bound handleEvent</div>
+    <div id="bound">Bound event</div>
+    <div id="comment-inline">Event proceeded by an inline comment</div>
+    <div id="comment-streaming">Event proceeded by a streaming comment</div>
+    <div id="anon-object-method">Anonymous object method</div>
+    <div id="object-method">Object method</div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/markup/test/doc_markup_events3.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <style>
+    #es6-method,
+    #generator,
+    #anon-generator,
+    #named-function-expression,
+    #anon-function-expression,
+    #returned-function,
+    #constructed-function,
+    #constructed-function-with-body-string,
+    #multiple-assignment {
+      border: 1px solid #000;
+      width: 200px;
+      min-height: 1em;
+      cursor: pointer;
+    }
+    </style>
+    <script type="application/javascript;version=1.8">
+      let namedFunctionExpression =
+      function foo() {
+        alert("namedFunctionExpression");
+      }
+
+      let anonFunctionExpression = function() {
+        alert("anonFunctionExpression");
+      };
+
+      let returnedFunction = (function() {
+        return function bar() {
+          alert("returnedFunction");
+        }
+      })();
+
+      let constructedFunc = new Function();
+
+      let constructedFuncWithBodyString =
+        new Function('a', 'b', 'c', 'alert("constructedFuncWithBodyString");');
+
+      let multipleAssignment = foo = bar = function multi() {
+        alert("multipleAssignment");
+      }
+
+      function init() {
+        let he = new handleEventClick();
+        let es6Method = document.getElementById("es6-method");
+        es6Method.addEventListener("click", he.es6Method);
+
+        let generatorNode = document.getElementById("generator");
+        generatorNode.addEventListener("click", generator);
+
+        let anonGenerator = document.getElementById("anon-generator");
+        anonGenerator.addEventListener("click", function* () {
+          alert("anonGenerator");
+        });
+
+        let namedFunctionExpressionNode =
+          document.getElementById("named-function-expression");
+        namedFunctionExpressionNode.addEventListener("click",
+                                                     namedFunctionExpression);
+
+        let anonFunctionExpressionNode =
+          document.getElementById("anon-function-expression");
+        anonFunctionExpressionNode.addEventListener("click",
+                                                     anonFunctionExpression);
+
+        let returnedFunctionNode = document.getElementById("returned-function");
+        returnedFunctionNode.addEventListener("click", returnedFunction);
+
+        let constructedFunctionNode =
+          document.getElementById("constructed-function");
+        constructedFunctionNode.addEventListener("click", constructedFunc);
+
+        let constructedFunctionWithBodyStringNode =
+          document.getElementById("constructed-function-with-body-string");
+        constructedFunctionWithBodyStringNode
+          .addEventListener("click", constructedFuncWithBodyString);
+
+        let multipleAssignmentNode =
+          document.getElementById("multiple-assignment");
+        multipleAssignmentNode.addEventListener("click", multipleAssignment);
+      }
+
+      function handleEventClick(hehe) {
+
+      }
+
+      handleEventClick.prototype = {
+        es6Method() {
+          alert("obj.es6Method");
+        }
+      };
+
+      function* generator() {
+        alert("generator");
+      }
+    </script>
+  </head>
+  <body onload="init();">
+    <h1>Events test 3</h1>
+    <div id="es6-method">ES6 method</div>
+    <div id="generator">Generator</div>
+    <div id="anon-generator">Anonymous Generator</div>
+    <div id="named-function-expression">Named Function Expression</div>
+    <div id="anon-function-expression">Anonymous Function Expression</div>
+    <div id="returned-function">Returned Function</div>
+    <div id="constructed-function">Constructed Function</div>
+    <div id="constructed-function-with-body-string">
+      Constructed Function with body string
+    </div>
+    <div id="multiple-assignment">Multiple Assignment</div>
+  </body>
+</html>
--- a/devtools/server/actors/inspector.js
+++ b/devtools/server/actors/inspector.js
@@ -82,18 +82,20 @@ loader.lazyRequireGetter(this, "CSS", "C
 
 const {EventParsers} = require("devtools/shared/event-parsers");
 
 const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
 const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
 const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
 const HIDDEN_CLASS = "__fx-devtools-hide-shortcut__";
 const XHTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const IMAGE_FETCHING_TIMEOUT = 500;
+const RX_FUNC_NAME = /((var|const|let)\s+)?([\w$.]+\s*[:=]\s*)*(function)?\s*\*?\s*([\w$]+)?\s*$/;
+
 // The possible completions to a ':' with added score to give certain values
 // some preference.
 const PSEUDO_SELECTORS = [
   [":active", 1],
   [":hover", 1],
   [":focus", 1],
   [":visited", 0],
   [":link", 0],
@@ -548,38 +550,32 @@ var NodeActor = exports.NodeActor = prot
     let script = listenerDO.script;
     let scriptSource = script.source.text;
     let functionSource =
       scriptSource.substr(script.sourceStart, script.sourceLength);
 
     /*
     The script returned is the whole script and
     scriptSource.substr(script.sourceStart, script.sourceLength) returns
-    something like:
+    something like this:
       () { doSomething(); }
 
-    So we need to work back to the preceeding \n, ; or } so we can get the
-      appropriate function info e.g.:
-      () => { doSomething(); }
-      function doit() { doSomething(); }
-      doit: function() { doSomething(); }
+    So we need to use some regex magic to get the appropriate function info
+    e.g.:
+      () => { ... }
+      function doit() { ... }
+      doit: function() { ... }
+      es6func() { ... }
+      var|let|const foo = function () { ... }
+      function generator*() { ... }
     */
     let scriptBeforeFunc = scriptSource.substr(0, script.sourceStart);
-    let lastEnding = Math.max(
-      scriptBeforeFunc.lastIndexOf(";"),
-      scriptBeforeFunc.lastIndexOf("}"),
-      scriptBeforeFunc.lastIndexOf("{"),
-      scriptBeforeFunc.lastIndexOf("("),
-      scriptBeforeFunc.lastIndexOf(","),
-      scriptBeforeFunc.lastIndexOf("!")
-    );
-
-    if (lastEnding !== -1) {
-      let functionPrefix = scriptBeforeFunc.substr(lastEnding + 1);
-      functionSource = functionPrefix + functionSource;
+    let matches = scriptBeforeFunc.match(RX_FUNC_NAME);
+    if (matches && matches.length > 0) {
+      functionSource = matches[0].trim() + functionSource;
     }
 
     let dom0 = false;
 
     if (typeof node.hasAttribute !== "undefined") {
       dom0 = !!node.hasAttribute("on" + type);
     } else {
       dom0 = !!node["on" + type];