Bug 851836 - breakpoints[aLocation.line] is undefined after bug 820012; r=past
authorEddy Bruel <ejpbruel@mozilla.com>
Mon, 22 Apr 2013 08:44:00 +0300
changeset 140514 7e4501974b5be152de4c3ea0dff61f11b9f94cd7
parent 140513 6bb651b07ae10ecf2ab8e20adf9f35a76f61110b
child 140515 9a35bbea86c707d08199920e06678e8f99937ed2
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs851836, 820012
milestone23.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 851836 - breakpoints[aLocation.line] is undefined after bug 820012; r=past
toolkit/devtools/debugger/server/dbg-script-actors.js
--- a/toolkit/devtools/debugger/server/dbg-script-actors.js
+++ b/toolkit/devtools/debugger/server/dbg-script-actors.js
@@ -592,35 +592,41 @@ ThreadActor.prototype = {
    * take that into account.
    *
    * @param object aLocation
    *        The location of the breakpoint as specified in the protocol.
    */
   _setBreakpoint: function TA__setBreakpoint(aLocation) {
     let breakpoints = this._breakpointStore[aLocation.url];
 
+    // Get or create the breakpoint actor for the given location
     let actor;
     if (breakpoints[aLocation.line].actor) {
       actor = breakpoints[aLocation.line].actor;
     } else {
       actor = breakpoints[aLocation.line].actor = new BreakpointActor(this, {
         url: aLocation.url,
         line: aLocation.line
       });
       this._hooks.addToParentPool(actor);
     }
 
+    // Find all scripts matching the given location
     let scripts = this.dbg.findScripts(aLocation);
     if (scripts.length == 0) {
       return {
         error: "noScript",
         actor: actor.actorID
       };
     }
 
+   /**
+     * For each script, if the given line has at least one entry point, set
+     * breakpoint on the bytecode offet for each of them.
+     */
     let found = false;
     for (let script of scripts) {
       let offsets = script.getLineOffsets(aLocation.line);
       if (offsets.length > 0) {
         for (let offset of offsets) {
           script.setBreakpoint(offset, actor);
         }
         actor.addScript(script, this);
@@ -628,65 +634,93 @@ ThreadActor.prototype = {
       }
     }
     if (found) {
       return {
         actor: actor.actorID
       };
     }
 
+   /**
+     * If we get here, no breakpoint was set. This is because the given line
+     * has no entry points, for example because it is empty. As a fallback
+     * strategy, we try to set the breakpoint on the smallest line greater
+     * than or equal to the given line that as at least one entry point.
+     */
+
+    // Find all innermost scripts matching the given location
     let scripts = this.dbg.findScripts({
       url: aLocation.url,
       line: aLocation.line,
       innermost: true
     });
 
+    /**
+     * For each innermost script, look for the smallest line greater than or
+     * equal to the given line that has one or more entry points. If found, set
+     * a breakpoint on the bytecode offset for each of its entry points.
+     */
     let actualLocation;
     let found = false;
     for (let script of scripts) {
       let offsets = script.getAllOffsets();
       for (let line = aLocation.line; line < offsets.length; ++line) {
         if (offsets[line]) {
           for (let offset of offsets[line]) {
             script.setBreakpoint(offset, actor);
           }
           actor.addScript(script, this);
           if (!actualLocation) {
             actualLocation = {
               url: aLocation.url,
               line: line,
-              column: aLocation.column
+              column: 0
             };
           }
           found = true;
           break;
         }
       }
     }
     if (found) {
       if (breakpoints[actualLocation.line] &&
           breakpoints[actualLocation.line].actor) {
+        /**
+         * We already have a breakpoint actor for the actual location, so
+         * actor we created earlier is now redundant. Delete it, update the
+         * breakpoint store, and return the actor for the actual location.
+         */
         actor.onDelete();
         delete breakpoints[aLocation.line];
         return {
           actor: breakpoints[actualLocation.line].actor.actorID,
           actualLocation: actualLocation
         };
       } else {
+        /**
+         * We don't have a breakpoint actor for the actual location yet.
+         * Instead or creating a new actor, reuse the actor we created earlier,
+         * and update the breakpoint store.
+         */
         actor.location = actualLocation;
         breakpoints[actualLocation.line] = breakpoints[aLocation.line];
+        delete breakpoints[aLocation.line];
+        // WARNING: This overwrites aLocation.line
         breakpoints[actualLocation.line].line = actualLocation.line;
-        delete breakpoints[aLocation.line];
         return {
           actor: actor.actorID,
           actualLocation: actualLocation
         };
       }
     }
 
+    /**
+     * If we get here, no line matching the given line was found, so just
+     * epically.
+     */
     return {
       error: "noCodeAtLineColumn",
       actor: actor.actorID
     };
   },
 
   /**
    * Get the script and source lists from the debugger.