Revert "Backed out changeset 3599e95a53b7 (bug 923975) for build bustage when reverting backout on a CLOSED TREE"

This reverts commit e0e90b5c82d8f05feb9df1e5b675c0680b469524.
This commit is contained in:
Jason Laster 2018-10-02 16:36:19 -04:00
Родитель 867896e0c3
Коммит 5fad9a20a0
12 изменённых файлов: 308 добавлений и 213 удалений

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

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

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

@ -21,8 +21,8 @@ async function test() {
await stepOverToLine(client, 27);
await reverseStepInToLine(client, 33);
await reverseStepOverToLine(client, 32);
await reverseStepOutToLine(client, 26);
await reverseStepOverToLine(client, 25);
await reverseStepOutToLine(client, 23);
await reverseStepOverToLine(client, 22);
await toolbox.destroy();
await gBrowser.removeTab(tab);

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

@ -49,12 +49,13 @@ function test() {
{key: "KEY_F11", keyRepeat: 2, caretLine: 18},
{key: "KEY_F11", keyRepeat: 2, caretLine: 27},
{key: "KEY_F10", keyRepeat: 1, caretLine: 27},
{key: "KEY_F11", keyRepeat: 1, caretLine: 18},
{key: "KEY_F11", keyRepeat: 5, caretLine: 32},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 1, caretLine: 29},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 2, caretLine: 34},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 2, caretLine: 34}
{key: "KEY_F11", keyRepeat: 1, caretLine: 19},
{key: "KEY_F11", keyRepeat: 5, caretLine: 29},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 1, caretLine: 32},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 1, caretLine: 34},
{key: "KEY_F11", modifier:"Shift", keyRepeat: 1, caretLine: 34}
];
// Trigger script that stops at debugger statement
executeSoon(() => generateMouseClickInTab(gTab,
"content.document.getElementById('start')"));

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

@ -88,6 +88,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
this.onUpdatedSourceEvent = this.onUpdatedSourceEvent.bind(this);
this.uncaughtExceptionHook = this.uncaughtExceptionHook.bind(this);
this.createCompletionGrip = this.createCompletionGrip.bind(this);
this.onDebuggerStatement = this.onDebuggerStatement.bind(this);
this.onNewScript = this.onNewScript.bind(this);
this.objectGrip = this.objectGrip.bind(this);
@ -522,15 +523,15 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
};
},
_makeOnPop: function({ thread, pauseAndRespond, createValueGrip: createValueGripHook,
startLocation }) {
_makeOnPop: function({ thread, pauseAndRespond, startLocation, steppingType }) {
const result = function(completion) {
// onPop is called with 'this' set to the current frame.
const generatedLocation = thread.sources.getFrameLocation(this);
const { originalSourceActor } = thread.unsafeSynchronize(
const originalLocation = thread.unsafeSynchronize(
thread.sources.getOriginalLocation(generatedLocation)
);
const { originalSourceActor } = originalLocation;
const url = originalSourceActor.url;
if (thread.sources.isBlackBoxed(url)) {
@ -541,16 +542,24 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
// subsequent step events on its caller.
this.reportedPop = true;
if (steppingType == "finish") {
const parentFrame = thread._getNextStepFrame(this);
if (parentFrame && parentFrame.script) {
const { onStep } = thread._makeSteppingHooks(
originalLocation, "next", false, completion
);
parentFrame.onStep = onStep;
return undefined;
}
}
return pauseAndRespond(this, packet => {
packet.why.frameFinished = {};
if (!completion) {
packet.why.frameFinished.terminated = true;
} else if (completion.hasOwnProperty("return")) {
packet.why.frameFinished.return = createValueGripHook(completion.return);
} else if (completion.hasOwnProperty("yield")) {
packet.why.frameFinished.return = createValueGripHook(completion.yield);
if (completion) {
thread.createCompletionGrip(packet, completion);
} else {
packet.why.frameFinished.throw = createValueGripHook(completion.throw);
packet.why.frameFinished = {
terminated: true
};
}
return packet;
});
@ -569,7 +578,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
},
// Return whether reaching a script offset should be considered a distinct
// "step" from another location in the same frame.
// "step" from another location.
_intraFrameLocationIsStepTarget: function(startLocation, script, offset) {
// Only allow stepping stops at entry points for the line.
if (!script.getOffsetLocation(offset).isEntryPoint) {
@ -621,7 +630,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
},
_makeOnStep: function({ thread, pauseAndRespond, startFrame,
startLocation, steppingType }) {
startLocation, steppingType, completion }) {
// Breaking in place: we should always pause.
if (steppingType === "break") {
return () => pauseAndRespond(this);
@ -646,15 +655,13 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
return undefined;
}
// A step has occurred if we have changed frames.
if (this !== startFrame) {
return pauseAndRespond(this);
}
// A step has occurred if we reached a step target.
if (thread._intraFrameLocationIsStepTarget(startLocation,
this.script, this.offset)) {
return pauseAndRespond(this);
return pauseAndRespond(
this,
packet => thread.createCompletionGrip(packet, completion)
);
}
// Otherwise, let execution continue (we haven't executed enough code to
@ -663,6 +670,25 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
};
},
createCompletionGrip: function(packet, completion) {
if (!completion) {
return packet;
}
const createGrip = value => createValueGrip(value, this._pausePool, this.objectGrip);
packet.why.frameFinished = {};
if (completion.hasOwnProperty("return")) {
packet.why.frameFinished.return = createGrip(completion.return);
} else if (completion.hasOwnProperty("yield")) {
packet.why.frameFinished.return = createGrip(completion.yield);
} else if (completion.hasOwnProperty("throw")) {
packet.why.frameFinished.throw = createGrip(completion.throw);
}
return packet;
},
/**
* When replaying, we need to specify the offsets where a frame's onStep hook
* should fire. Given that we are stepping forward (rewind == false) or
@ -696,7 +722,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
/**
* Define the JS hook functions for stepping.
*/
_makeSteppingHooks: function(startLocation, steppingType, rewinding) {
_makeSteppingHooks: function(startLocation, steppingType, rewinding, completion) {
// Bind these methods and state because some of the hooks are called
// with 'this' set to the current frame. Rather than repeating the
// binding in each _makeOnX method, just do it once here and pass it
@ -707,12 +733,12 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
{ type: "resumeLimit" },
onPacket
),
createValueGrip: v => createValueGrip(v, this._pausePool, this.objectGrip),
thread: this,
startFrame: this.youngestFrame,
startLocation: startLocation,
steppingType: steppingType,
rewinding: rewinding
rewinding: rewinding,
completion
};
return {

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

@ -846,3 +846,32 @@ function getInflatedStackLocations(thread, sample) {
// The profiler tree is inverted, so reverse the array.
return locations.reverse();
}
async function setupTestFromUrl(url) {
do_test_pending();
const { createRootActor } = require("xpcshell-test/testactors");
DebuggerServer.setRootActor(createRootActor);
DebuggerServer.init(() => true);
const global = createTestGlobal("test");
DebuggerServer.addTestGlobal(global);
const debuggerClient = new DebuggerClient(DebuggerServer.connectPipe());
await connect(debuggerClient);
const { tabs } = await listTabs(debuggerClient);
const tab = findTab(tabs, "test");
const [, tabClient] = await attachTarget(debuggerClient, tab);
const [, threadClient] = await attachThread(tabClient);
await resume(threadClient);
const sourceUrl = getFileUrl(url);
const promise = waitForNewSource(threadClient, sourceUrl);
loadSubScript(sourceUrl, global);
const { source } = await promise;
const sourceClient = threadClient.source(source);
return { global, debuggerClient, threadClient, sourceClient };
}

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

@ -68,18 +68,13 @@ function test_simple_breakpoint() {
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// The foo function call frame was just popped from the stack.
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(gDebuggee.a, 1);
Assert.equal(gDebuggee.b, undefined);
Assert.equal(packet.frame.where.line, gDebuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, gDebuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.

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

@ -66,18 +66,13 @@ function test_simple_breakpoint() {
Assert.equal(packet.why.frameFinished.return.type, "undefined");
},
function(packet) {
// The foo function call frame was just popped from the stack.
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(gDebuggee.a, 1);
Assert.equal(gDebuggee.b, undefined);
Assert.equal(packet.frame.where.line, gDebuggee.line0 + 5);
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.
Assert.equal(packet.frame.where.line, gDebuggee.line0 + 6);
Assert.notEqual(packet.why.type, "debuggerStatement");
Assert.equal(packet.why.type, "resumeLimit");
Assert.equal(packet.poppedFrames.length, 1);
},
function(packet) {
// Check that the debugger statement wasn't the reason for this pause.

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

@ -5,77 +5,87 @@
"use strict";
/**
* Check basic step-over functionality.
* Check scenarios where we're leaving function a and
* going to the function b's call-site.
*/
var gDebuggee;
var gClient;
var gCallback;
async function testFinish({threadClient, debuggerClient}) {
await resume(threadClient);
await close(debuggerClient);
do_test_finished();
}
async function invokeAndPause({global, debuggerClient}, expression) {
return executeOnNextTickAndWaitForPause(
() => Cu.evalInSandbox(expression, global),
debuggerClient
);
}
async function step({threadClient, debuggerClient}, cmd) {
return cmd(debuggerClient, threadClient);
}
function getPauseLocation(packet) {
const {line, column} = packet.frame.where;
return {line, column};
}
function getPauseReturn(packet) {
dump(`>> getPauseReturn yo ${JSON.stringify(packet.why)}\n`);
return packet.why.frameFinished.return;
}
async function steps(dbg, sequence) {
const locations = [];
for (const cmd of sequence) {
const packet = await step(dbg, cmd);
locations.push(getPauseLocation(packet));
}
return locations;
}
async function stepOutOfA(dbg, func, expectedLocation) {
await invokeAndPause(dbg, `${func}()`);
await steps(dbg, [stepOver, stepIn]);
dump(`>>> oof\n`);
const packet = await step(dbg, stepOut);
dump(`>>> foo\n`);
deepEqual(getPauseLocation(packet), expectedLocation, `step out location in ${func}`);
await resume(dbg.threadClient);
}
async function stepOverInA(dbg, func, expectedLocation) {
await invokeAndPause(dbg, `${func}()`);
await steps(dbg, [stepOver, stepIn, stepOver]);
let packet = await step(dbg, stepOver);
dump(`>> stepOverInA hi\n`);
equal(getPauseReturn(packet).ownPropertyLength, 1, "a() is returning obj");
packet = await step(dbg, stepOver);
deepEqual(getPauseLocation(packet), expectedLocation, `step out location in ${func}`);
await resume(dbg.threadClient);
}
async function testStep(dbg, func, expectedLocation) {
await stepOverInA(dbg, func, expectedLocation);
await stepOutOfA(dbg, func, expectedLocation);
}
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);
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(gDebuggee.a, undefined);
equal(gDebuggee.b, undefined);
dumpn("Step Over to line 4");
const step3 = await stepOver(gClient, threadClient);
equal(step3.type, "paused");
equal(step3.why.type, "resumeLimit");
equal(step3.frame.where.line, 4);
equal(gDebuggee.a, 1);
equal(gDebuggee.b, undefined);
dumpn("Step Over to line 4 to leave the frame");
const step4 = await stepOver(gClient, threadClient);
equal(step4.type, "paused");
equal(step4.why.type, "resumeLimit");
equal(step4.frame.where.line, 4);
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 */
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 testFinish(dbg);
})();
}

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

@ -37,7 +37,7 @@ async function test_simple_stepping() {
const step1 = await stepOut(gClient, threadClient);
equal(step1.type, "paused");
equal(step1.frame.where.line, 6);
equal(step1.frame.where.line, 8);
equal(step1.why.type, "resumeLimit");
equal(gDebuggee.a, 1);

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

@ -8,103 +8,140 @@
* Check that stepping out of a function returns the right return value.
*/
var gDebuggee;
var gClient;
var gThreadClient;
var gCallback;
async function invokeAndPause({global, debuggerClient}, expression) {
return executeOnNextTickAndWaitForPause(
() => Cu.evalInSandbox(expression, global),
debuggerClient
);
}
async function step({threadClient, debuggerClient}, cmd) {
return cmd(debuggerClient, threadClient);
}
function getPauseLocation(packet) {
const {line, column} = packet.frame.where;
return {line, column};
}
function getFrameFinished(packet) {
return packet.why.frameFinished;
}
async function steps(dbg, sequence) {
const locations = [];
for (const cmd of sequence) {
const packet = await step(dbg, cmd);
locations.push(getPauseLocation(packet));
}
return locations;
}
async function testFinish({threadClient, debuggerClient}) {
await resume(threadClient);
await close(debuggerClient);
do_test_finished();
}
async function testRet(dbg) {
let packet;
info(`1. Test returning from doRet via stepping over`);
await invokeAndPause(dbg, `doRet()`);
await steps(dbg, [stepOver, stepIn, stepOver]);
packet = await step(dbg, stepOver);
deepEqual(
getPauseLocation(packet),
{line: 6, column: 0},
`completion location in doRet`
);
deepEqual(
getFrameFinished(packet),
{"return": 2}, `completion value`);
await resume(dbg.threadClient);
info(`2. Test leaving from doRet via stepping out`);
await invokeAndPause(dbg, `doRet()`);
await steps(dbg, [stepOver, stepIn]);
packet = await step(dbg, stepOut);
deepEqual(
getPauseLocation(packet),
{line: 15, column: 2},
`completion location in doThrow`
);
deepEqual(
getFrameFinished(packet),
{"return": 2},
`completion completion value`
);
await resume(dbg.threadClient);
}
async function testThrow(dbg) {
let packet;
info(`3. Test leaving from doThrow via stepping over`);
await invokeAndPause(dbg, `doThrow()`);
await steps(dbg, [stepOver, stepOver, stepIn]);
packet = await step(dbg, stepOver);
deepEqual(
getPauseLocation(packet),
{line: 9, column: 8},
`completion location in doThrow`
);
deepEqual(
getFrameFinished(packet).throw.class,
"Error",
`completion value class`
);
deepEqual(
getFrameFinished(packet).throw.preview.message,
"yo",
`completion value preview`
);
await resume(dbg.threadClient);
info(`4. Test leaving from doThrow via stepping out`);
await invokeAndPause(dbg, `doThrow()`);
await steps(dbg, [stepOver, stepOver, stepIn]);
packet = await step(dbg, stepOut);
deepEqual(
getPauseLocation(packet),
{line: 22, column: 14},
`completion location in doThrow`
);
deepEqual(
getFrameFinished(packet).throw.class,
"Error",
`completion completion value class`
);
deepEqual(
getFrameFinished(packet).throw.preview.message,
"yo",
`completion completion value preview`
);
await resume(dbg.threadClient);
}
function run_test() {
run_test_with_server(DebuggerServer, function() {
run_test_with_server(WorkerDebuggerServer, do_test_finished);
});
do_test_pending();
}
function run_test_with_server(server, callback) {
gCallback = callback;
initTestDebuggerServer(server);
gDebuggee = addTestGlobal("test-stack", server);
gClient = new DebuggerClient(server.connectPipe());
gClient.connect().then(function() {
attachTestTabAndResume(
gClient, "test-stack",
function(response, tabClient, threadClient) {
gThreadClient = threadClient;
// XXX: We have to do an executeSoon so that the error isn't caught and
// reported by DebuggerClient.requester (because we are using the local
// transport and share a stack) which causes the test to fail.
Services.tm.dispatchToMainThread({
run: test_simple_stepping
});
});
});
}
async function test_simple_stepping() {
await executeOnNextTickAndWaitForPause(evaluateTestCode, gClient);
const step1 = await stepOut(gClient, gThreadClient);
equal(step1.type, "paused");
equal(step1.frame.where.line, 6);
equal(step1.why.type, "resumeLimit");
equal(step1.why.frameFinished.return, 10);
gThreadClient.resume();
const step2 = await waitForPause(gThreadClient);
equal(step2.type, "paused");
equal(step2.frame.where.line, 8);
equal(step2.why.type, "debuggerStatement");
gThreadClient.stepOut();
const step3 = await waitForPause(gThreadClient);
equal(step3.type, "paused");
equal(step3.frame.where.line, 9);
equal(step3.why.type, "resumeLimit");
equal(step3.why.frameFinished.return.type, "undefined");
gThreadClient.resume();
const step4 = await waitForPause(gThreadClient);
equal(step4.type, "paused");
equal(step4.frame.where.line, 11);
gThreadClient.stepOut();
const step5 = await waitForPause(gThreadClient);
equal(step5.type, "paused");
equal(step5.frame.where.line, 12);
equal(step5.why.type, "resumeLimit");
equal(step5.why.frameFinished.throw, "ah");
finishClient(gClient, gCallback);
}
function evaluateTestCode() {
/* eslint-disable */
Cu.evalInSandbox(
` // 1
function f() { // 2
debugger; // 3
var a = 10; // 4
return a; // 5
} // 6
function g() { // 7
debugger; // 8
} // 9
function h() { // 10
debugger; // 11
throw 'ah'; // 12
return 2; // 13
} // 14
f() // 15
g() // 16
try { // 17
h(); // 18
} catch (ex) { }; // 19
`, // 20
gDebuggee,
"1.8",
"test_stepping-07-test-code.js",
1
);
/* eslint-enable */
return (async function() {
const dbg = await setupTestFromUrl("completions.js");
await testRet(dbg);
await testThrow(dbg);
await testFinish(dbg);
})();
}

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

@ -46,7 +46,7 @@ async function testStepOutWithBreakpoint() {
dumpn("Step out of innerFunction");
const step2 = await stepOut(gClient, threadClient);
// The bug was that we'd stop again at the breakpoint on line 7.
equal(step2.frame.where.line, 10);
equal(step2.frame.where.line, 4);
finishClient(gClient, gCallback);
}

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

@ -6,6 +6,7 @@ skip-if = toolkit == 'android'
support-files =
babel_and_browserify_script_with_source_map.js
completions.js
source-map-data/sourcemapped.coffee
source-map-data/sourcemapped.map
post_init_global_actors.js
@ -16,6 +17,7 @@ support-files =
sourcemapped.js
testactors.js
hello-actor.js
stepping.js
setBreakpoint-on-column.js
setBreakpoint-on-column-in-gcd-script.js
setBreakpoint-on-column-with-no-offsets.js