diff --git a/devtools/server/actors/source.js b/devtools/server/actors/source.js index 1dee0a942e70..87575bd6d7b4 100644 --- a/devtools/server/actors/source.js +++ b/devtools/server/actors/source.js @@ -907,25 +907,48 @@ let SourceActor = ActorClassWithSpec(sourceSpec, { entryPoints.push({ script, offsets }); } } - } else { - // This is a column breakpoint, so we are interested in all column - // offsets that correspond to the given line *and* column number. + + if (entryPoints.length > 0) { + setBreakpointAtEntryPoints(actor, entryPoints); + return true; + } + + return false; + } + + // This is a column breakpoint, so we are interested in all column + // offsets that correspond to the given line *and* column number. + for (let script of scripts) { + let columnToOffsetMap = script.getAllColumnOffsets() + .filter(({ lineNumber }) => { + return lineNumber === generatedLine; + }); + for (let { columnNumber: column, offset } of columnToOffsetMap) { + if (column >= generatedColumn && column <= generatedLastColumn) { + entryPoints.push({ script, offsets: [offset] }); + } + } + } + + // If we don't find any matching entrypoints, then + // we should check to see if the breakpoint is to the left of the first offset. + if (entryPoints.length === 0) { for (let script of scripts) { - let columnToOffsetMap = script.getAllColumnOffsets() - .filter(({ lineNumber }) => { - return lineNumber === generatedLine; - }); - for (let { columnNumber: column, offset } of columnToOffsetMap) { - if (column >= generatedColumn && column <= generatedLastColumn) { + let columnToOffsetMap = script + .getAllColumnOffsets() + .filter(({ lineNumber }) => { + return lineNumber === generatedLine; + }); + + if (columnToOffsetMap.length > 0) { + let { columnNumber: column, offset } = columnToOffsetMap[0]; + if (generatedColumn < column) { entryPoints.push({ script, offsets: [offset] }); } } } } - if (entryPoints.length === 0) { - return false; - } setBreakpointAtEntryPoints(actor, entryPoints); return true; } diff --git a/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js b/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js new file mode 100644 index 000000000000..0f6e2a5239fb --- /dev/null +++ b/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js @@ -0,0 +1,64 @@ +"use strict"; + +var SOURCE_URL = getFileUrl("setBreakpoint-on-column.js"); + +function run_test() { + return Task.spawn(function* () { + do_test_pending(); + + DebuggerServer.registerModule("xpcshell-test/testactors"); + DebuggerServer.init(() => true); + + let global = createTestGlobal("test"); + 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 promise = waitForNewSource(threadClient, SOURCE_URL); + loadSubScript(SOURCE_URL, global); + let { source } = yield promise; + let sourceClient = threadClient.source(source); + + let location = { line: 4, column: 2 }; + let [packet, breakpointClient] = yield setBreakpoint( + sourceClient, + location + ); + + Assert.ok(!packet.isPending); + Assert.equal(false, "actualLocation" in packet); + + packet = yield executeOnNextTickAndWaitForPause(function () { + Cu.evalInSandbox("f()", global); + }, client); + + Assert.equal(packet.type, "paused"); + let why = packet.why; + Assert.equal(why.type, "breakpoint"); + Assert.equal(why.actors.length, 1); + Assert.equal(why.actors[0], breakpointClient.actor); + + let frame = packet.frame; + let where = frame.where; + Assert.equal(where.source.actor, source.actor); + Assert.equal(where.line, location.line); + Assert.equal(where.column, 6); + + let 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"); + + yield resume(threadClient); + yield close(client); + + do_test_finished(); + }); +} diff --git a/devtools/server/tests/unit/xpcshell.ini b/devtools/server/tests/unit/xpcshell.ini index 4e1e6e84044a..6f84ce913715 100644 --- a/devtools/server/tests/unit/xpcshell.ini +++ b/devtools/server/tests/unit/xpcshell.ini @@ -222,6 +222,7 @@ reason = bug 937197 [test_get-executable-lines-source-map.js] [test_xpcshell_debugging.js] support-files = xpcshell_debugging_script.js +[test_setBreakpoint-at-the-beginning-of-a-line.js] [test_setBreakpoint-on-column.js] [test_setBreakpoint-on-column-in-gcd-script.js] [test_setBreakpoint-on-column-with-no-offsets-at-end-of-line.js]