Bug 1147972 - Test setting a breakpoint on a line in a gcd script. r=jlong, a=lizzard
authorEddy Bruël <ejpbruel@gmail.com>
Fri, 27 Mar 2015 05:13:00 -0400
changeset 265821 923b536f3d2d12399ea9062ff5f94425b734f219
parent 265820 beaf7060929b93e1364093425eca7def97cc3808
child 265822 ec9550cf4108d91149c93263ad5ee62b0c435fdc
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlong, lizzard
bugs1147972
milestone39.0a2
Bug 1147972 - Test setting a breakpoint on a line in a gcd script. r=jlong, a=lizzard
toolkit/devtools/server/actors/script.js
toolkit/devtools/server/tests/unit/head_dbg.js
toolkit/devtools/server/tests/unit/setBreakpoint-on-line-in-gcd-script.js
toolkit/devtools/server/tests/unit/test_blackboxing-01.js
toolkit/devtools/server/tests/unit/test_setBreakpoint-on-line-in-gcd-script.js
toolkit/devtools/server/tests/unit/test_trace_actor-10.js
toolkit/devtools/server/tests/unit/xpcshell.ini
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -2746,33 +2746,27 @@ SourceActor.prototype = {
     }
 
     let { location: { line, column }, condition } = request;
     let location = new OriginalLocation(this, line, column);
     return this._getOrCreateBreakpointActor(
       location,
       condition
     ).then((actor) => {
-      if (actor.isPending) {
-        return {
-          error: "noCodeAtLocation",
-          actor: actor.actorID
-        };
-      } else {
-        let response = {
-          actor: actor.actorID
-        };
-
-        let actualLocation = actor.originalLocation;
-        if (!actualLocation.equals(location)) {
-          response.actualLocation = actualLocation.toJSON();
-        }
-
-        return response;
+      let response = {
+        actor: actor.actorID,
+        isPending: actor.isPending
+      };
+
+      let actualLocation = actor.originalLocation;
+      if (!actualLocation.equals(location)) {
+        response.actualLocation = actualLocation.toJSON();
       }
+
+      return response;
     });
   },
 
   /**
    * Get or create a BreakpointActor for the given location in the original
    * source, and ensure it is set as a breakpoint handler on all scripts that
    * match the given location.
    *
@@ -2880,17 +2874,17 @@ SourceActor.prototype = {
           while (actualLine < lineToEntryPointsMap.length) {
             let entryPoints = lineToEntryPointsMap[actualLine];
             if (entryPoints) {
               setBreakpointAtEntryPoints(actor, entryPoints);
               break;
             }
             ++actualLine;
           }
-          if (actualLine === lineToEntryPointsMap.length) {
+          if (actualLine >= lineToEntryPointsMap.length) {
             // We went past the last line in the map, so breakpoint sliding
             // failed. Keep the BreakpointActor in the BreakpointActorMap as a
             // pending breakpoint, so we can try again whenever a new script is
             // introduced.
             return originalLocation;
           }
 
           return new OriginalLocation(
--- a/toolkit/devtools/server/tests/unit/head_dbg.js
+++ b/toolkit/devtools/server/tests/unit/head_dbg.js
@@ -19,16 +19,31 @@ const Services = devtools.require("Servi
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 // Enable remote debugging for the relevant tests.
 Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
 
 const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils.js");
 const { DebuggerServer } = devtools.require("devtools/server/main");
 const { DebuggerServer: WorkerDebuggerServer } = worker.require("devtools/server/main");
 
+function getSources(threadClient) {
+  dump("Getting sources.\n");
+  return rdpRequest(threadClient, threadClient.getSources);
+}
+
+function findSource(sources, url) {
+  dump("Finding source with url '" + url + "'.\n");
+  for (let source of sources) {
+    if (source.url === url) {
+      return source;
+    }
+  }
+  return null;
+}
+
 function dumpn(msg) {
   dump("DBG-TEST: " + msg + "\n");
 }
 
 function tryImport(url) {
   try {
     Cu.import(url);
   } catch (e) {
@@ -551,27 +566,16 @@ function interrupt(threadClient) {
  * @returns Promise
  */
 function resumeAndWaitForPause(client, threadClient) {
   const paused = waitForPause(client);
   return resume(threadClient).then(() => paused);
 }
 
 /**
- * Get the list of sources for the specified thread.
- *
- * @param ThreadClient threadClient
- * @returns Promise
- */
-function getSources(threadClient) {
-  dumpn("Getting sources.");
-  return rdpRequest(threadClient, threadClient.getSources);
-}
-
-/**
  * Resume JS execution for a single step and wait for the pause after the step
  * has been taken.
  *
  * @param DebuggerClient client
  * @param ThreadClient threadClient
  * @returns Promise
  */
 function stepIn(client, threadClient) {
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/unit/setBreakpoint-on-line-in-gcd-script.js
@@ -0,0 +1,9 @@
+"use strict";
+
+function f() {}
+
+(function () {
+  var a = 1;
+  var b = 2;
+  var c = 3;
+})();
--- a/toolkit/devtools/server/tests/unit/test_blackboxing-01.js
+++ b/toolkit/devtools/server/tests/unit/test_blackboxing-01.js
@@ -30,19 +30,19 @@ const testBlackBox = Task.async(function
   let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
   let source = gThreadClient.source(packet.frame.where.source);
 
   yield setBreakpoint(source, {
     line: 2
   });
   yield resume(gThreadClient);
 
-  const sourcesResponse = yield getSources(gThreadClient);
+  const { sources } = yield getSources(gThreadClient);
   let sourceClient = gThreadClient.source(
-    sourcesResponse.sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
+    sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
   do_check_true(!sourceClient.isBlackBoxed,
                 "By default the source is not black boxed.");
 
   // Test that we can step into `doStuff` when we are not black boxed.
   yield runTest(
     function onSteppedLocation(aLocation) {
       do_check_eq(aLocation.source.url, BLACK_BOXED_URL);
       do_check_eq(aLocation.line, 2);
new file mode 100644
--- /dev/null
+++ b/toolkit/devtools/server/tests/unit/test_setBreakpoint-on-line-in-gcd-script.js
@@ -0,0 +1,57 @@
+"use strict";
+
+let SOURCE_URL = getFileUrl("setBreakpoint-on-line-in-gcd-script.js");
+
+function run_test() {
+  return Task.spawn(function* () {
+    do_test_pending();
+
+    let global = createTestGlobal("test");
+    loadSubScript(SOURCE_URL, global);
+    Cu.forceGC();
+
+    DebuggerServer.registerModule("xpcshell-test/testactors");
+    DebuggerServer.init(() => true);
+    DebuggerServer.addTestGlobal(global);
+    let client = new DebuggerClient(DebuggerServer.connectPipe());
+    yield connect(client);
+
+    let { tabs } = yield listTabs(client);
+    let tab = findTab(tabs, "test");
+    let [, tabClient] = yield attachTab(client, tab);
+    let [, threadClient] = yield attachThread(tabClient);
+    yield resume(threadClient);
+
+    let { sources } = yield getSources(threadClient);
+    let source = findSource(sources, SOURCE_URL);
+    let sourceClient = threadClient.source(source);
+
+    let location = { line: 7 };
+    let [packet, breakpointClient] = yield setBreakpoint(sourceClient, location);
+    do_check_true(packet.isPending);
+    do_check_false("actualLocation" in packet);
+
+    packet = yield executeOnNextTickAndWaitForPause(function () {
+      reload(tabClient).then(function () {
+        loadSubScript(SOURCE_URL, global);
+      });
+    }, client);
+    do_check_eq(packet.type, "paused");
+    let why = packet.why;
+    do_check_eq(why.type, "breakpoint");
+    do_check_eq(why.actors.length, 1);
+    do_check_eq(why.actors[0], breakpointClient.actor);
+    let frame = packet.frame;
+    let where = frame.where;
+    do_check_eq(where.source.actor, source.actor);
+    do_check_eq(where.line, location.line);
+    let variables = frame.environment.bindings.variables;
+    do_check_eq(variables.a.value, 1);
+    do_check_eq(variables.b.value.type, "undefined");
+    do_check_eq(variables.c.value.type, "undefined");
+    yield resume(threadClient);
+
+    yield close(client);
+    do_test_finished();
+  });
+}
--- a/toolkit/devtools/server/tests/unit/test_trace_actor-10.js
+++ b/toolkit/devtools/server/tests/unit/test_trace_actor-10.js
@@ -45,19 +45,19 @@ const testTraces = Task.async(function* 
     tracesStopped.resolve();
   });
 
   yield startTrace();
 
   evalSetup();
 
   // Blackbox source
-  const sourcesResponse = yield getSources(gThreadClient);
+  const { sources } = yield getSources(gThreadClient);
   let sourceClient = gThreadClient.source(
-    sourcesResponse.sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
+    sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
   do_check_true(!sourceClient.isBlackBoxed,
     "By default the source is not black boxed.");
   yield blackBox(sourceClient);
   do_check_true(sourceClient.isBlackBoxed);
 
   evalTestCode();
 
   yield tracesStopped.promise;
--- a/toolkit/devtools/server/tests/unit/xpcshell.ini
+++ b/toolkit/devtools/server/tests/unit/xpcshell.ini
@@ -12,16 +12,17 @@ support-files =
   pre_init_tab_actors.js
   registertestactors-01.js
   registertestactors-02.js
   registertestactors-03.js
   sourcemapped.js
   testactors.js
   tracerlocations.js
   hello-actor.js
+  setBreakpoint-on-line-in-gcd-script.js
 
 [test_ScriptStore.js]
 [test_actor-registry-actor.js]
 [test_nesting-01.js]
 [test_nesting-02.js]
 [test_nesting-03.js]
 [test_forwardingprefix.js]
 [test_getyoungestframe.js]
@@ -232,8 +233,9 @@ reason = bug 937197
 [test_get-executable-lines.js]
 [test_get-executable-lines-source-map.js]
 [test_xpcshell_debugging.js]
 support-files = xpcshell_debugging_script.js
 [test_memory_footprint.js]
 run-sequentially = measure memory, has to be run solo
 skip-if = os != 'linux' || debug || asan
 reason = bug 1014071
+[test_setBreakpoint-on-line-in-gcd-script.js]