Bug 1235374 - Change BreakpointActor to protocol.js. r=jryans
authorLin Clark <lclark@mozilla.com>
Fri, 22 Jan 2016 15:52:00 -0500
changeset 281391 76a10b1ae6abce425b0bca991be85662e5219a77
parent 281390 ab602ecfad88669fdf4d2174a8d74324eb1cf5d6
child 281392 c09a55daebd324a033eab19104f9c97f4f2f98de
push id29935
push userphilringnalda@gmail.com
push dateSun, 24 Jan 2016 02:12:02 +0000
treeherdermozilla-central@a2e81822194a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1235374
milestone46.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 1235374 - Change BreakpointActor to protocol.js. r=jryans
devtools/server/actors/breakpoint.js
devtools/server/actors/moz.build
devtools/server/actors/script.js
new file mode 100644
--- /dev/null
+++ b/devtools/server/actors/breakpoint.js
@@ -0,0 +1,170 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { ActorClass, method } = require("devtools/server/protocol");
+
+/**
+ * BreakpointActors exist for the lifetime of their containing thread and are
+ * responsible for deleting breakpoints, handling breakpoint hits and
+ * associating breakpoints with scripts.
+ */
+let BreakpointActor = ActorClass({
+  typeName: "breakpoint",
+
+  /**
+   * Create a Breakpoint actor.
+   *
+   * @param ThreadActor threadActor
+   *        The parent thread actor that contains this breakpoint.
+   * @param OriginalLocation originalLocation
+   *        The original location of the breakpoint.
+   */
+  initialize: function(threadActor, originalLocation) {
+    // The set of Debugger.Script instances that this breakpoint has been set
+    // upon.
+    this.scripts = new Set();
+
+    this.threadActor = threadActor;
+    this.originalLocation = originalLocation;
+    this.condition = null;
+    this.isPending = true;
+  },
+
+  disconnect: function() {
+    this.removeScripts();
+  },
+
+  hasScript: function(script) {
+    return this.scripts.has(script);
+  },
+
+  /**
+   * Called when this same breakpoint is added to another Debugger.Script
+   * instance.
+   *
+   * @param script Debugger.Script
+   *        The new source script on which the breakpoint has been set.
+   */
+  addScript: function(script) {
+    this.scripts.add(script);
+    this.isPending = false;
+  },
+
+  /**
+   * Remove the breakpoints from associated scripts and clear the script cache.
+   */
+  removeScripts: function() {
+    for (let script of this.scripts) {
+      script.clearBreakpoint(this);
+    }
+    this.scripts.clear();
+  },
+
+  /**
+   * Check if this breakpoint has a condition that doesn't error and
+   * evaluates to true in frame.
+   *
+   * @param frame Debugger.Frame
+   *        The frame to evaluate the condition in
+   * @returns Object
+   *          - result: boolean|undefined
+   *            True when the conditional breakpoint should trigger a pause,
+   *            false otherwise. If the condition evaluation failed/killed,
+   *            `result` will be `undefined`.
+   *          - message: string
+   *            If the condition throws, this is the thrown message.
+   */
+  checkCondition: function(frame) {
+    let completion = frame.eval(this.condition);
+    if (completion) {
+      if (completion.throw) {
+        // The evaluation failed and threw
+        let message = "Unknown exception";
+        try {
+          if (completion.throw.getOwnPropertyDescriptor) {
+            message = completion.throw.getOwnPropertyDescriptor("message")
+                      .value;
+          } else if (completion.toString) {
+            message = completion.toString();
+          }
+        } catch (ex) {}
+        return {
+          result: true,
+          message: message
+        };
+      } else if (completion.yield) {
+        assert(false, "Shouldn't ever get yield completions from an eval");
+      } else {
+        return { result: completion.return ? true : false };
+      }
+    } else {
+      // The evaluation was killed (possibly by the slow script dialog)
+      return { result: undefined };
+    }
+  },
+
+  /**
+   * A function that the engine calls when a breakpoint has been hit.
+   *
+   * @param frame Debugger.Frame
+   *        The stack frame that contained the breakpoint.
+   */
+  hit: function (frame) {
+    // Don't pause if we are currently stepping (in or over) or the frame is
+    // black-boxed.
+    let generatedLocation = this.threadActor.sources.getFrameLocation(frame);
+    let { originalSourceActor } = this.threadActor.unsafeSynchronize(
+      this.threadActor.sources.getOriginalLocation(generatedLocation));
+    let url = originalSourceActor.url;
+
+    if (this.threadActor.sources.isBlackBoxed(url)
+        || frame.onStep) {
+      return undefined;
+    }
+
+    let reason = {};
+
+    if (this.threadActor._hiddenBreakpoints.has(this.actorID)) {
+      reason.type = "pauseOnDOMEvents";
+    } else if (!this.condition) {
+      reason.type = "breakpoint";
+      // TODO: add the rest of the breakpoints on that line (bug 676602).
+      reason.actors = [ this.actorID ];
+    } else {
+      let { result, message } = this.checkCondition(frame)
+
+      if (result) {
+        if (!message) {
+          reason.type = "breakpoint";
+        } else {
+          reason.type = "breakpointConditionThrown";
+          reason.message = message;
+        }
+        reason.actors = [ this.actorID ];
+      } else {
+        return undefined;
+      }
+    }
+    return this.threadActor._pauseAndRespond(frame, reason);
+  },
+
+  /**
+   * Handle a protocol request to remove this breakpoint.
+   */
+  delete: method(function() {
+    // Remove from the breakpoint store.
+    if (this.originalLocation) {
+      this.threadActor.breakpointActorMap.deleteActor(this.originalLocation);
+    }
+    this.threadActor.threadLifetimePool.removeActor(this);
+    // Remove the actual breakpoint from the associated scripts.
+    this.removeScripts();
+  })
+});
+
+exports.BreakpointActor = BreakpointActor;
--- a/devtools/server/actors/moz.build
+++ b/devtools/server/actors/moz.build
@@ -8,16 +8,17 @@ DIRS += [
     'highlighters',
     'utils',
 ]
 
 DevToolsModules(
     'actor-registry.js',
     'addon.js',
     'animation.js',
+    'breakpoint.js',
     'call-watcher.js',
     'canvas.js',
     'child-process.js',
     'childtab.js',
     'chrome.js',
     'common.js',
     'csscoverage.js',
     'device.js',
--- a/devtools/server/actors/script.js
+++ b/devtools/server/actors/script.js
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const Services = require("Services");
 const { Cc, Ci, Cu, components, ChromeWorker } = require("chrome");
 const { ActorPool, OriginalLocation, GeneratedLocation } = require("devtools/server/actors/common");
+const { BreakpointActor } = require("devtools/server/actors/breakpoint");
 const { FrameActor } = require("devtools/server/actors/frame");
 const { ObjectActor, createValueGrip, longStringGrip } = require("devtools/server/actors/object");
 const { DebuggerServer } = require("devtools/server/main");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { assert, dumpn, update, fetch } = DevToolsUtils;
 const { dirname, joinURI } = require("devtools/shared/path");
 const promise = require("promise");
 const PromiseDebugging = require("PromiseDebugging");
@@ -1526,17 +1527,17 @@ ThreadActor.prototype = {
     // Clear DOM event breakpoints.
     // XPCShell tests don't use actual DOM windows for globals and cause
     // removeListenerForAllEvents to throw.
     if (!isWorker && this.global && !this.global.toString().includes("Sandbox")) {
       let els = Cc["@mozilla.org/eventlistenerservice;1"]
                 .getService(Ci.nsIEventListenerService);
       els.removeListenerForAllEvents(this.global, this._allEventsListener, true);
       for (let [,bp] of this._hiddenBreakpoints) {
-        bp.onDelete();
+        bp.delete();
       }
       this._hiddenBreakpoints.clear();
     }
 
     this._state = "paused";
 
     // Create the actor pool that will hold the pause actor and its
     // children.
@@ -2790,17 +2791,17 @@ SourceActor.prototype = {
         );
 
         // Update the actor to use the new location (reusing a
         // previous breakpoint if it already exists on that line).
         const actualLocation = new OriginalLocation(originalSourceActor, actualLine);
         const existingActor = this.breakpointActorMap.getActor(actualLocation);
         this.breakpointActorMap.deleteActor(originalLocation);
         if (existingActor) {
-          actor.onDelete();
+          actor.delete();
           actor = existingActor;
         } else {
           actor.originalLocation = actualLocation;
           this.breakpointActorMap.setActor(actualLocation, actor);
         }
       }
 
       return promise.resolve(actor);
@@ -2969,182 +2970,16 @@ update(PauseScopedObjectActor.prototype,
   }),
 });
 
 update(PauseScopedObjectActor.prototype.requestTypes, {
   "threadGrip": PauseScopedObjectActor.prototype.onThreadGrip,
 });
 
 /**
- * Creates a BreakpointActor. BreakpointActors exist for the lifetime of their
- * containing thread and are responsible for deleting breakpoints, handling
- * breakpoint hits and associating breakpoints with scripts.
- *
- * @param ThreadActor aThreadActor
- *        The parent thread actor that contains this breakpoint.
- * @param OriginalLocation aOriginalLocation
- *        The original location of the breakpoint.
- */
-function BreakpointActor(aThreadActor, aOriginalLocation)
-{
-  // The set of Debugger.Script instances that this breakpoint has been set
-  // upon.
-  this.scripts = new Set();
-
-  this.threadActor = aThreadActor;
-  this.originalLocation = aOriginalLocation;
-  this.condition = null;
-  this.isPending = true;
-}
-
-BreakpointActor.prototype = {
-  actorPrefix: "breakpoint",
-  condition: null,
-
-  disconnect: function () {
-    this.removeScripts();
-  },
-
-  hasScript: function (aScript) {
-    return this.scripts.has(aScript);
-  },
-
-  /**
-   * Called when this same breakpoint is added to another Debugger.Script
-   * instance.
-   *
-   * @param aScript Debugger.Script
-   *        The new source script on which the breakpoint has been set.
-   * @param ThreadActor aThreadActor
-   *        The parent thread actor that contains this breakpoint.
-   */
-  addScript: function (aScript) {
-    this.scripts.add(aScript);
-    this.isPending = false;
-  },
-
-  /**
-   * Remove the breakpoints from associated scripts and clear the script cache.
-   */
-  removeScripts: function () {
-    for (let script of this.scripts) {
-      script.clearBreakpoint(this);
-    }
-    this.scripts.clear();
-  },
-
-  /**
-   * Check if this breakpoint has a condition that doesn't error and
-   * evaluates to true in aFrame.
-   *
-   * @param aFrame Debugger.Frame
-   *        The frame to evaluate the condition in
-   * @returns Object
-   *          - result: boolean|undefined
-   *            True when the conditional breakpoint should trigger a pause, false otherwise.
-   *            If the condition evaluation failed/killed, `result` will be `undefined`.
-   *          - message: string
-   *            The thrown message converted to a string, when the condition throws.
-   */
-  checkCondition: function(aFrame) {
-    let completion = aFrame.eval(this.condition);
-    if (completion) {
-      if (completion.throw) {
-        // The evaluation failed and threw
-        let message = "Unknown exception";
-        try {
-          if (completion.throw.getOwnPropertyDescriptor) {
-            message = completion.throw.getOwnPropertyDescriptor("message").value;
-          } else if (completion.toString) {
-            message = completion.toString();
-          }
-        } catch (ex) {}
-        return {
-          result: true,
-          message: message
-        };
-      } else if (completion.yield) {
-        assert(false, "Shouldn't ever get yield completions from an eval");
-      } else {
-        return { result: completion.return ? true : false };
-      }
-    } else {
-      // The evaluation was killed (possibly by the slow script dialog)
-      return { result: undefined };
-    }
-  },
-
-  /**
-   * A function that the engine calls when a breakpoint has been hit.
-   *
-   * @param aFrame Debugger.Frame
-   *        The stack frame that contained the breakpoint.
-   */
-  hit: function (aFrame) {
-    // Don't pause if we are currently stepping (in or over) or the frame is
-    // black-boxed.
-    let generatedLocation = this.threadActor.sources.getFrameLocation(aFrame);
-    let { originalSourceActor } = this.threadActor.unsafeSynchronize(
-      this.threadActor.sources.getOriginalLocation(generatedLocation));
-    let url = originalSourceActor.url;
-
-    if (this.threadActor.sources.isBlackBoxed(url)
-        || aFrame.onStep) {
-      return undefined;
-    }
-
-    let reason = {};
-
-    if (this.threadActor._hiddenBreakpoints.has(this.actorID)) {
-      reason.type = "pauseOnDOMEvents";
-    } else if (!this.condition) {
-      reason.type = "breakpoint";
-      // TODO: add the rest of the breakpoints on that line (bug 676602).
-      reason.actors = [ this.actorID ];
-    } else {
-      let { result, message } = this.checkCondition(aFrame)
-
-      if (result) {
-        if (!message) {
-          reason.type = "breakpoint";
-        } else {
-          reason.type = "breakpointConditionThrown";
-          reason.message = message;
-        }
-        reason.actors = [ this.actorID ];
-      } else {
-        return undefined;
-      }
-    }
-    return this.threadActor._pauseAndRespond(aFrame, reason);
-  },
-
-  /**
-   * Handle a protocol request to remove this breakpoint.
-   *
-   * @param aRequest object
-   *        The protocol request object.
-   */
-  onDelete: function (aRequest) {
-    // Remove from the breakpoint store.
-    if (this.originalLocation) {
-      this.threadActor.breakpointActorMap.deleteActor(this.originalLocation);
-    }
-    this.threadActor.threadLifetimePool.removeActor(this);
-    // Remove the actual breakpoint from the associated scripts.
-    this.removeScripts();
-    return { from: this.actorID };
-  }
-};
-
-BreakpointActor.prototype.requestTypes = {
-  "delete": BreakpointActor.prototype.onDelete
-};
-
-/**
  * Creates an EnvironmentActor. EnvironmentActors are responsible for listing
  * the bindings introduced by a lexical environment and assigning new values to
  * those identifier bindings.
  *
  * @param Debugger.Environment aEnvironment
  *        The lexical environment that will be used to create the actor.
  * @param ThreadActor aThreadActor
  *        The parent thread actor that contains this environment.