Bug 1552453 - Breakpoint doesnt pause in file during page load. r=loganfsmyth
authorJason Laster <jlaster@mozilla.com>
Thu, 23 May 2019 12:52:34 +0000
changeset 475203 b0d23e155d8772321220306d07a3f192ded929cf
parent 475202 df8b61492199b1d31919104bb9dacde587d0883d
child 475204 963955816d383e7a277930c8ce58a08fefa7b26a
push id36057
push useraciure@mozilla.com
push dateThu, 23 May 2019 21:52:03 +0000
treeherdermozilla-central@d551d37b9ad0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersloganfsmyth
bugs1552453
milestone69.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 1552453 - Breakpoint doesnt pause in file during page load. r=loganfsmyth Differential Revision: https://phabricator.services.mozilla.com/D32161
devtools/server/actors/thread.js
devtools/server/tests/unit/test_breakpoint-23.js
devtools/server/tests/unit/xpcshell.ini
devtools/shared/client/thread-client.js
--- a/devtools/server/actors/thread.js
+++ b/devtools/server/actors/thread.js
@@ -1659,24 +1659,25 @@ const ThreadActor = ActorClassWithSpec(t
     // and so we also need to be sure that there is still a source actor for the source.
     let sourceActor;
     if (this._debuggerSourcesSeen.has(source) && this.sources.hasSourceActor(source)) {
       sourceActor = this.sources.getSourceActor(source);
     } else {
       sourceActor = this.sources.createSourceActor(source);
     }
 
-    if (this._onLoadBreakpointURLs.has(source.url)) {
-      this.setBreakpoint({ sourceUrl: source.url, line: 1 }, {});
+    const sourceUrl = sourceActor.url;
+    if (this._onLoadBreakpointURLs.has(sourceUrl)) {
+      this.setBreakpoint({ sourceUrl, line: 1 }, {});
     }
 
     const bpActors = this.breakpointActorMap.findActors()
-    .filter((actor) => {
-      return actor.location.sourceUrl && actor.location.sourceUrl == source.url;
-    });
+    .filter((actor) =>
+      actor.location.sourceUrl && actor.location.sourceUrl == sourceUrl
+    );
 
     for (const actor of bpActors) {
       sourceActor.applyBreakpoint(actor);
     }
 
     this._debuggerSourcesSeen.add(source);
     return true;
   },
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_breakpoint-23.js
@@ -0,0 +1,29 @@
+/* eslint-disable max-nested-callbacks */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Bug 1552453 - Verify that breakpoints are hit for evaluated
+ * scripts that contain a source url pragma.
+ */
+add_task(threadClientTest(async ({ threadClient, targetFront }) => {
+  await threadClient.setBreakpoint(
+    { sourceUrl: "http://example.com/code.js", line: 2, column: 1 },
+    {}
+  );
+
+  info("Create a new script with the displayUrl code.js");
+  const consoleFront = await targetFront.getFront("console");
+  consoleFront.evaluateJSAsync("function f() {\n return 5; \n}\n//# sourceURL=http://example.com/code.js");
+
+  const sourcePacket = await waitForEvent(threadClient, "newSource");
+  equal(sourcePacket.source.url, "http://example.com/code.js");
+
+  info("Evaluate f() and pause at line 2");
+  consoleFront.evaluateJSAsync("f()");
+  const pausedPacket = await waitForPause(threadClient);
+  equal(pausedPacket.why.type, "breakpoint");
+  equal(pausedPacket.frame.where.line, 2);
+}));
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -127,16 +127,17 @@ skip-if = true # tests for breakpoint ac
 [test_breakpoint-18.js]
 [test_breakpoint-19.js]
 skip-if = true
 reason = bug 1104838
 [test_breakpoint-20.js]
 [test_breakpoint-21.js]
 [test_breakpoint-22.js]
 skip-if = true # breakpoint sliding is not supported bug 1525685
+[test_breakpoint-23.js]
 [test_conditional_breakpoint-01.js]
 [test_conditional_breakpoint-02.js]
 [test_conditional_breakpoint-03.js]
 [test_logpoint-01.js]
 [test_logpoint-02.js]
 [test_listsources-01.js]
 [test_listsources-02.js]
 [test_listsources-03.js]
--- a/devtools/shared/client/thread-client.js
+++ b/devtools/shared/client/thread-client.js
@@ -1,21 +1,33 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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 {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
+const {
+  arg,
+  DebuggerClient,
+} = require("devtools/shared/client/debugger-client");
 const eventSource = require("devtools/shared/client/event-source");
-const {ThreadStateTypes} = require("devtools/shared/client/constants");
+const { ThreadStateTypes } = require("devtools/shared/client/constants");
 
-loader.lazyRequireGetter(this, "ObjectClient", "devtools/shared/client/object-client");
-loader.lazyRequireGetter(this, "SourceFront", "devtools/shared/fronts/source", true);
+loader.lazyRequireGetter(
+  this,
+  "ObjectClient",
+  "devtools/shared/client/object-client"
+);
+loader.lazyRequireGetter(
+  this,
+  "SourceFront",
+  "devtools/shared/fronts/source",
+  true
+);
 
 /**
  * Creates a thread client for the remote debugging protocol server. This client
  * is a front to the thread actor created in the server side, hiding the
  * protocol details in a traditional JavaScript API.
  *
  * @param client DebuggerClient
  * @param actor string
@@ -45,63 +57,68 @@ ThreadClient.prototype = {
   },
 
   get _transport() {
     return this.client._transport;
   },
 
   _assertPaused: function(command) {
     if (!this.paused) {
-      throw Error(command + " command sent while not paused. Currently " + this._state);
+      throw Error(
+        command + " command sent while not paused. Currently " + this._state
+      );
     }
   },
 
   /**
    * Resume a paused thread. If the optional limit parameter is present, then
    * the thread will also pause when that limit is reached.
    *
    * @param [optional] object limit
    *        An object with a type property set to the appropriate limit (next,
    *        step, or finish) per the remote debugging protocol specification.
    *        Use null to specify no limit.
    * @param bool aRewind
    *        Whether execution should rewind until the limit is reached, rather
    *        than proceeding forwards. This parameter has no effect if the
    *        server does not support rewinding.
    */
-  _doResume: DebuggerClient.requester({
-    type: "resume",
-    resumeLimit: arg(0),
-    rewind: arg(1),
-  }, {
-    before: function(packet) {
-      this._assertPaused("resume");
-
-      // Put the client in a tentative "resuming" state so we can prevent
-      // further requests that should only be sent in the paused state.
-      this._previousState = this._state;
-      this._state = "resuming";
-
-      return packet;
+  _doResume: DebuggerClient.requester(
+    {
+      type: "resume",
+      resumeLimit: arg(0),
+      rewind: arg(1),
     },
-    after: function(response) {
-      if (response.error && this._state == "resuming") {
-        // There was an error resuming, update the state to the new one
-        // reported by the server, if given (only on wrongState), otherwise
-        // reset back to the previous state.
-        if (response.state) {
-          this._state = ThreadStateTypes[response.state];
-        } else {
-          this._state = this._previousState;
+    {
+      before: function(packet) {
+        this._assertPaused("resume");
+
+        // Put the client in a tentative "resuming" state so we can prevent
+        // further requests that should only be sent in the paused state.
+        this._previousState = this._state;
+        this._state = "resuming";
+
+        return packet;
+      },
+      after: function(response) {
+        if (response.error && this._state == "resuming") {
+          // There was an error resuming, update the state to the new one
+          // reported by the server, if given (only on wrongState), otherwise
+          // reset back to the previous state.
+          if (response.state) {
+            this._state = ThreadStateTypes[response.state];
+          } else {
+            this._state = this._previousState;
+          }
         }
-      }
-      delete this._previousState;
-      return response;
-    },
-  }),
+        delete this._previousState;
+        return response;
+      },
+    }
+  ),
 
   /**
    * Reconfigure the thread actor.
    *
    * @param object options
    *        A dictionary object of the new options to use in the thread actor.
    */
   reconfigure: DebuggerClient.requester({
@@ -209,24 +226,27 @@ ThreadClient.prototype = {
     type: "pauseOnExceptions",
     pauseOnExceptions: arg(0),
     ignoreCaughtExceptions: arg(1),
   }),
 
   /**
    * Detach from the thread actor.
    */
-  detach: DebuggerClient.requester({
-    type: "detach",
-  }, {
-    after: function(response) {
-      this.client.unregisterClient(this);
-      return response;
+  detach: DebuggerClient.requester(
+    {
+      type: "detach",
     },
-  }),
+    {
+      after: function(response) {
+        this.client.unregisterClient(this);
+        return response;
+      },
+    }
+  ),
 
   /**
    * Promote multiple pause-lifetime object actors to thread-lifetime ones.
    *
    * @param array actors
    *        An array with actor IDs to promote.
    */
   threadGrips: DebuggerClient.requester({