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 id30214
push userkwierso@gmail.com
push dateTue, 26 Apr 2016 21:17:19 +0000
treeherdermozilla-central@6a441b2b2997 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersochameau
bugs1226548
milestone49.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 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];