Bug 877682 - blackbox sources in the debugger server via the rdp; r=dcamp,past

This commit is contained in:
Nick Fitzgerald 2013-06-11 17:23:00 +03:00
parent 92be042dbc
commit c85e0b6a3c
9 changed files with 729 additions and 22 deletions

View File

@ -3312,6 +3312,30 @@
"n_buckets": "1000", "n_buckets": "1000",
"description": "The time (in milliseconds) that it took a 'detach' request to go round trip." "description": "The time (in milliseconds) that it took a 'detach' request to go round trip."
}, },
"DEVTOOLS_DEBUGGER_RDP_LOCAL_BLACKBOX_MS": {
"kind": "exponential",
"high": "10000",
"n_buckets": "1000",
"description": "The time (in milliseconds) that it took a 'blackbox' request to go round trip."
},
"DEVTOOLS_DEBUGGER_RDP_REMOTE_BLACKBOX_MS": {
"kind": "exponential",
"high": "10000",
"n_buckets": "1000",
"description": "The time (in milliseconds) that it took a 'blackbox' request to go round trip."
},
"DEVTOOLS_DEBUGGER_RDP_LOCAL_UNBLACKBOX_MS": {
"kind": "exponential",
"high": "10000",
"n_buckets": "1000",
"description": "The time (in milliseconds) that it took an 'ublackbox' request to go round trip."
},
"DEVTOOLS_DEBUGGER_RDP_REMOTE_UNBLACKBOX_MS": {
"kind": "exponential",
"high": "10000",
"n_buckets": "1000",
"description": "The time (in milliseconds) that it took an 'unblackbox' request to go round trip."
},
"DEVTOOLS_OPTIONS_OPENED_BOOLEAN": { "DEVTOOLS_OPTIONS_OPENED_BOOLEAN": {
"kind": "boolean", "kind": "boolean",
"description": "How many times has the devtool's Options panel been opened?" "description": "How many times has the devtool's Options panel been opened?"

View File

@ -1565,11 +1565,51 @@ LongStringClient.prototype = {
*/ */
function SourceClient(aClient, aForm) { function SourceClient(aClient, aForm) {
this._form = aForm; this._form = aForm;
this._isBlackBoxed = aForm.isBlackBoxed;
this._client = aClient; this._client = aClient;
} }
SourceClient.prototype = { SourceClient.prototype = {
get _transport() { return this._client._transport; }, get _transport() this._client._transport,
get isBlackBoxed() this._isBlackBoxed,
get actor() this._form.actor,
get request() this._client.request,
/**
* Black box this SourceClient's source.
*
* @param aCallback Function
* The callback function called when we receive the response from the server.
*/
blackBox: DebuggerClient.requester({
type: "blackbox"
}, {
telemetry: "BLACKBOX",
after: function (aResponse) {
if (!aResponse.error) {
this._isBlackBoxed = true;
}
return aResponse;
}
}),
/**
* Un-black box this SourceClient's source.
*
* @param aCallback Function
* The callback function called when we receive the response from the server.
*/
unblackBox: DebuggerClient.requester({
type: "unblackbox"
}, {
telemetry: "UNBLACKBOX",
after: function (aResponse) {
if (!aResponse.error) {
this._isBlackBoxed = false;
}
return aResponse;
}
}),
/** /**
* Get a long string grip for this SourceClient's source. * Get a long string grip for this SourceClient's source.

View File

@ -327,45 +327,60 @@ ThreadActor.prototype = {
if (aRequest && aRequest.resumeLimit) { if (aRequest && aRequest.resumeLimit) {
// Bind these methods because some of the hooks are called with 'this' // Bind these methods because some of the hooks are called with 'this'
// set to the current frame. // set to the current frame.
let pauseAndRespond = this._pauseAndRespond.bind(this); let pauseAndRespond = aFrame => {
this._pauseAndRespond(aFrame, { type: "resumeLimit" });
};
let createValueGrip = this.createValueGrip.bind(this); let createValueGrip = this.createValueGrip.bind(this);
let startFrame = this._youngestFrame; let startFrame = this.youngestFrame;
let startLine; let startLine;
if (this._youngestFrame.script) { if (this.youngestFrame.script) {
let offset = this._youngestFrame.offset; let offset = this.youngestFrame.offset;
startLine = this._youngestFrame.script.getOffsetLine(offset); startLine = this.youngestFrame.script.getOffsetLine(offset);
} }
// Define the JS hook functions for stepping. // Define the JS hook functions for stepping.
let onEnterFrame = function TA_onEnterFrame(aFrame) { let onEnterFrame = aFrame => {
return pauseAndRespond(aFrame, { type: "resumeLimit" }); if (this.sources.isBlackBoxed(aFrame.script.url)) {
return undefined;
}
return pauseAndRespond(aFrame);
}; };
let thread = this;
let onPop = function TA_onPop(aCompletion) { let onPop = function TA_onPop(aCompletion) {
// onPop is called with 'this' set to the current frame. // onPop is called with 'this' set to the current frame.
if (thread.sources.isBlackBoxed(this.script.url)) {
return undefined;
}
// Note that we're popping this frame; we need to watch for // Note that we're popping this frame; we need to watch for
// subsequent step events on its caller. // subsequent step events on its caller.
this.reportedPop = true; this.reportedPop = true;
return pauseAndRespond(this, { type: "resumeLimit" }); return pauseAndRespond(this);
} };
let onStep = function TA_onStep() { let onStep = function TA_onStep() {
// onStep is called with 'this' set to the current frame. // onStep is called with 'this' set to the current frame.
if (thread.sources.isBlackBoxed(this.script.url)) {
return undefined;
}
// If we've changed frame or line, then report that. // If we've changed frame or line, then report that.
if (this !== startFrame || if (this !== startFrame ||
(this.script && (this.script &&
this.script.getOffsetLine(this.offset) != startLine)) { this.script.getOffsetLine(this.offset) != startLine)) {
return pauseAndRespond(this, { type: "resumeLimit" }); return pauseAndRespond(this);
} }
// Otherwise, let execution continue. // Otherwise, let execution continue.
return undefined; return undefined;
} };
let steppingType = aRequest.resumeLimit.type; let steppingType = aRequest.resumeLimit.type;
if (["step", "next", "finish"].indexOf(steppingType) == -1) { if (["step", "next", "finish"].indexOf(steppingType) == -1) {
@ -430,7 +445,7 @@ ThreadActor.prototype = {
// save our frame now to be restored after eval returns. // save our frame now to be restored after eval returns.
// XXX: or we could just start using dbg.getNewestFrame() now that it // XXX: or we could just start using dbg.getNewestFrame() now that it
// works as expected. // works as expected.
let youngest = this._youngestFrame; let youngest = this.youngestFrame;
// Put ourselves back in the running state and inform the client. // Put ourselves back in the running state and inform the client.
let resumedPacket = this._resumed(); let resumedPacket = this._resumed();
@ -459,7 +474,7 @@ ThreadActor.prototype = {
let count = aRequest.count; let count = aRequest.count;
// Find the starting frame... // Find the starting frame...
let frame = this._youngestFrame; let frame = this.youngestFrame;
let i = 0; let i = 0;
while (frame && (i < start)) { while (frame && (i < start)) {
frame = frame.older; frame = frame.older;
@ -811,7 +826,7 @@ ThreadActor.prototype = {
*/ */
_requestFrame: function TA_requestFrame(aFrameID) { _requestFrame: function TA_requestFrame(aFrameID) {
if (!aFrameID) { if (!aFrameID) {
return this._youngestFrame; return this.youngestFrame;
} }
if (this._framePool.has(aFrameID)) { if (this._framePool.has(aFrameID)) {
@ -845,7 +860,7 @@ ThreadActor.prototype = {
// Save the pause frame (if any) as the youngest frame for // Save the pause frame (if any) as the youngest frame for
// stack viewing. // stack viewing.
this._youngestFrame = aFrame; this.youngestFrame = aFrame;
// Create the actor pool that will hold the pause actor and its // Create the actor pool that will hold the pause actor and its
// children. // children.
@ -908,7 +923,7 @@ ThreadActor.prototype = {
this._pausePool = null; this._pausePool = null;
this._pauseActor = null; this._pauseActor = null;
this._youngestFrame = null; this.youngestFrame = null;
return { from: this.actorID, type: "resumed" }; return { from: this.actorID, type: "resumed" };
}, },
@ -1185,7 +1200,7 @@ ThreadActor.prototype = {
* The exception that was thrown in the debugger code. * The exception that was thrown in the debugger code.
*/ */
uncaughtExceptionHook: function TA_uncaughtExceptionHook(aException) { uncaughtExceptionHook: function TA_uncaughtExceptionHook(aException) {
dumpn("Got an exception:" + aException); dumpn("Got an exception: " + aException.message + "\n" + aException.stack);
}, },
/** /**
@ -1196,6 +1211,9 @@ ThreadActor.prototype = {
* The stack frame that contained the debugger statement. * The stack frame that contained the debugger statement.
*/ */
onDebuggerStatement: function TA_onDebuggerStatement(aFrame) { onDebuggerStatement: function TA_onDebuggerStatement(aFrame) {
if (this.sources.isBlackBoxed(aFrame.script.url)) {
return undefined;
}
return this._pauseAndRespond(aFrame, { type: "debuggerStatement" }); return this._pauseAndRespond(aFrame, { type: "debuggerStatement" });
}, },
@ -1209,6 +1227,9 @@ ThreadActor.prototype = {
* The exception that was thrown. * The exception that was thrown.
*/ */
onExceptionUnwind: function TA_onExceptionUnwind(aFrame, aValue) { onExceptionUnwind: function TA_onExceptionUnwind(aFrame, aValue) {
if (this.sources.isBlackBoxed(aFrame.script.url)) {
return undefined;
}
try { try {
let packet = this._paused(aFrame); let packet = this._paused(aFrame);
if (!packet) { if (!packet) {
@ -1456,7 +1477,8 @@ SourceActor.prototype = {
form: function SA_form() { form: function SA_form() {
return { return {
actor: this.actorID, actor: this.actorID,
url: this._url url: this._url,
isBlackBoxed: this.threadActor.sources.isBlackBoxed(this.url)
// TODO bug 637572: introductionScript // TODO bug 637572: introductionScript
}; };
}, },
@ -1508,11 +1530,39 @@ SourceActor.prototype = {
"message": "Could not load the source for " + this._url + "." "message": "Could not load the source for " + this._url + "."
}; };
}); });
},
/**
* Handler for the "blackbox" packet.
*/
onBlackBox: function SA_onBlackBox(aRequest) {
this.threadActor.sources.blackBox(this.url);
let packet = {
from: this.actorID
};
if (this.threadActor.state == "paused"
&& this.threadActor.youngestFrame
&& this.threadActor.youngestFrame.script.url == this.url) {
packet.pausedInSource = true;
}
return packet;
},
/**
* Handler for the "unblackbox" packet.
*/
onUnblackBox: function SA_onUnblackBox(aRequest) {
this.threadActor.sources.unblackBox(this.url);
return {
from: this.actorID
};
} }
}; };
SourceActor.prototype.requestTypes = { SourceActor.prototype.requestTypes = {
"source": SourceActor.prototype.onSource "source": SourceActor.prototype.onSource,
"blackbox": SourceActor.prototype.onBlackBox,
"unblackbox": SourceActor.prototype.onUnblackBox
}; };
@ -2059,6 +2109,7 @@ FrameActor.prototype = {
if (this.frame.script) { if (this.frame.script) {
form.where = { url: this.frame.script.url, form.where = { url: this.frame.script.url,
line: this.frame.script.getOffsetLine(this.frame.offset) }; line: this.frame.script.getOffsetLine(this.frame.offset) };
form.isBlackBoxed = this.threadActor.sources.isBlackBoxed(this.frame.script.url)
} }
if (!this.frame.older) { if (!this.frame.older) {
@ -2157,6 +2208,10 @@ BreakpointActor.prototype = {
* The stack frame that contained the breakpoint. * The stack frame that contained the breakpoint.
*/ */
hit: function BA_hit(aFrame) { hit: function BA_hit(aFrame) {
if (this.threadActor.sources.isBlackBoxed(this.location.url)) {
return undefined;
}
// TODO: add the rest of the breakpoints on that line (bug 676602). // TODO: add the rest of the breakpoints on that line (bug 676602).
let reason = { type: "breakpoint", actors: [ this.actorID ] }; let reason = { type: "breakpoint", actors: [ this.actorID ] };
return this.threadActor._pauseAndRespond(aFrame, reason, (aPacket) => { return this.threadActor._pauseAndRespond(aFrame, reason, (aPacket) => {
@ -2494,8 +2549,8 @@ update(ChromeDebuggerActor.prototype, {
* Manages the sources for a thread. Handles source maps, locations in the * Manages the sources for a thread. Handles source maps, locations in the
* sources, etc for ThreadActors. * sources, etc for ThreadActors.
*/ */
function ThreadSources(aThreadActor, aUseSourceMaps, function ThreadSources(aThreadActor, aUseSourceMaps, aAllowPredicate,
aAllowPredicate, aOnNewSource) { aOnNewSource) {
this._thread = aThreadActor; this._thread = aThreadActor;
this._useSourceMaps = aUseSourceMaps; this._useSourceMaps = aUseSourceMaps;
this._allow = aAllowPredicate; this._allow = aAllowPredicate;
@ -2513,6 +2568,12 @@ function ThreadSources(aThreadActor, aUseSourceMaps,
this._generatedUrlsByOriginalUrl = Object.create(null); this._generatedUrlsByOriginalUrl = Object.create(null);
} }
/**
* Must be a class property because it needs to persist across reloads, same as
* the breakpoint store.
*/
ThreadSources._blackBoxedSources = new Set();
ThreadSources.prototype = { ThreadSources.prototype = {
/** /**
* Return the source actor representing |aURL|, creating one if none * Return the source actor representing |aURL|, creating one if none
@ -2687,6 +2748,39 @@ ThreadSources.prototype = {
}); });
}, },
/**
* Returns true if URL for the given source is black boxed.
*
* @param aURL String
* The URL of the source which we are checking whether it is black
* boxed or not.
*/
isBlackBoxed: function TS_isBlackBoxed(aURL) {
return ThreadSources._blackBoxedSources.has(aURL);
},
/**
* Add the given source URL to the set of sources that are black boxed. If the
* thread is currently paused and we are black boxing the yougest frame's
* source, this will force a step.
*
* @param aURL String
* The URL of the source which we are black boxing.
*/
blackBox: function TS_blackBox(aURL) {
ThreadSources._blackBoxedSources.add(aURL);
},
/**
* Remove the given source URL to the set of sources that are black boxed.
*
* @param aURL String
* The URL of the source which we are no longer black boxing.
*/
unblackBox: function TS_unblackBox(aURL) {
ThreadSources._blackBoxedSources.delete(aURL);
},
/** /**
* Normalize multiple relative paths towards the base paths on the right. * Normalize multiple relative paths towards the base paths on the right.
*/ */

View File

@ -0,0 +1,178 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test basic black boxing.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_black_box();
});
});
do_test_pending();
}
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);
});
});
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
let arg = 15; // line 2 - Step in here
k(arg); // line 3
}, // line 4
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + 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
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}
function test_black_box_default() {
gThreadClient.getSources(function (aResponse) {
do_check_true(!aResponse.error, "Should be able to get sources.");
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.");
// 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.isBlackBoxed));
},
test_black_boxing.bind(null, sourceClient)
);
});
}
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.");
// 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.isBlackBoxed, "Should be black boxed");
} else {
do_check_true(!f.isBlackBoxed, "Should not be black boxed")
}
}
},
test_unblack_boxing.bind(null, aSourceClient)
);
});
}
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.");
// 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.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);
// We hit the breakpoint once more on the way out
gClient.addOneTimeListener("paused", function () {
gThreadClient.resume(aFinishedCallback);
});
gThreadClient.resume();
});
});
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);
});
}

View File

@ -0,0 +1,104 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we don't hit breakpoints in black boxed sources, and that when we
* unblack box the source again, the breakpoint hasn't disappeared and we will
* hit it again.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_black_box();
});
});
do_test_pending();
}
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: BLACK_BOXED_URL,
line: 2
}, function (aResponse) {
do_check_true(!aResponse.error, "Should be able to set breakpoint.");
gThreadClient.resume(test_black_box_breakpoint);
});
});
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
let arg = 15; // line 2 - Break here
k(arg); // line 3
}, // line 4
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + function runTest() { // line 1
doStuff( // line 2
function (n) { // line 3
debugger; // line 5
} // line 6
); // line 7
} // line 8
+ "\n debugger;", // line 9
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}
function test_black_box_breakpoint() {
gThreadClient.getSources(function ({error, sources}) {
do_check_true(!error, "Should not get an error: " + error);
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
sourceClient.blackBox(function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
do_check_eq(aPacket.why.type, "debuggerStatement",
"We should pass over the breakpoint since the source is black boxed.");
gThreadClient.resume(test_unblack_box_breakpoint.bind(null, sourceClient));
});
gDebuggee.runTest();
});
});
}
function test_unblack_box_breakpoint(aSourceClient) {
aSourceClient.unblackBox(function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
do_check_eq(aPacket.why.type, "breakpoint",
"We should hit the breakpoint again");
// We will hit the debugger statement on resume, so do this nastiness to skip over it.
gClient.addOneTimeListener(
"paused",
gThreadClient.resume.bind(
gThreadClient,
finishClient.bind(null, gClient)));
gThreadClient.resume();
});
gDebuggee.runTest();
});
}

View File

@ -0,0 +1,104 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we don't stop at debugger statements inside black boxed sources.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_black_box();
});
});
do_test_pending();
}
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: 4
}, function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gThreadClient.resume(test_black_box_dbg_statement);
});
});
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
debugger; // line 2 - Break here
k(100); // line 3
}, // line 4
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + function runTest() { // line 1
doStuff( // line 2
function (n) { // line 3
Math.abs(n); // line 4 - Break here
} // line 5
); // line 6
} // line 7
+ "\n debugger;", // line 8
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}
function test_black_box_dbg_statement() {
gThreadClient.getSources(function ({error, sources}) {
do_check_true(!error, "Should not get an error: " + error);
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
sourceClient.blackBox(function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
do_check_eq(aPacket.why.type, "breakpoint",
"We should pass over the debugger statement.");
gThreadClient.resume(test_unblack_box_dbg_statement.bind(null, sourceClient));
});
gDebuggee.runTest();
});
});
}
function test_unblack_box_dbg_statement(aSourceClient) {
aSourceClient.unblackBox(function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
do_check_eq(aPacket.why.type, "debuggerStatement",
"We should stop at the debugger statement again");
// We will hit the breakpoint on resume, so do this nastiness to skip over it.
gClient.addOneTimeListener(
"paused",
gThreadClient.resume.bind(
gThreadClient,
finishClient.bind(null, gClient)));
gThreadClient.resume();
});
gDebuggee.runTest();
});
}

View File

@ -0,0 +1,79 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test behavior of blackboxing sources we are currently paused in.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_black_box();
});
});
do_test_pending();
}
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: BLACK_BOXED_URL,
line: 2
}, function (aResponse) {
do_check_true(!aResponse.error, "Should be able to set breakpoint.");
test_black_box_paused();
});
});
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
debugger; // line 2
k(100); // line 3
}, // line 4
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + function runTest() { // line 1
doStuff( // line 2
function (n) { // line 3
n; // line 4
} // line 5
); // line 6
} // line 7
+ "\n runTest();", // line 8
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}
function test_black_box_paused() {
gThreadClient.getSources(function ({error, sources}) {
do_check_true(!error, "Should not get an error: " + error);
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
sourceClient.blackBox(function ({error, pausedInSource}) {
do_check_true(!error, "Should not get an error: " + error);
do_check_true(pausedInSource, "We should be notified that we are currently paused in this source");
finishClient(gClient);
});
});
}

View File

@ -0,0 +1,79 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test exceptions inside black boxed sources.
*/
var gDebuggee;
var gClient;
var gThreadClient;
function run_test()
{
initTestDebuggerServer();
gDebuggee = addTestGlobal("test-black-box");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-black-box", function(aResponse, aTabClient, aThreadClient) {
gThreadClient = aThreadClient;
test_black_box();
});
});
do_test_pending();
}
const BLACK_BOXED_URL = "http://example.com/blackboxme.js";
const SOURCE_URL = "http://example.com/source.js";
function test_black_box()
{
gClient.addOneTimeListener("paused", test_black_box_exception);
Components.utils.evalInSandbox(
"" + function doStuff(k) { // line 1
throw new Error("wu tang clan ain't nuthin' ta fuck wit"); // line 2
k(100); // line 3
}, // line 4
gDebuggee,
"1.8",
BLACK_BOXED_URL,
1
);
Components.utils.evalInSandbox(
"" + function runTest() { // line 1
doStuff( // line 2
function (n) { // line 3
debugger; // line 4
} // line 5
); // line 6
} // line 7
+ "\ndebugger;\n" // line 8
+ "runTest()", // line 9
gDebuggee,
"1.8",
SOURCE_URL,
1
);
}
function test_black_box_exception() {
gThreadClient.getSources(function ({error, sources}) {
do_check_true(!error, "Should not get an error: " + error);
let sourceClient = gThreadClient.source(sources.filter(s => s.url == BLACK_BOXED_URL)[0]);
sourceClient.blackBox(function ({error}) {
do_check_true(!error, "Should not get an error: " + error);
gThreadClient.pauseOnExceptions(true);
gClient.addOneTimeListener("paused", function (aEvent, aPacket) {
do_check_neq(aPacket.frame.where.url, BLACK_BOXED_URL,
"We shouldn't pause while in the black boxed source.");
finishClient(gClient);
});
gThreadClient.resume();
});
});
}

View File

@ -11,6 +11,11 @@ reason = bug 821285
[test_dbgglobal.js] [test_dbgglobal.js]
[test_dbgclient_debuggerstatement.js] [test_dbgclient_debuggerstatement.js]
[test_attach.js] [test_attach.js]
[test_blackboxing-01.js]
[test_blackboxing-02.js]
[test_blackboxing-03.js]
[test_blackboxing-04.js]
[test_blackboxing-05.js]
[test_frameactor-01.js] [test_frameactor-01.js]
[test_frameactor-02.js] [test_frameactor-02.js]
[test_frameactor-03.js] [test_frameactor-03.js]