Bug 901098 - Trace actor callsite trace type actually returns source location; r=fitzgen

This commit is contained in:
Jake Bailey 2013-08-02 17:26:31 -07:00
parent 05183e06ae
commit 0dec37b416
3 changed files with 95 additions and 39 deletions

View File

@ -442,10 +442,14 @@ TraceTypes.register("name", TraceTypes.Events.enterFrame, function({ frame }) {
: "(" + frame.type + ")";
});
TraceTypes.register("callsite", TraceTypes.Events.enterFrame, function({ frame }) {
TraceTypes.register("location", TraceTypes.Events.enterFrame, function({ frame }) {
if (!frame.script) {
return undefined;
}
// We should return the location of the start of the script, but
// Debugger.Script does not provide complete start locations
// (bug 901138). Instead, return the current offset (the location of
// the first statement in the function).
return {
url: frame.script.url,
line: frame.script.getOffsetLine(frame.offset),
@ -453,6 +457,18 @@ TraceTypes.register("callsite", TraceTypes.Events.enterFrame, function({ frame }
};
});
TraceTypes.register("callsite", TraceTypes.Events.enterFrame, function({ frame }) {
let older = frame.older;
if (!older || !older.script) {
return undefined;
}
return {
url: older.script.url,
line: older.script.getOffsetLine(older.offset),
column: getOffsetColumn(older.offset, older.script)
};
});
TraceTypes.register("time", TraceTypes.Events.enterFrame, timeSinceTraceStarted);
TraceTypes.register("time", TraceTypes.Events.exitFrame, timeSinceTraceStarted);

View File

@ -2,8 +2,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Simple tests for "callsite", "time", "parameterNames", "arguments",
* and "return" trace types.
* Simple tests for "location", "callsite", "time", "parameterNames",
* "arguments", and "return" trace types.
*/
let {defer} = devtools.require("sdk/core/promise");
@ -28,6 +28,29 @@ function run_test()
do_test_pending();
}
function check_number(value, name)
{
do_check_eq(typeof value, "number", name + ' should be a number');
do_check_true(!isNaN(value), name + ' should be a number');
}
function check_location(actual, expected, name)
{
do_check_eq(typeof actual, "object",
name + ' missing expected source location');
check_number(actual.line, name + ' line');
check_number(actual.column, name + ' column');
do_check_eq(actual.url, expected.url,
name + ' location should have url ' + expected.url);
do_check_eq(actual.line, expected.line,
name + ' location should have source line of ' + expected.line);
do_check_eq(actual.column, expected.column,
name + ' location should have source column of ' + expected.line);
}
function test_enter_exit_frame()
{
let packets = [];
@ -35,32 +58,30 @@ function test_enter_exit_frame()
gTraceClient.addListener("enteredFrame", function(aEvent, aPacket) {
do_check_eq(aPacket.type, "enteredFrame",
'enteredFrame response should have type "enteredFrame"');
do_check_eq(typeof aPacket.sequence, "number",
'enteredFrame response should have sequence number');
do_check_true(!isNaN(aPacket.sequence),
'enteredFrame sequence should be a number');
do_check_eq(typeof aPacket.name, "string",
'enteredFrame response should have function name');
do_check_eq(typeof aPacket.callsite, "object",
'enteredFrame response should have callsite');
do_check_eq(typeof aPacket.time, "number",
'enteredFrame response should have time');
do_check_true(!isNaN(aPacket.time),
'enteredFrame time should be a number');
do_check_eq(typeof aPacket.location, "object",
'enteredFrame response should have source location');
check_number(aPacket.sequence, 'enteredFrame sequence');
check_number(aPacket.time, 'enteredFrame time');
check_number(aPacket.location.line, 'enteredFrame source line');
check_number(aPacket.location.column, 'enteredFrame source column');
if (aPacket.callsite) {
check_number(aPacket.callsite.line, 'enteredFrame callsite line');
check_number(aPacket.callsite.column, 'enteredFrame callsite column');
}
packets[aPacket.sequence] = aPacket;
});
gTraceClient.addListener("exitedFrame", function(aEvent, aPacket) {
do_check_eq(aPacket.type, "exitedFrame",
'exitedFrame response should have type "exitedFrame"');
do_check_eq(typeof aPacket.sequence, "number",
'exitedFrame response should have sequence number');
do_check_true(!isNaN(aPacket.sequence),
'exitedFrame sequence should be a number');
do_check_eq(typeof aPacket.time, "number",
'exitedFrame response should have time');
do_check_true(!isNaN(aPacket.time),
'exitedFrame time should be a number');
check_number(aPacket.sequence, 'exitedFrame sequence');
check_number(aPacket.time, 'exitedFrame time');
packets[aPacket.sequence] = aPacket;
});
@ -68,28 +89,42 @@ function test_enter_exit_frame()
.then(eval_code)
.then(stop_trace)
.then(function() {
do_check_eq(packets[2].name, "foo",
'Third packet in sequence should be entry to "foo" frame');
let url = getFileUrl("tracerlocations.js");
do_check_eq(typeof packets[2].parameterNames, "object",
check_location(packets[0].location, { url: url, line: 1, column: 0 },
'global entry packet');
do_check_eq(packets[1].name, "foo",
'Second packet in sequence should be entry to "foo" frame');
// foo's definition is at tracerlocations.js:3:0, but
// Debugger.Script does not provide complete definition
// locations (bug 901138). tracerlocations.js:4:2 is the first
// statement in the function (used as an approximation).
check_location(packets[1].location, { url: url, line: 4, column: 2 },
'foo source');
check_location(packets[1].callsite, { url: url, line: 8, column: 0 },
'foo callsite');
do_check_eq(typeof packets[1].parameterNames, "object",
'foo entry packet should have parameterNames');
do_check_eq(packets[2].parameterNames.length, 1,
do_check_eq(packets[1].parameterNames.length, 1,
'foo should have only one formal parameter');
do_check_eq(packets[2].parameterNames[0], "x",
do_check_eq(packets[1].parameterNames[0], "x",
'foo should have formal parameter "x"');
do_check_eq(typeof packets[2].arguments, "object",
do_check_eq(typeof packets[1].arguments, "object",
'foo entry packet should have arguments');
do_check_true(Array.isArray(packets[2].arguments),
do_check_true(Array.isArray(packets[1].arguments),
'foo entry packet arguments should be an array');
do_check_eq(packets[2].arguments.length, 1,
do_check_eq(packets[1].arguments.length, 1,
'foo should have only one actual parameter');
do_check_eq(packets[2].arguments[0], 42,
do_check_eq(packets[1].arguments[0], 42,
'foo should have actual parameter 42');
do_check_eq(typeof packets[3].return, "string",
do_check_eq(typeof packets[2].return, "string",
'Fourth packet in sequence should be exit from "foo" frame');
do_check_eq(packets[3].return, "bar",
do_check_eq(packets[2].return, "bar",
'foo should return "bar"');
finishClient(gClient);
@ -100,7 +135,7 @@ function start_trace()
{
let deferred = defer();
gTraceClient.startTrace(
["name", "callsite", "time", "parameterNames", "arguments", "return"],
["name", "location", "callsite", "time", "parameterNames", "arguments", "return"],
null,
function() { deferred.resolve(); });
return deferred.promise;
@ -108,12 +143,9 @@ function start_trace()
function eval_code()
{
gDebuggee.eval("(" + function() {
function foo(x) {
return "bar";
}
foo(42);
} + ")()");
let code = readFile("tracerlocations.js");
Components.utils.evalInSandbox(code, gDebuggee, "1.8",
getFileUrl("tracerlocations.js"), 1);
}
function stop_trace()

View File

@ -0,0 +1,8 @@
// For JS Tracer tests dealing with source locations.
function foo(x) {
x += 6;
return "bar";
}
foo(42);