mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1000967 - Add source notes for |new| expression and function calls to improve source maps and debugging. r=ejpbruel
This commit is contained in:
parent
2ec301a262
commit
f79fcccd5f
@ -41,7 +41,7 @@ function runTests()
|
||||
method: "display",
|
||||
code: error1,
|
||||
result: error1 + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
|
||||
label: "error display output"
|
||||
},
|
||||
{
|
||||
@ -78,7 +78,7 @@ function runTests()
|
||||
method: "run",
|
||||
code: error1,
|
||||
result: error1 + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
|
||||
label: "error run output"
|
||||
},
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ function runTests()
|
||||
method: "display",
|
||||
code: error,
|
||||
result: error + openComment + "Exception: Ouch!\n@" +
|
||||
scratchpad.uniqueName + ":1:1" + closeComment,
|
||||
scratchpad.uniqueName + ":1:7" + closeComment,
|
||||
label: "error display output",
|
||||
},
|
||||
{
|
||||
@ -57,7 +57,7 @@ function runTests()
|
||||
method: "run",
|
||||
code: error,
|
||||
result: error + openComment + "Exception: Ouch!\n@" +
|
||||
scratchpad.uniqueName + ":1:1" + closeComment,
|
||||
scratchpad.uniqueName + ":1:7" + closeComment,
|
||||
label: "error run output",
|
||||
},
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=923010
|
||||
}, { "mandatory": { "BOGUS": 5 } } )
|
||||
ok(false, "That call to createAnswer should have thrown");
|
||||
} catch (e) {
|
||||
is(e.lineNumber, 20, "Exception should have been on line 20");
|
||||
is(e.lineNumber, 16, "Exception should have been on line 16");
|
||||
is(e.message,
|
||||
"createAnswer passed invalid constraints - unknown mandatory constraint: BOGUS",
|
||||
"Should have the exception we expect");
|
||||
|
@ -37,8 +37,8 @@
|
||||
[ "Callback message", msg, "Error: hello" ],
|
||||
[ "Event error-object", errorEvent.error, thrown],
|
||||
[ "Callback error-object", error, thrown ],
|
||||
[ "Event column", errorEvent.colno, 6 ], // Sadly not correct right now
|
||||
[ "Callback column", column, 6 ]
|
||||
[ "Event column", errorEvent.colno, 15 ],
|
||||
[ "Callback column", column, 15 ]
|
||||
]);
|
||||
</script>
|
||||
<script>
|
||||
|
@ -50,6 +50,9 @@ using mozilla::PodCopy;
|
||||
static bool
|
||||
SetSrcNoteOffset(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which, ptrdiff_t offset);
|
||||
|
||||
static bool
|
||||
UpdateSourceCoordNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset);
|
||||
|
||||
struct frontend::StmtInfoBCE : public StmtInfoBase
|
||||
{
|
||||
StmtInfoBCE *down; /* info for enclosing statement */
|
||||
@ -273,8 +276,10 @@ EmitJump(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, ptrdiff_t off)
|
||||
}
|
||||
|
||||
static ptrdiff_t
|
||||
EmitCall(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, uint16_t argc)
|
||||
EmitCall(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, uint16_t argc, ParseNode *pn=nullptr)
|
||||
{
|
||||
if (pn && !UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
|
||||
return -1;
|
||||
return Emit3(cx, bce, op, ARGC_HI(argc), ARGC_LO(argc));
|
||||
}
|
||||
|
||||
@ -4505,7 +4510,7 @@ EmitForOf(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t t
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // ITER NEXT ITER UNDEFINED
|
||||
return false;
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1) < 0) // ITER RESULT
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1, forHead) < 0) // ITER RESULT
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
if (Emit1(cx, bce, JSOP_DUP) < 0) // ITER RESULT RESULT
|
||||
@ -5196,7 +5201,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR ITERABLE
|
||||
return false;
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 0) < 0) // ITER
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 0, iter) < 0) // ITER
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
|
||||
@ -5268,7 +5273,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||
return false;
|
||||
if (Emit2(cx, bce, JSOP_PICK, (jsbytecode)3) < 0) // ITER THROW ITER EXCEPTION
|
||||
return false;
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1) < 0) // ITER RESULT
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
JS_ASSERT(bce->stackDepth == depth + 1);
|
||||
@ -5305,7 +5310,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||
return false;
|
||||
if (Emit2(cx, bce, JSOP_PICK, (jsbytecode)3) < 0) // ITER NEXT ITER RECEIVED
|
||||
return false;
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1) < 0) // ITER RESULT
|
||||
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
JS_ASSERT(bce->stackDepth == depth + 1);
|
||||
@ -5626,7 +5631,7 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
}
|
||||
|
||||
if (!spread) {
|
||||
if (EmitCall(cx, bce, pn->getOp(), argc) < 0)
|
||||
if (EmitCall(cx, bce, pn->getOp(), argc, pn) < 0)
|
||||
return false;
|
||||
} else {
|
||||
if (Emit1(cx, bce, pn->getOp()) < 0)
|
||||
|
@ -8,7 +8,7 @@ dbg.onDebuggerStatement = function (frame) {
|
||||
assertEq(exc.message, "diaf");
|
||||
assertEq(exc.fileName, "fail");
|
||||
assertEq(exc.lineNumber, 4);
|
||||
assertEq(exc.columnNumber, 20);
|
||||
assertEq(exc.columnNumber, 24);
|
||||
return;
|
||||
}
|
||||
throw new Error("deleteProperty should throw");
|
||||
|
27
js/src/jit-test/tests/debug/Script-getAllColumnOffsets-06.js
Normal file
27
js/src/jit-test/tests/debug/Script-getAllColumnOffsets-06.js
Normal file
@ -0,0 +1,27 @@
|
||||
// getColumnOffsets correctly places function calls.
|
||||
|
||||
var global = newGlobal();
|
||||
Debugger(global).onDebuggerStatement = function (frame) {
|
||||
var script = frame.eval("f").return.script;
|
||||
script.getAllColumnOffsets().forEach(function (offset) {
|
||||
script.setBreakpoint(offset.offset, {
|
||||
hit: function (frame) {
|
||||
assertEq(offset.lineNumber, 1);
|
||||
global.log += offset.columnNumber + " ";
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
global.log = "";
|
||||
// 1 2 3 4
|
||||
// 0123456789012345678901234567890123456789012345678
|
||||
global.eval("function f(){ 1 && print(print()) && new Error() } debugger;");
|
||||
global.f();
|
||||
|
||||
// 14 - Enter the function body
|
||||
// 25 - Inner print()
|
||||
// 19 - Outer print()
|
||||
// 37 - new Error()
|
||||
// 48 - Exit the function body
|
||||
assertEq(global.log, "14 25 19 37 48 ");
|
@ -25,7 +25,9 @@ test(foo, 1);
|
||||
|
||||
//234567890123456789
|
||||
test(function(f) { return f.bar; }, 19);
|
||||
test(function(f) { return f(); }, 19);
|
||||
// 1 2
|
||||
//2345678901234567890123456
|
||||
test(function(f) { return f(); }, 26);
|
||||
/* Cover negative colspan case using for(;;) loop with error in update part. */
|
||||
test(function(){
|
||||
//0 1 2 3 4
|
||||
@ -41,9 +43,9 @@ test(function() { var tmp = null; tmp.foo; }, 35)
|
||||
|
||||
/* Just a generic 'throw'. */
|
||||
test(function() {
|
||||
//234567890123
|
||||
//234567890123456789
|
||||
foo({}); throw new Error('a');
|
||||
}, 13);
|
||||
}, 19);
|
||||
|
||||
/* Be sure to report the right statement */
|
||||
test(function() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
actual = 'No Error';
|
||||
expected = /column-numbers\.js:4:5/;
|
||||
expected = /column-numbers\.js:4:11/;
|
||||
try {
|
||||
throw new Error("test");
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ const Cr = Components.results;
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { worker } = Cu.import("resource://gre/modules/devtools/worker-loader.js", {})
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
const { promiseInvoke } = devtools.require("devtools/async-utils");
|
||||
|
||||
const Services = devtools.require("Services");
|
||||
// Always log packets when running tests. runxpcshelltests.py will throw
|
||||
@ -22,12 +24,16 @@ const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils.js");
|
||||
const { DebuggerServer } = devtools.require("devtools/server/main");
|
||||
const { DebuggerServer: WorkerDebuggerServer } = worker.require("devtools/server/main");
|
||||
|
||||
function dumpn(msg) {
|
||||
dump("DBG-TEST: " + msg + "\n");
|
||||
}
|
||||
|
||||
function tryImport(url) {
|
||||
try {
|
||||
Cu.import(url);
|
||||
} catch (e) {
|
||||
dump("Error importing " + url + "\n");
|
||||
dump(DevToolsUtils.safeErrorString(e) + "\n");
|
||||
dumpn("Error importing " + url);
|
||||
dumpn(DevToolsUtils.safeErrorString(e));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -78,9 +84,9 @@ let listener = {
|
||||
// If we've been given an nsIScriptError, then we can print out
|
||||
// something nicely formatted, for tools like Emacs to pick up.
|
||||
var scriptError = aMessage.QueryInterface(Ci.nsIScriptError);
|
||||
dump(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
||||
aMessage.errorMessage + "\n");
|
||||
dumpn(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
||||
aMessage.errorMessage);
|
||||
var string = aMessage.errorMessage;
|
||||
} catch (x) {
|
||||
// Be a little paranoid with message, as the whole goal here is to lose
|
||||
@ -106,7 +112,7 @@ let listener = {
|
||||
// If we throw an error here because of them our tests start failing.
|
||||
// So, we'll just dump the message to the logs instead, to make sure the
|
||||
// information isn't lost.
|
||||
dump("head_dbg.js observed a console message: " + string + "\n");
|
||||
dumpn("head_dbg.js observed a console message: " + string);
|
||||
}
|
||||
};
|
||||
|
||||
@ -121,7 +127,7 @@ function check_except(func)
|
||||
do_check_true(true);
|
||||
return;
|
||||
}
|
||||
dump("Should have thrown an exception: " + func.toString());
|
||||
dumpn("Should have thrown an exception: " + func.toString());
|
||||
do_check_true(false);
|
||||
}
|
||||
|
||||
@ -336,9 +342,9 @@ TracingTransport.prototype = {
|
||||
dumpLog: function() {
|
||||
for (let entry of this.packets) {
|
||||
if (entry.type === "sent") {
|
||||
dump("trace.expectSend(" + entry.packet + ");\n");
|
||||
dumpn("trace.expectSend(" + entry.packet + ");");
|
||||
} else {
|
||||
dump("trace.expectReceive(" + entry.packet + ");\n");
|
||||
dumpn("trace.expectReceive(" + entry.packet + ");");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -407,3 +413,171 @@ const Test = task => () => {
|
||||
};
|
||||
|
||||
const assert = do_check_true;
|
||||
|
||||
/**
|
||||
* Create a promise that is resolved on the next occurence of the given event.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param String event
|
||||
* @returns Promise
|
||||
*/
|
||||
function waitForEvent(client, event) {
|
||||
dumpn("Waiting for event: " + event);
|
||||
return new Promise((resolve, reject) => {
|
||||
client.addOneTimeListener(event, (_, packet) => resolve(packet));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a promise that is resolved on the next pause.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @returns Promise
|
||||
*/
|
||||
function waitForPause(client) {
|
||||
return waitForEvent(client, "paused");
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action on the next tick and return a promise that is resolved on
|
||||
* the next pause.
|
||||
*
|
||||
* When using promises and Task.jsm, we often want to do an action that causes a
|
||||
* pause and continue the task once the pause has ocurred. Unfortunately, if we
|
||||
* do the action that causes the pause within the task's current tick we will
|
||||
* pause before we have a chance to yield the promise that waits for the pause
|
||||
* and we enter a dead lock. The solution is to create the promise that waits
|
||||
* for the pause, schedule the action to run on the next tick of the event loop,
|
||||
* and finally yield the promise.
|
||||
*
|
||||
* @param Function action
|
||||
* @param DebuggerClient client
|
||||
* @returns Promise
|
||||
*/
|
||||
function executeOnNextTickAndWaitForPause(action, client) {
|
||||
const paused = waitForPause(client);
|
||||
executeSoon(action);
|
||||
return paused;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a promise that is resolved with the server's response to the client's
|
||||
* Remote Debugger Protocol request. If a response with the `error` property is
|
||||
* received, the promise is rejected. Any extra arguments passed in are
|
||||
* forwarded to the method invocation.
|
||||
*
|
||||
* See `setBreakpoint` below, for example usage.
|
||||
*
|
||||
* @param DebuggerClient/ThreadClient/SourceClient/etc client
|
||||
* @param Function method
|
||||
* @param any args
|
||||
* @returns Promise
|
||||
*/
|
||||
function rdpRequest(client, method, ...args) {
|
||||
return promiseInvoke(client, method, ...args)
|
||||
.then(response => {
|
||||
const { error, message } = response;
|
||||
if (error) {
|
||||
throw new Error(error + ": " + message);
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a breakpoint over the Remote Debugging Protocol.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @param {url, line[, column[, condition]]} breakpointOptions
|
||||
* @returns Promise
|
||||
*/
|
||||
function setBreakpoint(threadClient, breakpointOptions) {
|
||||
dumpn("Setting a breakpoint: " + JSON.stringify(breakpointOptions, null, 2));
|
||||
return rdpRequest(threadClient, threadClient.setBreakpoint, breakpointOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for the specified thread.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function resume(threadClient) {
|
||||
dumpn("Resuming.");
|
||||
return rdpRequest(threadClient, threadClient.resume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for the specified thread and then wait for the next pause
|
||||
* event.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function resumeAndWaitForPause(client, threadClient) {
|
||||
const paused = waitForPause(client);
|
||||
return resume(threadClient).then(() => paused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of sources for the specified thread.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function getSources(threadClient) {
|
||||
dumpn("Getting sources.");
|
||||
return rdpRequest(threadClient, threadClient.getSources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume JS execution for a single step and wait for the pause after the step
|
||||
* has been taken.
|
||||
*
|
||||
* @param DebuggerClient client
|
||||
* @param ThreadClient threadClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function stepIn(client, threadClient) {
|
||||
dumpn("Stepping in.");
|
||||
const paused = waitForPause(client);
|
||||
return rdpRequest(threadClient, threadClient.stepIn)
|
||||
.then(() => paused);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of `count` frames currently on stack, starting at the index
|
||||
* `first` for the specified thread.
|
||||
*
|
||||
* @param ThreadClient threadClient
|
||||
* @param Number first
|
||||
* @param Number count
|
||||
* @returns Promise
|
||||
*/
|
||||
function getFrames(threadClient, first, count) {
|
||||
dumpn("Getting frames.");
|
||||
return rdpRequest(threadClient, threadClient.getFrames, first, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Black box the specified source.
|
||||
*
|
||||
* @param SourceClient sourceClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function blackBox(sourceClient) {
|
||||
dumpn("Black boxing source: " + sourceClient.actor);
|
||||
return rdpRequest(sourceClient, sourceClient.blackBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop black boxing the specified source.
|
||||
*
|
||||
* @param SourceClient sourceClient
|
||||
* @returns Promise
|
||||
*/
|
||||
function unBlackBox(sourceClient) {
|
||||
dumpn("Un-black boxing source: " + sourceClient.actor);
|
||||
return rdpRequest(sourceClient, sourceClient.unblackBox);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ function run_test()
|
||||
gClient.connect(function() {
|
||||
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_black_box();
|
||||
testBlackBox();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
@ -26,18 +26,71 @@ function run_test()
|
||||
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
|
||||
const SOURCE_URL = "http://example.com/source.js";
|
||||
|
||||
function test_black_box()
|
||||
{
|
||||
gClient.addOneTimeListener("paused", function () {
|
||||
gThreadClient.setBreakpoint({
|
||||
url: SOURCE_URL,
|
||||
line: 2
|
||||
}, function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should be able to set breakpoint.");
|
||||
gThreadClient.resume(test_black_box_default);
|
||||
});
|
||||
});
|
||||
const testBlackBox = Task.async(function* () {
|
||||
yield executeOnNextTickAndWaitForPause(evalCode, gClient);
|
||||
|
||||
yield setBreakpoint(gThreadClient, {
|
||||
url: SOURCE_URL,
|
||||
line: 2
|
||||
});
|
||||
yield resume(gThreadClient);
|
||||
|
||||
const sourcesResponse = yield getSources(gThreadClient);
|
||||
let sourceClient = gThreadClient.source(
|
||||
sourcesResponse.sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
do_check_true(!sourceClient.isBlackBoxed,
|
||||
"By default the source is not black boxed.");
|
||||
|
||||
// Test that we can step into `doStuff` when we are not black boxed.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, BLACK_BOXED_URL);
|
||||
do_check_eq(aLocation.line, 2);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.source.isBlackBoxed));
|
||||
}
|
||||
);
|
||||
|
||||
let blackBoxResponse = yield blackBox(sourceClient);
|
||||
do_check_true(sourceClient.isBlackBoxed);
|
||||
|
||||
// Test that we step through `doStuff` when we are black boxed and its frame
|
||||
// doesn't show up.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, SOURCE_URL);
|
||||
do_check_eq(aLocation.line, 3);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
for (let f of aFrames) {
|
||||
if (f.where.url == BLACK_BOXED_URL) {
|
||||
do_check_true(f.source.isBlackBoxed);
|
||||
} else {
|
||||
do_check_true(!f.source.isBlackBoxed)
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let unBlackBoxResponse = yield unBlackBox(sourceClient);
|
||||
do_check_true(!sourceClient.isBlackBoxed);
|
||||
|
||||
// Test that we can step into `doStuff` again.
|
||||
yield runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, BLACK_BOXED_URL);
|
||||
do_check_eq(aLocation.line, 2);
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.source.isBlackBoxed));
|
||||
}
|
||||
);
|
||||
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
||||
function evalCode() {
|
||||
Components.utils.evalInSandbox(
|
||||
"" + function doStuff(k) { // line 1
|
||||
let arg = 15; // line 2 - Step in here
|
||||
@ -53,11 +106,11 @@ function test_black_box()
|
||||
"" + function runTest() { // line 1
|
||||
doStuff( // line 2 - Break here
|
||||
function (n) { // line 3 - Step through `doStuff` to here
|
||||
debugger; // line 5
|
||||
} // line 6
|
||||
); // line 7
|
||||
} // line 8
|
||||
+ "\n debugger;", // line 9
|
||||
debugger; // line 4
|
||||
} // line 5
|
||||
); // line 6
|
||||
} + "\n" // line 7
|
||||
+ "debugger;", // line 8
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
SOURCE_URL,
|
||||
@ -65,110 +118,28 @@ function test_black_box()
|
||||
);
|
||||
}
|
||||
|
||||
function test_black_box_default() {
|
||||
gThreadClient.getSources(function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should be able to get sources.");
|
||||
const runTest = Task.async(function* (onSteppedLocation, onDebuggerStatementFrames) {
|
||||
let packet = yield executeOnNextTickAndWaitForPause(gDebuggee.runTest,
|
||||
gClient);
|
||||
do_check_eq(packet.why.type, "breakpoint");
|
||||
|
||||
let sourceClient = gThreadClient.source(
|
||||
aResponse.sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
|
||||
do_check_true(!sourceClient.isBlackBoxed,
|
||||
"By default the source is not black boxed.");
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
yield stepIn(gClient, gThreadClient);
|
||||
|
||||
// Test that we can step into `doStuff` when we are not black boxed.
|
||||
runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, BLACK_BOXED_URL,
|
||||
"Should step into `doStuff`.");
|
||||
do_check_eq(aLocation.line, 2,
|
||||
"Should step into `doStuff`.");
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.source.isBlackBoxed));
|
||||
},
|
||||
test_black_boxing.bind(null, sourceClient)
|
||||
);
|
||||
});
|
||||
}
|
||||
const location = yield getCurrentLocation();
|
||||
onSteppedLocation(location);
|
||||
|
||||
function test_black_boxing(aSourceClient) {
|
||||
aSourceClient.blackBox(function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should not get an error black boxing.");
|
||||
do_check_true(aSourceClient.isBlackBoxed,
|
||||
"The source client should report itself as black boxed correctly.");
|
||||
packet = yield resumeAndWaitForPause(gClient, gThreadClient);
|
||||
do_check_eq(packet.why.type, "debuggerStatement");
|
||||
|
||||
// Test that we step through `doStuff` when we are black boxed and its frame
|
||||
// doesn't show up.
|
||||
runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, SOURCE_URL,
|
||||
"Should step through `doStuff`.");
|
||||
do_check_eq(aLocation.line, 3,
|
||||
"Should step through `doStuff`.");
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
for (let f of aFrames) {
|
||||
if (f.where.url == BLACK_BOXED_URL) {
|
||||
do_check_true(f.source.isBlackBoxed, "Should be black boxed");
|
||||
} else {
|
||||
do_check_true(!f.source.isBlackBoxed, "Should not be black boxed")
|
||||
}
|
||||
}
|
||||
},
|
||||
test_unblack_boxing.bind(null, aSourceClient)
|
||||
);
|
||||
});
|
||||
}
|
||||
let { frames } = yield getFrames(gThreadClient, 0, 100);
|
||||
onDebuggerStatementFrames(frames);
|
||||
|
||||
function test_unblack_boxing(aSourceClient) {
|
||||
aSourceClient.unblackBox(function (aResponse) {
|
||||
do_check_true(!aResponse.error, "Should not get an error un-black boxing");
|
||||
do_check_true(!aSourceClient.isBlackBoxed, "The source is not black boxed.");
|
||||
return resume(gThreadClient);
|
||||
});
|
||||
|
||||
// Test that we can step into `doStuff` again.
|
||||
runTest(
|
||||
function onSteppedLocation(aLocation) {
|
||||
do_check_eq(aLocation.url, BLACK_BOXED_URL,
|
||||
"Should step into `doStuff`.");
|
||||
do_check_eq(aLocation.line, 2,
|
||||
"Should step into `doStuff`.");
|
||||
},
|
||||
function onDebuggerStatementFrames(aFrames) {
|
||||
do_check_true(!aFrames.some(f => f.source.isBlackBoxed));
|
||||
},
|
||||
finishClient.bind(null, gClient)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function runTest(aOnSteppedLocation, aOnDebuggerStatementFrames, aFinishedCallback) {
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
gClient.addOneTimeListener("paused", function () {
|
||||
gClient.addOneTimeListener("paused", function () {
|
||||
getCurrentLocation(function (aLocation) {
|
||||
aOnSteppedLocation(aLocation);
|
||||
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
gThreadClient.getFrames(0, 100, function ({frames}) {
|
||||
aOnDebuggerStatementFrames(frames);
|
||||
gThreadClient.resume(aFinishedCallback);
|
||||
});
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
});
|
||||
gThreadClient.stepIn();
|
||||
});
|
||||
gThreadClient.stepIn();
|
||||
});
|
||||
|
||||
gDebuggee.runTest();
|
||||
}
|
||||
|
||||
function getCurrentLocation(aCallback) {
|
||||
gThreadClient.getFrames(0, 1, function ({frames, error}) {
|
||||
do_check_true(!error, "Should not get an error: " + error);
|
||||
let [{where}] = frames;
|
||||
aCallback(where);
|
||||
});
|
||||
}
|
||||
const getCurrentLocation = Task.async(function* () {
|
||||
const response = yield getFrames(gThreadClient, 0, 1);
|
||||
return response.frames[0].where;
|
||||
});
|
||||
|
@ -291,7 +291,7 @@ add_task(function* test_state() {
|
||||
let state = barrier.state[0];
|
||||
do_print("State: " + JSON.stringify(barrier.state, null, "\t"));
|
||||
Assert.equal(state.filename, filename);
|
||||
Assert.equal(state.lineNumber, lineNumber + 2);
|
||||
Assert.equal(state.lineNumber, lineNumber + 1);
|
||||
Assert.equal(state.name, BLOCKER_NAME);
|
||||
|
||||
deferred.resolve();
|
||||
|
Loading…
Reference in New Issue
Block a user