Bug 1518661 - Part 7: Update debugger server to use new getPossibleBreakpoints APIs. r=jlast

Making use of the new SpiderMonkey APIs for available breakpoints means
that the server needs to think a lot less about where it is pausing and
allows us to drop the concept of a pause points from the server entirely.
It is now up to SpiderMonkey to decide where it will and will not stop
when it is stepping.

Differential Revision: https://phabricator.services.mozilla.com/D17665

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Logan Smyth 2019-02-13 02:31:03 +00:00
parent b78439c9df
commit 241f292283
27 changed files with 139 additions and 226 deletions

View File

@ -14,19 +14,6 @@ import { getGeneratedLocation } from "../../utils/source-maps";
import type { SourceId } from "../../types";
import type { ThunkArgs, Action } from "../types";
function compressPausePoints(pausePoints) {
const compressed = {};
for (const line in pausePoints) {
compressed[line] = {};
for (const col in pausePoints[line]) {
const { types } = pausePoints[line][col];
compressed[line][col] = (types.break ? 1 : 0) | (types.step ? 2 : 0);
}
}
return compressed;
}
async function mapLocations(pausePoints, state, source, sourceMaps) {
const pausePointList = convertToList(pausePoints);
const sourceId = source.id;
@ -58,17 +45,8 @@ export function setPausePoints(sourceId: SourceId) {
return;
}
let pausePoints = await parser.getPausePoints(sourceId);
if (isGenerated(source)) {
const compressed = compressPausePoints(pausePoints);
for (const sourceActor of getSourceActors(getState(), sourceId)) {
await client.setPausePoints(sourceActor, compressed);
}
}
pausePoints = await mapLocations(
pausePoints,
const pausePoints = await mapLocations(
await parser.getPausePoints(sourceId),
getState(),
source,
sourceMaps

View File

@ -28,7 +28,6 @@ add_task(async function() {
await selectSource(dbg, "simple1");
await waitForSelectedSource(dbg, "simple1");
await addBreakpoint(dbg, "simple1", 1);
await addBreakpoint(dbg, "simple1", 4);
await addBreakpoint(dbg, "simple1", 5);
await addBreakpoint(dbg, "simple1", 6);
@ -40,14 +39,14 @@ add_task(async function() {
// which promises get resolved. The problem seems to indicate a coverage gap
// in waitUntilService(). Workaround this by only waiting for one dispatch,
// though this is fragile and could break again in the future.
let dispatched = waitForDispatch(dbg, "DISABLE_BREAKPOINT", /*3*/ 1);
let dispatched = waitForDispatch(dbg, "DISABLE_BREAKPOINT", /*2*/ 1);
selectContextMenuItem(dbg, selectors.breakpointContextMenu.disableOthers);
await waitForState(dbg, state =>
dbg.selectors.getBreakpointsList(state)
.every(bp => (bp.location.line !== 1) === bp.disabled)
.every(bp => (bp.location.line !== 4) === bp.disabled)
);
await dispatched;
ok("breakpoint at 1 is the only enabled breakpoint");
ok("breakpoint at 4 is the only enabled breakpoint");
openFirstBreakpointContextMenu(dbg);
// select "Disable All"
@ -61,23 +60,23 @@ add_task(async function() {
openFirstBreakpointContextMenu(dbg);
// select "Enable Others"
dispatched = waitForDispatch(dbg, "ENABLE_BREAKPOINT", 3);
dispatched = waitForDispatch(dbg, "ENABLE_BREAKPOINT", 2);
selectContextMenuItem(dbg, selectors.breakpointContextMenu.enableOthers);
await waitForState(dbg, state =>
dbg.selectors.getBreakpointsList(state)
.every(bp => (bp.location.line === 1) === bp.disabled)
.every(bp => (bp.location.line === 4) === bp.disabled)
);
await dispatched;
ok("all breakpoints except line 1 are enabled");
openFirstBreakpointContextMenu(dbg);
// select "Remove Others"
dispatched = waitForDispatch(dbg, "REMOVE_BREAKPOINT", 3);
dispatched = waitForDispatch(dbg, "REMOVE_BREAKPOINT", 2);
selectContextMenuItem(dbg, selectors.breakpointContextMenu.removeOthers);
await waitForState(dbg, state =>
dbg.selectors.getBreakpointsList(state).length === 1 &&
dbg.selectors.getBreakpointsList(state)[0].location.line === 1
dbg.selectors.getBreakpointsList(state)[0].location.line === 4
);
await dispatched;
ok("remaining breakpoint should be on line 1");
ok("remaining breakpoint should be on line 4");
});

View File

@ -36,6 +36,9 @@ add_task(async function() {
await pressResume(dbg);
assertPausedLocation(dbg);
await pressStepOver(dbg);
assertPausedLocation(dbg);
await pressStepIn(dbg);
assertPausedLocation(dbg);

View File

@ -33,28 +33,17 @@ add_task(async function test() {
await selectSource(dbg, "pause-points.js")
await testCase(dbg, {
name: "statements",
steps: [
[9, 2],
[10, 4],
[10, 13],
[11, 2],
[11, 10],
[11, 21],
[11, 29],
[12, 2],
[12, 12],
[13, 0]
]
steps: [[9,2], [10,4], [10,13], [11,2], [11,21], [12,2], [12,12], [13,0]]
});
await testCase(dbg, {
name: "expressions",
steps: [[40,2], [41,2], [41,8], [42,12], [43,0]]
steps: [[40,2], [41,2], [42,12], [43,0]]
});
await testCase(dbg, {
name: "sequences",
steps: [[23,2], [25,12], [31,4], [34,2], [37,0]]
steps: [[23,2], [25,12], [29,12], [34,2], [37,0]]
});
await testCase(dbg, {
@ -62,15 +51,11 @@ add_task(async function test() {
steps: [
[16, 2],
[17, 12],
[17, 20],
[18, 10],
[19, 2],
[19, 8],
[19, 17],
[19, 25],
[19, 8],
[19, 17],
[19, 25],
[19, 8]
]
});

View File

@ -57,6 +57,7 @@ function testStepOverForOf(dbg) {
{ line: 4, column: 2 },
[
["stepOver", { line: 6, column: 20 }],
["stepOver", { line: 6, column: 2 }],
["stepOver", { line: 7, column: 4 }],
["stepOver", { line: 6, column: 2 }],
["stepOver", { line: 7, column: 4 }],
@ -76,10 +77,10 @@ function testStepOverForOfArray(dbg) {
{ line: 3, column: 2 },
[
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 13 }],
["stepOver", { line: 6, column: 4 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 13 }],
["stepOver", { line: 6, column: 4 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 9, column: 2 }]
@ -114,9 +115,9 @@ function testStepOverForOfArrayClosure(dbg) {
{ line: 3, column: 2 },
[
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 13 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 5, column: 7 }],
["stepOver", { line: 5, column: 13 }],
["stepOver", { line: 5, column: 2 }],
["stepOver", { line: 9, column: 2 }]
]

View File

@ -81,7 +81,6 @@ add_task(async function() {
await waitForPaused(dbg);
assertPausedLocation(dbg);
await stepIn(dbg);
await stepIn(dbg);
assertPausedLocation(dbg);

View File

@ -24,6 +24,6 @@ add_task(async function test() {
await stepIn(dbg);
await stepIn(dbg);
assertDebugLine(dbg, 42267);
assertDebugLine(dbg, 42271);
assertPausedLocation(dbg);
});

View File

@ -28,12 +28,10 @@ add_task(async function() {
await reverseStepOverToLine(client, 21);
await checkEvaluateInTopFrame(client, "number", 9);
await stepOverToLine(client, 21);
await stepOverToLine(client, 22);
await stepOverToLine(client, 23);
await stepOverToLine(client, 13);
await stepOverToLine(client, 17);
await stepOverToLine(client, 17);
await stepOverToLine(client, 18);
// After forward-stepping out of the topmost frame we should run forward to

View File

@ -737,6 +737,13 @@ ReplayDebuggerScript.prototype = {
getSuccessorOffsets(pc) { return this._forward("getSuccessorOffsets", pc); },
getPredecessorOffsets(pc) { return this._forward("getPredecessorOffsets", pc); },
getAllColumnOffsets() { return this._forward("getAllColumnOffsets"); },
getOffsetMetadata(pc) { return this._forward("getOffsetMetadata", pc); },
getPossibleBreakpoints(query) {
return this._forward("getPossibleBreakpoints", query);
},
getPossibleBreakpointOffsets(query) {
return this._forward("getPossibleBreakpointOffsets", query);
},
setBreakpoint(offset, handler) {
this._dbg._setBreakpoint(() => { handler.hit(this._dbg.getNewestFrame()); },

View File

@ -783,6 +783,9 @@ const gRequestHandlers = {
getSuccessorOffsets: forwardToScript("getSuccessorOffsets"),
getPredecessorOffsets: forwardToScript("getPredecessorOffsets"),
getAllColumnOffsets: forwardToScript("getAllColumnOffsets"),
getOffsetMetadata: forwardToScript("getOffsetMetadata"),
getPossibleBreakpoints: forwardToScript("getPossibleBreakpoints"),
getPossibleBreakpointOffsets: forwardToScript("getPossibleBreakpointOffsets"),
frameEvaluate(request) {
if (!RecordReplayControl.maybeDivergeFromRecording()) {

View File

@ -268,7 +268,7 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
getExecutableLines: async function() {
const offsetsLines = new Set();
for (const s of this._findDebuggeeScripts()) {
for (const offset of s.getAllColumnOffsets()) {
for (const offset of s.getPossibleBreakpoints()) {
offsetsLines.add(offset.lineNumber);
}
}
@ -307,7 +307,7 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
const positions = [];
for (const script of scripts) {
const offsets = script.getAllColumnOffsets();
const offsets = script.getPossibleBreakpoints();
for (const { lineNumber, columnNumber } of offsets) {
if (
lineNumber < startLine ||
@ -330,13 +330,7 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
.sort((a, b) => {
const lineDiff = a.line - b.line;
return lineDiff === 0 ? a.column - b.column : lineDiff;
})
// Filter out duplicate locations since they are useless in this context.
.filter((item, i, arr) => (
i === 0 ||
item.line !== arr[i - 1].line ||
item.column !== arr[i - 1].column
));
});
},
getBreakpointPositionsCompressed(query) {
@ -449,12 +443,13 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
// Find all entry points that correspond to the given location.
const entryPoints = [];
if (column === undefined) {
// This is a line breakpoint, so we are interested in all offsets
// that correspond to the given line number.
// This is a line breakpoint, so we add a breakpoint on the first
// breakpoint on the line.
for (const script of scripts) {
const offsets = script.getLineOffsets(line);
const offsets = script.getPossibleBreakpointOffsets({ line });
if (offsets.length > 0) {
entryPoints.push({ script, offsets });
entryPoints.push({ script, offsets: [offsets[0]] });
break;
}
}
} else {
@ -463,8 +458,7 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
const columnToOffsetMaps = scripts.map(script =>
[
script,
script.getAllColumnOffsets()
.filter(({ lineNumber }) => lineNumber === line),
script.getPossibleBreakpoints({ line }),
]
);

View File

@ -607,51 +607,37 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
// "step" from another location.
_intraFrameLocationIsStepTarget: function(startLocation, script, offset) {
// Only allow stepping stops at entry points for the line.
if (!script.getOffsetLocation(offset).isEntryPoint) {
if (!script.getOffsetMetadata(offset).isBreakpoint) {
return false;
}
// Cases when we have executed enough within a frame to consider a "step"
// to have occured:
//
// 1. We change URLs (can happen without changing frames thanks to
// source mapping).
// 2. The source has pause points and we change locations.
// 3. The source does not have pause points and we change lines.
const generatedLocation = this.sources.getScriptOffsetLocation(script, offset);
// Case 1.
if (startLocation.generatedUrl !== generatedLocation.generatedUrl) {
return true;
}
const pausePoints = generatedLocation.generatedSourceActor.pausePoints;
// TODO(logan): When we remove points points, this can be removed too as
// we assert that we're at a different frame offset from the last time
// we paused.
const lineChanged = startLocation.generatedLine !== generatedLocation.generatedLine;
const columnChanged =
startLocation.generatedColumn !== generatedLocation.generatedColumn;
if (!pausePoints) {
// Case 3.
return lineChanged;
}
// Case 2.
if (!lineChanged && !columnChanged) {
return false;
}
// When pause points are specified for the source,
// we should pause when we are at a stepOver pause point
const pausePoint = findPausePointForLocation(pausePoints, generatedLocation);
const pausePoints = generatedLocation.generatedSourceActor.pausePoints;
const pausePoint = pausePoints &&
findPausePointForLocation(pausePoints, generatedLocation);
if (pausePoint) {
return pausePoint.step;
}
// NOTE: if we do not find a pause point we want to
// fall back on the old behavior (Case 3)
return lineChanged;
return script.getOffsetMetadata(offset).isStepStart;
},
_makeOnStep: function({ thread, pauseAndRespond, startFrame,

View File

@ -273,7 +273,7 @@ TabSources.prototype = {
* Returns an object of the form { source, line, column }
*/
getScriptOffsetLocation: function(script, offset) {
const {lineNumber, columnNumber} = script.getOffsetLocation(offset);
const {lineNumber, columnNumber} = script.getOffsetMetadata(offset);
return new GeneratedLocation(
this.createSourceActor(script.source),
lineNumber,

View File

@ -16,7 +16,11 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { sourceUrl: source.url, line: debuggee.line0 + 3 };
const location = {
sourceUrl: source.url,
line: debuggee.line0 + 3,
column: 5,
};
threadClient.setBreakpoint(location, {});
@ -27,6 +31,16 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
// Check that the breakpoint worked.
Assert.equal(debuggee.i, 0);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
const location2 = {
sourceUrl: source.url,
line: debuggee.line0 + 3,
column: 12,
};
threadClient.setBreakpoint(location2, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
@ -35,7 +49,7 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
Assert.equal(debuggee.i, 1);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
threadClient.removeBreakpoint(location2);
threadClient.resume(resolve);
});

View File

@ -16,7 +16,11 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
threadClient,
packet.frame.where.actor
);
const location = { sourceUrl: source.url, line: debuggee.line0 + 2 };
const location = {
sourceUrl: source.url,
line: debuggee.line0 + 2,
column: 8,
};
threadClient.setBreakpoint(location, {});
@ -27,6 +31,17 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
// Check that the breakpoint worked.
Assert.equal(debuggee.a, undefined);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
const location2 = {
sourceUrl: source.url,
line: debuggee.line0 + 2,
column: 32,
};
threadClient.setBreakpoint(location2, {});
threadClient.addOneTimeListener("paused", function(event, packet) {
// Check the return value.
Assert.equal(packet.type, "paused");
@ -36,7 +51,7 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
Assert.equal(debuggee.res, undefined);
// Remove the breakpoint.
threadClient.removeBreakpoint(location);
threadClient.removeBreakpoint(location2);
threadClient.resume(resolve);
});

View File

@ -32,12 +32,6 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// At the end of the foo function call frame.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.notEqual(packet.why.type, "breakpoint");
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// Check that the breakpoint wasn't the reason for this pause, but
// that the frame is about to be popped while stepping.

View File

@ -31,11 +31,6 @@ add_task(threadClientTest(({ threadClient, debuggee }) => {
Assert.equal(packet.why.type, "breakpoint");
Assert.notEqual(packet.why.type, "resumeLimit");
},
function(packet) {
// Stepped to the closing brace of the function.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);
Assert.equal(packet.why.type, "resumeLimit");
},
function(packet) {
// The frame is about to be popped while stepping.
Assert.equal(packet.frame.where.line, debuggee.line0 + 3);

View File

@ -25,6 +25,9 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
let variables = frame.environment.bindings.variables;
Assert.equal(variables.i.value.type, "undefined");
const location2 = { sourceUrl: sourceClient.url, line: 7 };
setBreakpoint(threadClient, location2);
packet = await executeOnNextTickAndWaitForPause(
() => resume(threadClient),
client
@ -36,9 +39,9 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
frame = packet.frame;
where = frame.where;
Assert.equal(where.actor, source.actor);
Assert.equal(where.line, location.line);
Assert.equal(where.line, location2.line);
variables = frame.environment.bindings.variables;
Assert.equal(variables.i.value, 0);
Assert.equal(variables.i.value, 1);
await resume(threadClient);
}, { doNotRunWorker: true }));

View File

@ -37,7 +37,12 @@ function run_test() {
}
const SOURCE_URL = "http://example.com/foobar.js";
const SOURCE_CONTENT = "stopMe()";
const SOURCE_CONTENT = `
stopMe();
for(var i = 0; i < 2; i++) {
debugger;
}
`;
function test_source() {
DebuggerServer.LONG_STRING_LENGTH = 200;
@ -60,11 +65,23 @@ function test_source() {
Assert.deepEqual(
response.positions,
[{
line: 1,
column: 0,
line: 2,
column: 2,
}, {
line: 1,
column: 8,
line: 3,
column: 14,
}, {
line: 3,
column: 17,
}, {
line: 3,
column: 24,
}, {
line: 4,
column: 4,
}, {
line: 6,
column: 0,
}]
);
@ -74,7 +91,10 @@ function test_source() {
Assert.deepEqual(
response.positions,
{
1: [0, 8],
2: [2],
3: [14, 17, 24],
4: [4],
6: [0],
}
);

View File

@ -61,7 +61,7 @@ async function stepOutOfA(dbg, func, expectedLocation) {
async function stepOverInA(dbg, func, expectedLocation) {
await invokeAndPause(dbg, `${func}()`);
await steps(dbg, [stepOver, stepIn, stepOver]);
await steps(dbg, [stepOver, stepIn]);
let packet = await step(dbg, stepOver);
dump(`>> stepOverInA hi\n`);
@ -82,9 +82,9 @@ function run_test() {
return (async function() {
const dbg = await setupTestFromUrl("stepping.js");
await testStep(dbg, "arithmetic", {line: 16, column: 8});
await testStep(dbg, "composition", {line: 21, column: 2});
await testStep(dbg, "chaining", {line: 26, column: 6});
await testStep(dbg, "arithmetic", {line: 17, column: 0});
await testStep(dbg, "composition", {line: 22, column: 0});
await testStep(dbg, "chaining", {line: 27, column: 0});
await testFinish(dbg);
})();

View File

@ -49,7 +49,7 @@ async function testRet(dbg) {
info(`1. Test returning from doRet via stepping over`);
await invokeAndPause(dbg, `doRet()`);
await steps(dbg, [stepOver, stepIn, stepOver]);
await steps(dbg, [stepOver, stepIn]);
packet = await step(dbg, stepOver);
deepEqual(
@ -89,7 +89,7 @@ async function testThrow(dbg) {
info(`3. Test leaving from doThrow via stepping over`);
await invokeAndPause(dbg, `doThrow()`);
await steps(dbg, [stepOver, stepOver, stepIn]);
await steps(dbg, [stepOver, stepIn]);
packet = await step(dbg, stepOver);
deepEqual(
@ -113,24 +113,19 @@ async function testThrow(dbg) {
info(`4. Test leaving from doThrow via stepping out`);
await invokeAndPause(dbg, `doThrow()`);
await steps(dbg, [stepOver, stepOver, stepIn]);
await steps(dbg, [stepOver, stepIn]);
packet = await step(dbg, stepOut);
deepEqual(
getPauseLocation(packet),
{line: 22, column: 14},
`completion location in doThrow`
{line: 24, column: 0},
`stepOut location in doThrow`
);
deepEqual(
getFrameFinished(packet).throw.class,
"Error",
`completion completion value class`
);
deepEqual(
getFrameFinished(packet).throw.preview.message,
"yo",
`completion completion value preview`
getFrameFinished(packet),
{return: {type: "undefined"}},
`completion type`
);
await resume(dbg.threadClient);
}

View File

@ -29,17 +29,14 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
dumpn("Continuing and waiting for second debugger statement");
const dbgStmt2 = await resumeAndWaitForPause(client, threadClient);
equal(dbgStmt2.frame.where.line, 12,
"Should be at debugger statement on line 3");
"Should be at debugger statement on line 12");
dumpn("Testing stepping with explicit return");
const step3 = await stepOver(client, threadClient);
equal(step3.frame.where.line, 13, "Should step to line 13");
const step4 = await stepOver(client, threadClient);
equal(step4.frame.where.line, 15, "Should step out of the function from line 15");
// This step is a bit funny, see bug 1013219 for details.
const step5 = await stepOver(client, threadClient);
equal(step5.frame.where.line, 15, "Should step out of the function from line 15");
ok(step5.why.frameFinished, "This should be the explicit function return");
ok(step4.why.frameFinished, "This should be the explicit function return");
}));
function evaluateTestCode(debuggee) {

View File

@ -21,13 +21,17 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
await threadClient.setBreakpoint({ sourceUrl: source.url, line: 7 }, {});
dumpn("Step in to innerFunction");
const step1 = await stepIn(client, threadClient);
equal(step1.frame.where.line, 7);
const step1 = await stepOver(client, threadClient);
equal(step1.frame.where.line, 3);
dumpn("Step in to innerFunction");
const step2 = await stepIn(client, threadClient);
equal(step2.frame.where.line, 7);
dumpn("Step out of innerFunction");
const step2 = await stepOut(client, threadClient);
const step3 = await stepOut(client, threadClient);
// The bug was that we'd stop again at the breakpoint on line 7.
equal(step2.frame.where.line, 4);
equal(step3.frame.where.line, 4);
}));
function evaluateTestCode(debuggee) {

View File

@ -18,7 +18,7 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
const step2 = await stepOut(client, threadClient);
// The bug was that we'd step right past the end of the function and never pause.
equal(step2.frame.where.line, 2);
equal(step2.why.frameFinished.return, 42);
deepEqual(step2.why.frameFinished.return, { type: "undefined"});
}));
function evaluateTestCode(debuggee) {

View File

@ -1,76 +0,0 @@
/* 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.
*/
add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
dumpn("Evaluating test code and waiting for first debugger statement");
const dbgStmt = await executeOnNextTickAndWaitForPause(
() => evaluateTestCode(debuggee), client);
equal(dbgStmt.frame.where.line, 2, "Should be at debugger statement on line 2");
equal(debuggee.a, undefined);
equal(debuggee.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(client, threadClient);
equal(step1.type, "paused");
equal(step1.why.type, "resumeLimit");
equal(step1.frame.where.line, 3);
equal(step1.frame.where.column, 0);
equal(debuggee.a, undefined);
equal(debuggee.b, undefined);
dumpn("Step Over to line 4");
const step2 = await stepOver(client, threadClient);
equal(step2.type, "paused");
equal(step2.why.type, "resumeLimit");
equal(step2.frame.where.line, 4);
equal(step2.frame.where.column, 0);
equal(debuggee.a, 1);
equal(debuggee.b, undefined);
dumpn("Step Over to the end of line 4");
const step3 = await stepOver(client, threadClient);
equal(step3.type, "paused");
equal(step3.why.type, "resumeLimit");
equal(step3.frame.where.line, 4);
equal(step3.frame.where.column, 14);
equal(debuggee.a, 1);
equal(debuggee.b, 2);
}));
function evaluateTestCode(debuggee) {
/* eslint-disable */
Cu.evalInSandbox(
` // 1
debugger; // 2
var a = 1; // 3
var b = 2;`, // 4
debuggee,
"1.8",
"test_stepping-01-test-code.js",
1
);
/* eslint-disable */
}

View File

@ -35,7 +35,7 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
equal(step1.type, "paused");
equal(step1.why.type, "resumeLimit");
equal(step1.frame.where.line, 3);
equal(step1.frame.where.column, 0);
equal(step1.frame.where.column, 12);
equal(debuggee.a, undefined);
equal(debuggee.b, undefined);
@ -45,7 +45,7 @@ add_task(threadClientTest(async ({ threadClient, debuggee, client }) => {
equal(step2.type, "paused");
equal(step2.why.type, "resumeLimit");
equal(step2.frame.where.line, 4);
equal(step2.frame.where.column, 0);
equal(step2.frame.where.column, 12);
equal(debuggee.a, 1);
equal(debuggee.b, undefined);

View File

@ -192,7 +192,6 @@ skip-if = true # breakpoint sliding is not supported bug 1525685
[test_stepping-07.js]
[test_stepping-08.js]
[test_stepping-09.js]
[test_stepping-with-pause-points.js]
[test_stepping-with-skip-breakpoints.js]
[test_framebindings-01.js]
[test_framebindings-02.js]