Bug 849071 - Create some kind of chrome to turn source mapping on/off in the debugger, r=vporof

This commit is contained in:
Panos Astithas 2013-04-16 18:00:33 +03:00
Родитель 3400505bb7
Коммит d3e7c334ed
8 изменённых файлов: 286 добавлений и 3 удалений

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

@ -253,9 +253,7 @@ let DebuggerController = {
if (aCallback) {
aCallback();
}
}, {
useSourceMaps: Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled")
});
}, { useSourceMaps: Prefs.sourceMapsEnabled });
},
/**
@ -299,6 +297,29 @@ let DebuggerController = {
if (aCallback) {
aCallback();
}
}, { useSourceMaps: Prefs.sourceMapsEnabled });
},
/**
* Detach and reattach to the thread actor with useSourceMaps true, blow
* away old scripts and get sources again.
*/
reconfigureThread: function DC_reconfigureThread(aUseSourceMaps) {
this.client.reconfigureThread(aUseSourceMaps, (aResponse) => {
if (aResponse.error) {
let msg = "Couldn't reconfigure thread: " + aResponse.message;
Cu.reportError(msg);
dumpn(msg);
return;
}
// Update the source list widget.
DebuggerView.Sources.empty();
SourceUtils.clearCache();
this.SourceScripts._handleTabNavigation();
// Update the stack frame list.
this.activeThread._clearFrames();
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
});
},
@ -1659,6 +1680,7 @@ let Prefs = new ViewHelpers.Prefs("devtools.debugger", {
variablesSortingEnabled: ["Bool", "ui.variables-sorting-enabled"],
variablesOnlyEnumVisible: ["Bool", "ui.variables-only-enum-visible"],
variablesSearchboxVisible: ["Bool", "ui.variables-searchbox-visible"],
sourceMapsEnabled: ["Bool", "source-maps-enabled"],
remoteHost: ["Char", "remote-host"],
remotePort: ["Int", "remote-port"],
remoteAutoConnect: ["Bool", "remote-autoconnect"],

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

@ -187,6 +187,7 @@ function OptionsView() {
this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
this._toggleShowVariablesOnlyEnum = this._toggleShowVariablesOnlyEnum.bind(this);
this._toggleShowVariablesFilterBox = this._toggleShowVariablesFilterBox.bind(this);
this._toggleShowOriginalSource = this._toggleShowOriginalSource.bind(this);
}
OptionsView.prototype = {
@ -201,11 +202,13 @@ OptionsView.prototype = {
this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
this._showVariablesOnlyEnumItem = document.getElementById("show-vars-only-enum");
this._showVariablesFilterBoxItem = document.getElementById("show-vars-filter-box");
this._showOriginalSourceItem = document.getElementById("show-original-source");
this._pauseOnExceptionsItem.setAttribute("checked", Prefs.pauseOnExceptions);
this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
this._showVariablesOnlyEnumItem.setAttribute("checked", Prefs.variablesOnlyEnumVisible);
this._showVariablesFilterBoxItem.setAttribute("checked", Prefs.variablesSearchboxVisible);
this._showOriginalSourceItem.setAttribute("checked", Prefs.sourceMapsEnabled);
},
/**
@ -262,10 +265,21 @@ OptionsView.prototype = {
this._showVariablesFilterBoxItem.getAttribute("checked") == "true";
},
/**
* Listener handling the 'show original source' menuitem command.
*/
_toggleShowOriginalSource: function DVO__toggleShowOriginalSource() {
let pref = Prefs.sourceMapsEnabled =
this._showOriginalSourceItem.getAttribute("checked") == "true";
DebuggerController.reconfigureThread(pref);
},
_button: null,
_pauseOnExceptionsItem: null,
_showPanesOnStartupItem: null,
_showVariablesOnlyEnumItem: null,
_showOriginalSourceItem: null,
_showVariablesFilterBoxItem: null
};

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

@ -64,6 +64,8 @@
oncommand="DebuggerView.Options._toggleShowVariablesOnlyEnum()"/>
<command id="toggleShowVariablesFilterBox"
oncommand="DebuggerView.Options._toggleShowVariablesFilterBox()"/>
<command id="toggleShowOriginalSource"
oncommand="DebuggerView.Options._toggleShowOriginalSource()"/>
</commandset>
<popupset id="debuggerPopupset">
@ -160,6 +162,11 @@
label="&debuggerUI.showVarsFilter;"
accesskey="&debuggerUI.showVarsFilter.key;"
command="toggleShowVariablesFilterBox"/>
<menuitem id="show-original-source"
type="checkbox"
label="&debuggerUI.showOriginalSource;"
accesskey="&debuggerUI.showOriginalSource.key;"
command="toggleShowOriginalSource"/>
</menupopup>
</popupset>

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

@ -97,6 +97,7 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_progress-listener-bug.js \
browser_dbg_chrome-debugging.js \
browser_dbg_source_maps-01.js \
browser_dbg_source_maps-02.js \
head.js \
helpers.js \
$(NULL)

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

@ -0,0 +1,203 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we can toggle between the original and generated sources.
*/
const TAB_URL = EXAMPLE_URL + "binary_search.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gPrevPref = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
gPrevPref = Services.prefs.getBoolPref(
"devtools.debugger.source-maps-enabled");
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", true);
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown(aEvent) {
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
// Show original sources should be already enabled.
is(gPrevPref, false,
"The source maps functionality should be disabled by default.");
is(gDebugger.Prefs.sourceMapsEnabled, true,
"The source maps pref should be true from startup.");
is(gDebugger.DebuggerView.Options._showOriginalSourceItem.getAttribute("checked"),
"true", "Source maps should be enabled from startup. ")
ok(aEvent.detail.url.indexOf(".coffee") != -1,
"The debugger should show the source mapped coffee script file.");
ok(aEvent.detail.url.indexOf(".js") == -1,
"The debugger should not show the generated js script file.");
ok(gDebugger.editor.getText().search(/isnt/) != -1,
"The debugger's editor should have the coffee script source displayed.");
ok(gDebugger.editor.getText().search(/function/) == -1,
"The debugger's editor should not have the JS source displayed.");
testToggleGeneratedSource();
});
});
}
function testToggleGeneratedSource() {
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown(aEvent) {
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
is(gDebugger.Prefs.sourceMapsEnabled, false,
"The source maps pref should have been set to false.");
is(gDebugger.DebuggerView.Options._showOriginalSourceItem.getAttribute("checked"),
"false", "Source maps should be enabled from startup. ")
ok(aEvent.detail.url.indexOf(".coffee") == -1,
"The debugger should not show the source mapped coffee script file.");
ok(aEvent.detail.url.indexOf(".js") != -1,
"The debugger should show the generated js script file.");
ok(gDebugger.editor.getText().search(/isnt/) == -1,
"The debugger's editor should have the coffee script source displayed.");
ok(gDebugger.editor.getText().search(/function/) != -1,
"The debugger's editor should not have the JS source displayed.");
testSetBreakpoint();
});
// Disable source maps.
gDebugger.DebuggerView.Options._showOriginalSourceItem.setAttribute("checked",
"false");
gDebugger.DebuggerView.Options._toggleShowOriginalSource();
}
function testSetBreakpoint() {
let { activeThread } = gDebugger.DebuggerController;
activeThread.setBreakpoint({
url: EXAMPLE_URL + "binary_search.js",
line: 7
}, function (aResponse, bpClient) {
ok(!aResponse.error,
"Should be able to set a breakpoint in a JavaScript file.");
testHitBreakpoint();
});
}
function testHitBreakpoint() {
let { activeThread } = gDebugger.DebuggerController;
activeThread.resume(function (aResponse) {
ok(!aResponse.error, "Shouldn't get an error resuming");
is(aResponse.type, "resumed", "Type should be 'resumed'");
activeThread.addOneTimeListener("framesadded", function (aEvent, aPacket) {
// Make sure that we have JavaScript stack frames.
let frames = gDebugger.DebuggerView.StackFrames._container._list;
let childNodes = frames.childNodes;
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Correct number of frames.");
ok(frames.querySelector("#stackframe-0 .dbg-stackframe-details")
.getAttribute("value").search(/js/),
"First frame should be a JS frame.");
waitForCaretPos(6, testToggleOnPause);
});
// This will cause the breakpoint to be hit, and put us back in the paused
// stated.
executeSoon(function() {
gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
});
});
}
function testToggleOnPause() {
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown(aEvent) {
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
is(gDebugger.Prefs.sourceMapsEnabled, true,
"The source maps pref should have been set to true.");
is(gDebugger.DebuggerView.Options._showOriginalSourceItem.getAttribute("checked"),
"true", "Source maps should be enabled. ")
ok(aEvent.detail.url.indexOf(".coffee") != -1,
"The debugger should show the source mapped coffee script file.");
ok(aEvent.detail.url.indexOf(".js") == -1,
"The debugger should not show the generated js script file.");
ok(gDebugger.editor.getText().search(/isnt/) != -1,
"The debugger's editor should not have the coffee script source displayed.");
ok(gDebugger.editor.getText().search(/function/) == -1,
"The debugger's editor should have the JS source displayed.");
// Make sure that we have coffee script stack frames.
let frames = gDebugger.DebuggerView.StackFrames._container._list;
let childNodes = frames.childNodes;
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Correct number of frames.");
ok(frames.querySelector("#stackframe-0 .dbg-stackframe-details")
.getAttribute("value").search(/coffee/),
"First frame should be a coffee script frame.");
waitForCaretPos(4, resumeAndFinish);
});
// Enable source maps.
gDebugger.DebuggerView.Options._showOriginalSourceItem.setAttribute("checked",
"true");
gDebugger.DebuggerView.Options._toggleShowOriginalSource();
}
function resumeAndFinish()
{
let { activeThread } = gDebugger.DebuggerController;
activeThread.resume(function (aResponse) {
ok(!aResponse.error, "Shouldn't get an error resuming");
is(aResponse.type, "resumed", "Type should be 'resumed'");
closeDebuggerAndFinish();
});
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gDebugger.DebuggerView.editor.getCaretPosition().line != number) {
return;
}
is(gDebugger.DebuggerView.editor.getCaretPosition().line, number,
"The right line is focused.")
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
registerCleanupFunction(function() {
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", false);
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gPrevPref = null;
});

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

@ -65,6 +65,12 @@
<!ENTITY debuggerUI.showOnlyEnum "Show only enumerable properties">
<!ENTITY debuggerUI.showOnlyEnum.key "P">
<!-- LOCALIZATION NOTE (debuggerUI.showOriginalSource): This is the label for
- the checkbox that toggles the display of original or sourcemap-derived
- sources. -->
<!ENTITY debuggerUI.showOriginalSource "Show original sources">
<!ENTITY debuggerUI.showOriginalSource.key "O">
<!-- LOCALIZATION NOTE (debuggerUI.searchPanelTitle): This is the text that
- appears in the filter panel popup as a description. -->
<!ENTITY debuggerUI.searchPanelTitle "Operators">

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

@ -486,6 +486,23 @@ DebuggerClient.prototype = {
});
},
/**
* Reconfigure a thread actor.
*
* @param boolean aUseSourceMaps
* A flag denoting whether to use source maps or not.
* @param function aOnResponse
* Called with the response packet.
*/
reconfigureThread: function DC_reconfigureThread(aUseSourceMaps, aOnResponse) {
let packet = {
to: this.activeThread._actor,
type: "reconfigure",
options: { useSourceMaps: aUseSourceMaps }
};
this.request(packet, aOnResponse);
},
/**
* Release an object actor.
*

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

@ -253,6 +253,18 @@ ThreadActor.prototype = {
};
},
onReconfigure: function TA_onReconfigure(aRequest) {
if (this.state == "exited") {
return { error: "wrongState" };
}
update(this._options, aRequest.options || {});
// Clear existing sources, so they can be recreated on next access.
this._sources = null;
return {};
},
/**
* Pause the debuggee, by entering a nested event loop, and return a 'paused'
* packet to the client.
@ -1281,6 +1293,7 @@ ThreadActor.prototype = {
ThreadActor.prototype.requestTypes = {
"attach": ThreadActor.prototype.onAttach,
"detach": ThreadActor.prototype.onDetach,
"reconfigure": ThreadActor.prototype.onReconfigure,
"resume": ThreadActor.prototype.onResume,
"clientEvaluate": ThreadActor.prototype.onClientEvaluate,
"frames": ThreadActor.prototype.onFrames,