Bug 1545103 - applyBreakpoint should no longer support fuzzy matches.
authorJason Laster <jlaster@mozilla.com>
Fri, 19 Apr 2019 16:07:24 +0000
changeset 470212 30b70a449280e6df10496a51e89c01b8c98bb92e
parent 470211 9e242ede9b1c647366d60fc2bad3b2c78539c31e
child 470213 b330e84e1458ac4e11343638f622329a48bb952b
child 470221 4ab859fec944584152eaf9771c21406e342fc7c8
push id112847
push userdluca@mozilla.com
push dateFri, 19 Apr 2019 21:51:54 +0000
treeherdermozilla-inbound@b330e84e1458 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1545103
milestone68.0a1
first release with
nightly linux32
30b70a449280 / 68.0a1 / 20190419214439 / files
nightly linux64
30b70a449280 / 68.0a1 / 20190419214439 / files
nightly mac
30b70a449280 / 68.0a1 / 20190419214439 / files
nightly win32
30b70a449280 / 68.0a1 / 20190419214439 / files
nightly win64
30b70a449280 / 68.0a1 / 20190419214439 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1545103 - applyBreakpoint should no longer support fuzzy matches. Differential Revision: https://phabricator.services.mozilla.com/D28203
devtools/server/actors/source.js
devtools/server/actors/utils/closest-scripts.js
devtools/server/actors/utils/moz.build
devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js
devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-minified-fn.js
devtools/server/tests/unit/test_setBreakpoint-at-the-end-of-a-line.js
devtools/server/tests/unit/xpcshell.ini
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -9,17 +9,16 @@
 const { Ci } = require("chrome");
 const { setBreakpointAtEntryPoints } = require("devtools/server/actors/breakpoint");
 const { createValueGrip } = require("devtools/server/actors/object/utils");
 const { ActorClassWithSpec } = require("devtools/shared/protocol");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const { assert, fetch } = DevToolsUtils;
 const { joinURI } = require("devtools/shared/path");
 const { sourceSpec } = require("devtools/shared/specs/source");
-const { findClosestScriptBySource } = require("devtools/server/actors/utils/closest-scripts");
 
 loader.lazyRequireGetter(this, "arrayBufferGrip", "devtools/server/actors/array-buffer", true);
 
 function isEvalSource(source) {
   const introType = source.introductionType;
 
   // Script elements that are dynamically created are treated as eval sources.
   // We detect these by looking at whether there was another script on the stack
@@ -428,24 +427,24 @@ const SourceActor = ActorClassWithSpec(s
    * @param BreakpointActor actor
    *        The BreakpointActor to be set as a breakpoint handler.
    *
    * @returns A Promise that resolves to the given BreakpointActor.
    */
   applyBreakpoint: function(actor) {
     const { line, column } = actor.location;
 
-    // Find all scripts that match the given source actor and line
-    // number.
-    let scripts = this._findDebuggeeScripts({ line });
-    scripts = scripts.filter((script) => !actor.hasScript(script));
-
     // Find all entry points that correspond to the given location.
     const entryPoints = [];
     if (column === undefined) {
+      // Find all scripts that match the given source actor and line
+      // number.
+      const scripts = this._findDebuggeeScripts({ line })
+        .filter((script) => !actor.hasScript(script));
+
       // This is a line breakpoint, so we add a breakpoint on the first
       // breakpoint on the line.
       const lineMatches = [];
       for (const script of scripts) {
         const possibleBreakpoints = script.getPossibleBreakpoints({ line });
         for (const possibleBreakpoint of possibleBreakpoints) {
           lineMatches.push({ ...possibleBreakpoint, script });
         }
@@ -461,64 +460,33 @@ const SourceActor = ActorClassWithSpec(s
         const firstColumnMatches = lineMatches
           .filter(m => m.columnNumber === firstColumn);
 
         for (const { script, offset } of firstColumnMatches) {
           entryPoints.push({ script, offsets: [offset] });
         }
       }
     } else {
-      // Compute columnToOffsetMaps for each script so that we can
-      // find matching entrypoints for the column breakpoint.
-      const columnToOffsetMaps = scripts.map(script =>
-        [
-          script,
-          script.getPossibleBreakpoints({ line }),
-        ]
-      );
-
-      // This is a column breakpoint, so we are interested in all column
-      // offsets that correspond to the given line *and* column number.
-      for (const [script, columnToOffsetMap] of columnToOffsetMaps) {
-        for (const { columnNumber, offset } of columnToOffsetMap) {
-          if (columnNumber >= column && columnNumber <= column + 1) {
-            entryPoints.push({ script, offsets: [offset] });
-          }
-        }
-      }
+      // Find all scripts that match the given source actor, line,
+      // and column number.
+      const scripts = this._findDebuggeeScripts({ line, column })
+        .filter((script) => !actor.hasScript(script));
 
-      // If we don't find any matching entrypoints,
-      // then we should see if the breakpoint comes before or after the column offsets.
-      if (entryPoints.length === 0) {
-        // It's not entirely clear if the scripts that make it here can come
-        // from a variety of sources. This function allows filtering by URL
-        // so it seems like it may be possible and we are erring on the side
-        // of caution by handling it here.
-        const closestScripts = findClosestScriptBySource(
-          columnToOffsetMaps.map(pair => pair[0]),
+      for (const script of scripts) {
+        // Check to see if the script contains a breakpoint position at
+        // this line and column.
+        const possibleBreakpoint = script.getPossibleBreakpoints({
           line,
-          column,
-        );
+          minColumn: column,
+          maxColumn: column + 1,
+        }).pop();
 
-        const columnToOffsetLookup = new Map(columnToOffsetMaps);
-        for (const script of closestScripts) {
-          const columnToOffsetMap = columnToOffsetLookup.get(script);
-
-          if (columnToOffsetMap.length > 0) {
-            const firstColumnOffset = columnToOffsetMap[0];
-            const lastColumnOffset = columnToOffsetMap[columnToOffsetMap.length - 1];
-
-            if (column < firstColumnOffset.columnNumber) {
-              entryPoints.push({ script, offsets: [firstColumnOffset.offset] });
-            }
-
-            if (column > lastColumnOffset.columnNumber) {
-              entryPoints.push({ script, offsets: [lastColumnOffset.offset] });
-            }
-          }
+        if (possibleBreakpoint) {
+          const { offset } = possibleBreakpoint;
+          entryPoints.push({ script, offsets: [offset] });
         }
       }
     }
 
     setBreakpointAtEntryPoints(actor, entryPoints);
   },
 });
 
deleted file mode 100644
--- a/devtools/server/actors/utils/closest-scripts.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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 { findSourceOffset } = require("devtools/server/actors/utils/dbg-source");
-
-function findClosestScriptBySource(scripts, generatedLine, generatedColumn) {
-  const bySource = new Map();
-  for (const script of scripts) {
-    const { source } = script;
-    if (script.format !== "js" || !source) {
-      continue;
-    }
-
-    let sourceScripts = bySource.get(source);
-    if (!sourceScripts) {
-      sourceScripts = [];
-      bySource.set(source, sourceScripts);
-    }
-
-    sourceScripts.push(script);
-  }
-
-  const closestScripts = [];
-  for (const sourceScripts of bySource.values()) {
-    const closest = findClosestScript(sourceScripts, generatedLine, generatedColumn);
-    if (closest) {
-      closestScripts.push(closest);
-    }
-  }
-  return closestScripts;
-}
-exports.findClosestScriptBySource = findClosestScriptBySource;
-
-function findClosestScript(scripts, generatedLine, generatedColumn) {
-  if (scripts.length === 0) {
-    return null;
-  }
-  const { source } = scripts[0];
-
-  const offset = findSourceOffset(
-    source,
-    generatedLine,
-    generatedColumn,
-  );
-
-  let closest = null;
-  for (const script of scripts) {
-    if (script.source !== source) {
-      throw new Error("All scripts must be from a single source.");
-    }
-
-    if (
-      offset >= script.sourceStart &&
-      offset < script.sourceStart + script.sourceLength &&
-      (!closest || script.sourceLength < closest.sourceLength)
-    ) {
-      closest = script;
-    }
-  }
-
-  return closest;
-}
--- a/devtools/server/actors/utils/moz.build
+++ b/devtools/server/actors/utils/moz.build
@@ -4,17 +4,16 @@
 # 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/.
 
 DevToolsModules(
     'accessibility.js',
     'actor-registry-utils.js',
     'actor-registry.js',
     'breakpoint-actor-map.js',
-    'closest-scripts.js',
     'css-grid-utils.js',
     'dbg-source.js',
     'event-breakpoints.js',
     'event-loop.js',
     'make-debugger.js',
     'shapes-utils.js',
     'stack.js',
     'TabSources.js',
deleted file mode 100644
--- a/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js
+++ /dev/null
@@ -1,33 +0,0 @@
-"use strict";
-
-const SOURCE_URL = getFileUrl("setBreakpoint-on-column.js");
-
-add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
-  const promise = waitForNewSource(threadClient, SOURCE_URL);
-  loadSubScript(SOURCE_URL, debuggee);
-  const { source } = await promise;
-
-  const location = { sourceUrl: source.url, line: 4, column: 2 };
-  setBreakpoint(threadClient, location);
-
-  const packet = await executeOnNextTickAndWaitForPause(function() {
-    Cu.evalInSandbox("f()", debuggee);
-  }, client);
-
-  Assert.equal(packet.type, "paused");
-  const why = packet.why;
-  Assert.equal(why.type, "breakpoint");
-  Assert.equal(why.actors.length, 1);
-
-  const frame = packet.frame;
-  Assert.equal(frame.where.actor, source.actor);
-  Assert.equal(frame.where.line, location.line);
-  Assert.equal(frame.where.column, 10);
-
-  const variables = frame.environment.bindings.variables;
-  Assert.equal(variables.a.value.type, "undefined");
-  Assert.equal(variables.b.value.type, "undefined");
-  Assert.equal(variables.c.value.type, "undefined");
-
-  await resume(threadClient);
-}, { doNotRunWorker: true }));
--- a/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-minified-fn.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-minified-fn.js
@@ -4,17 +4,17 @@ const SOURCE_URL = getFileUrl("setBreakp
 
 add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
   const promise = waitForNewSource(threadClient, SOURCE_URL);
   loadSubScript(SOURCE_URL, debuggee);
   const { source } = await promise;
 
   // Pause inside of the nested function so we can make sure that we don't
   // add any other breakpoints at other places on this line.
-  const location = { sourceUrl: source.url, line: 3, column: 47 };
+  const location = { sourceUrl: source.url, line: 3, column: 56 };
   setBreakpoint(threadClient, location);
 
   const packet = await executeOnNextTickAndWaitForPause(function() {
     Cu.evalInSandbox("f()", debuggee);
   }, client);
 
   Assert.equal(packet.type, "paused");
   const why = packet.why;
deleted file mode 100644
--- a/devtools/server/tests/unit/test_setBreakpoint-at-the-end-of-a-line.js
+++ /dev/null
@@ -1,34 +0,0 @@
-"use strict";
-
-const SOURCE_URL = getFileUrl("setBreakpoint-on-column.js");
-
-add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
-  const promise = waitForNewSource(threadClient, SOURCE_URL);
-  loadSubScript(SOURCE_URL, debuggee);
-  const { source } = await promise;
-
-  const location = { sourceUrl: source.url, line: 4, column: 42 };
-  setBreakpoint(threadClient, location);
-
-  const packet = await executeOnNextTickAndWaitForPause(function() {
-    Cu.evalInSandbox("f()", debuggee);
-  }, client);
-
-  Assert.equal(packet.type, "paused");
-  const why = packet.why;
-  Assert.equal(why.type, "breakpoint");
-  Assert.equal(why.actors.length, 1);
-
-  const frame = packet.frame;
-  const where = frame.where;
-  Assert.equal(where.actor, source.actor);
-  Assert.equal(where.line, location.line);
-  Assert.equal(where.column, 32);
-
-  const variables = frame.environment.bindings.variables;
-  Assert.equal(variables.a.value, 1);
-  Assert.equal(variables.b.value, 2);
-  Assert.equal(variables.c.value.type, "undefined");
-
-  await resume(threadClient);
-}, { doNotRunWorker: true }));
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -215,19 +215,17 @@ reason = bug 937197
 [test_protocolSpec.js]
 [test_registerClient.js]
 [test_client_request.js]
 [test_symbols-01.js]
 [test_symbols-02.js]
 [test_get-executable-lines.js]
 [test_xpcshell_debugging.js]
 support-files = xpcshell_debugging_script.js
-[test_setBreakpoint-at-the-beginning-of-a-line.js]
 [test_setBreakpoint-at-the-beginning-of-a-minified-fn.js]
-[test_setBreakpoint-at-the-end-of-a-line.js]
 [test_setBreakpoint-at-the-end-of-a-minified-fn.js]
 [test_setBreakpoint-on-column.js]
 [test_setBreakpoint-on-column-in-gcd-script.js]
 [test_setBreakpoint-on-line.js]
 [test_setBreakpoint-on-line-in-gcd-script.js]
 [test_setBreakpoint-on-line-with-multiple-offsets.js]
 [test_setBreakpoint-on-line-with-multiple-statements.js]
 [test_setBreakpoint-on-line-with-no-offsets.js]