Bug 1447316 - The debugger should use pausePoints to decide where to stop. r=jimb

MozReview-Commit-ID: 4Sxz0VIKB3j
This commit is contained in:
Jason Laster 2018-03-19 13:51:51 -04:00
Родитель e561bf58c4
Коммит 2fef0dedc3
6 изменённых файлов: 157 добавлений и 6 удалений

Просмотреть файл

@ -661,6 +661,21 @@ let SourceActor = ActorClassWithSpec(sourceSpec, {
this.threadActor.sources.unblackBox(this.url);
},
/**
* Handler for the "setPausePoints" packet.
*
* @param Array pausePoints
* A list of pausePoint objects
*
* type PausePoint = {
* location: { line: number, column: number }
* types: { breakpoint: boolean, stepOver: boolean }
* }
*/
setPausePoints: function(pausePoints) {
this.pausePoints = pausePoints;
},
/**
* Handle a request to set a breakpoint.
*

Просмотреть файл

@ -497,7 +497,8 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
// 1.1. We change frames.
// 1.2. We change URLs (can happen without changing frames thanks to
// source mapping).
// 1.3. We change lines.
// 1.3. The source has pause points and we change locations.
// 1.4 The source does not have pause points and We change lines.
//
// Cases when we should always continue execution, even if one of the
// above cases is true:
@ -512,10 +513,33 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return undefined;
}
// Cases 1.1, 1.2 and 1.3
if (this !== startFrame
|| startLocation.originalUrl !== newLocation.originalUrl
|| startLocation.originalLine !== newLocation.originalLine) {
// Cases 1.1, 1.2
if (this !== startFrame || startLocation.originalUrl !== newLocation.originalUrl) {
return pauseAndRespond(this);
}
const pausePoints = newLocation.originalSourceActor.pausePoints;
if (!pausePoints) {
// Case 1.4
if (startLocation.originalLine !== newLocation.originalLine) {
return pauseAndRespond(this);
}
return undefined;
}
// Case 1.3
if (
startLocation.originalLine === newLocation.originalLine
&& startLocation.originalColumn === newLocation.originalColumn
) {
return undefined;
}
// When pause points are specified for the source,
// we should pause when we are at a stepOver pause point
const pausePoint = findPausePointForLocation(pausePoints, newLocation);
if (pausePoint && pausePoint.types.stepOver) {
return pauseAndRespond(this);
}
@ -1888,6 +1912,13 @@ function findEntryPointsForLine(scripts, line) {
return entryPoints;
}
function findPausePointForLocation(pausePoints, location) {
return pausePoints.find(pausePoint =>
pausePoint.location.line === location.originalLine
&& pausePoint.location.column === location.originalColumn
);
}
/**
* Unwrap a global that is wrapped in a |Debugger.Object|, or if the global has
* become a dead object, return |undefined|.

Просмотреть файл

@ -0,0 +1,90 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-disable no-shadow, max-nested-callbacks */
"use strict";
/**
* Check basic step-over functionality with pause points
* for the first statement and end of the last statement.
*/
var gDebuggee;
var gClient;
var gCallback;
function run_test() {
do_test_pending();
run_test_with_server(DebuggerServer, function() {
run_test_with_server(WorkerDebuggerServer, do_test_finished);
});
}
function run_test_with_server(server, callback) {
gCallback = callback;
initTestDebuggerServer(server);
gDebuggee = addTestGlobal("test-stepping", server);
gClient = new DebuggerClient(server.connectPipe());
gClient.connect(test_simple_stepping);
}
async function test_simple_stepping() {
const [attachResponse,, threadClient] = await attachTestTabAndResume(gClient,
"test-stepping");
ok(!attachResponse.error, "Should not get an error attaching");
dumpn("Evaluating test code and waiting for first debugger statement");
const dbgStmt = await executeOnNextTickAndWaitForPause(evaluateTestCode, gClient);
equal(dbgStmt.frame.where.line, 2, "Should be at debugger statement on line 2");
equal(gDebuggee.a, undefined);
equal(gDebuggee.b, undefined);
const source = await getSource(threadClient, "test_stepping-01-test-code.js");
// Add pause points for the first and end of the last statement.
// Note: we intentionally ignore the second statement.
source.setPausePoints([{
location: {line: 3, column: 8},
types: {breakpoint: true, stepOver: true}
},
{
location: {line: 4, column: 14},
types: {breakpoint: true, stepOver: true}
}]);
dumpn("Step Over to line 3");
const step1 = await stepOver(gClient, threadClient);
equal(step1.type, "paused");
equal(step1.why.type, "resumeLimit");
equal(step1.frame.where.line, 3);
equal(step1.frame.where.column, 8);
equal(gDebuggee.a, undefined);
equal(gDebuggee.b, undefined);
dumpn("Step Over to the end of line 4");
const step4 = await stepOver(gClient, threadClient);
equal(step4.type, "paused");
equal(step4.why.type, "resumeLimit");
equal(step4.frame.where.line, 4);
equal(step4.frame.where.column, 14);
equal(gDebuggee.a, 1);
equal(gDebuggee.b, 2);
finishClient(gClient, gCallback);
}
function evaluateTestCode() {
/* eslint-disable */
Cu.evalInSandbox(
` // 1
debugger; // 2
var a = 1; // 3
var b = 2;`, // 4
gDebuggee,
"1.8",
"test_stepping-01-test-code.js",
1
);
/* eslint-disable */
}

Просмотреть файл

@ -190,6 +190,7 @@ reason = only ran on B2G
[test_stepping-06.js]
[test_stepping-07.js]
[test_stepping-08.js]
[test_stepping-with-pause-points.js]
[test_framebindings-01.js]
[test_framebindings-02.js]
[test_framebindings-03.js]

Просмотреть файл

@ -276,7 +276,16 @@ SourceClient.prototype = {
return doSetBreakpoint(cleanUp);
});
}
},
setPausePoints: function(pausePoints) {
const packet = {
to: this._form.actor,
type: "setPausePoints",
pausePoints
};
return this._client.request(packet);
},
};
module.exports = SourceClient;

Просмотреть файл

@ -21,6 +21,11 @@ const sourceSpec = generateActorSpec({
disablePrettyPrint: {
response: RetVal("json")
},
setPausePoints: {
request: {
pausePoints: Arg(0, "json"),
}
},
blackbox: { response: { pausedInSource: RetVal("boolean") } },
unblackbox: {},
setBreakpoint: {