зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1183325
- Allow use of debugger shortcut keys when split console has focus;r=bgrins
--HG-- extra : commitid : AqeVkKWIGnh
This commit is contained in:
Родитель
54d10e513e
Коммит
2932cac017
|
@ -706,7 +706,10 @@ StackFrames.prototype = {
|
|||
}
|
||||
|
||||
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
|
||||
DebuggerView.editor.focus();
|
||||
// Focus the editor, but don't steal focus from the split console.
|
||||
if (!DebuggerController._toolbox.isSplitConsoleFocused()) {
|
||||
DebuggerView.editor.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,15 @@ DebuggerPanel.prototype = {
|
|||
this._toolbox.on("host-changed", this.handleHostChanged);
|
||||
this.target.on("thread-paused", this.highlightWhenPaused);
|
||||
this.target.on("thread-resumed", this.unhighlightWhenResumed);
|
||||
// Add keys from this document's keyset to the toolbox, so they
|
||||
// can work when the split console is focused.
|
||||
let keysToClone = ["resumeKey", "resumeKey2", "stepOverKey",
|
||||
"stepOverKey2", "stepInKey", "stepInKey2",
|
||||
"stepOutKey", "stepOutKey2"];
|
||||
for (let key of keysToClone) {
|
||||
let elm = this.panelWin.document.getElementById(key);
|
||||
this._toolbox.useKeyWithSplitConsole(elm, "jsdebugger");
|
||||
}
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
|
|
|
@ -101,6 +101,7 @@ support-files =
|
|||
doc_script-switching-01.html
|
||||
doc_script-switching-02.html
|
||||
doc_split-console-paused-reload.html
|
||||
doc_step-many-statements.html
|
||||
doc_step-out.html
|
||||
doc_terminate-on-tab-close.html
|
||||
doc_watch-expressions.html
|
||||
|
@ -573,3 +574,5 @@ skip-if = e10s && debug
|
|||
skip-if = e10s && debug
|
||||
[browser_dbg_WorkerActor.attachThread.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_split-console-keypress.js]
|
||||
skip-if = e10s && debug
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* When the split console is focused and the debugger is open,
|
||||
* debugger shortcut keys like F11 should work
|
||||
*/
|
||||
const TAB_URL = EXAMPLE_URL + "doc_step-many-statements.html";
|
||||
|
||||
function test() {
|
||||
let gDebugger, gToolbox, gThreadClient, gTab, gPanel;
|
||||
initDebugger(TAB_URL).then(([aTab,debuggeeWin,aPanel]) => {
|
||||
gPanel = aPanel;
|
||||
gDebugger = aPanel.panelWin;
|
||||
gToolbox = gDevTools.getToolbox(aPanel.target);
|
||||
gTab = aTab;
|
||||
gThreadClient = gDebugger.DebuggerController.activeThread;
|
||||
waitForSourceShown(aPanel, TAB_URL).then(testConsole);
|
||||
});
|
||||
let testConsole = Task.async(function *() {
|
||||
// We need to open the split console (with an ESC keypress),
|
||||
// then get the script into a paused state by pressing a button in the page,
|
||||
// ensure focus is in the split console,
|
||||
// synthesize a few keys - important ones we share listener for are
|
||||
// "resumeKey", "stepOverKey", "stepInKey", "stepOutKey"
|
||||
// then check that
|
||||
// * The input cursor remains in the console's input box
|
||||
// * The paused state is as expected
|
||||
// * the debugger cursor is where we want it
|
||||
let jsterm = yield getSplitConsole(gToolbox, gDebugger);
|
||||
// The console is now open (if not make the test fail already)
|
||||
ok(gToolbox.splitConsole, "Split console is shown.");
|
||||
|
||||
// Information for sub-tests. When 'key' is synthesized 'keyRepeat' times,
|
||||
// cursor should be at 'caretLine' of this test..
|
||||
let stepTests = [
|
||||
{key: 'VK_F11', keyRepeat: 1, caretLine: 16},
|
||||
{key: 'VK_F11', keyRepeat: 2, caretLine: 18},
|
||||
{key: 'VK_F11', keyRepeat: 2, caretLine: 26},
|
||||
{key: 'VK_F10', keyRepeat: 1, caretLine: 18},
|
||||
{key: 'VK_F11', keyRepeat: 1, caretLine: 19},
|
||||
{key: 'VK_F11', keyRepeat: 5, caretLine: 29},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 1, caretLine: 32},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 32},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 20}
|
||||
];
|
||||
// Trigger script that stops at debugger statement
|
||||
executeSoon(() => generateMouseClickInTab(gTab,
|
||||
"content.document.getElementById('start')"));
|
||||
yield waitForPause(gThreadClient);
|
||||
|
||||
// Focus the console and add event listener to track whether it loses focus
|
||||
// (Must happen after generateMouseClickInTab() call)
|
||||
let consoleLostFocus = false;
|
||||
jsterm.inputNode.focus();
|
||||
jsterm.inputNode.addEventListener('blur', () => {consoleLostFocus = true;});
|
||||
|
||||
is(gThreadClient.paused, true,
|
||||
"Should be paused at debugger statement.");
|
||||
// As long as we have test work to do..
|
||||
for (let i = 0, thisTest; thisTest = stepTests[i]; i++) {
|
||||
// First we send another key event if required by the test
|
||||
while (thisTest.keyRepeat > 0) {
|
||||
thisTest.keyRepeat --;
|
||||
let keyMods = thisTest.modifier === 'Shift' ? {shiftKey:true} : {};
|
||||
executeSoon(() => {EventUtils.synthesizeKey(thisTest.key, keyMods)});
|
||||
yield waitForPause(gThreadClient);
|
||||
}
|
||||
|
||||
// We've sent the required number of keys
|
||||
// Here are the conditions we're interested in: paused state,
|
||||
// cursor still in console (tested later), caret correct in editor
|
||||
is(gThreadClient.paused, true,
|
||||
"Should still be paused");
|
||||
//ok(isCaretPos(gPanel, thisTest.caretLine),
|
||||
// "Test " + i + ": CaretPos at line " + thisTest.caretLine);
|
||||
ok(isDebugPos(gPanel, thisTest.caretLine),
|
||||
"Test " + i + ": DebugPos at line " + thisTest.caretLine);
|
||||
}
|
||||
// Did focus go missing while we were stepping?
|
||||
is(consoleLostFocus, false, "Console input should not lose focus");
|
||||
// We're done with the tests in the stepTests array
|
||||
// Last key we test is "resume"
|
||||
executeSoon(() => EventUtils.synthesizeKey('VK_F8', {}));
|
||||
|
||||
// We reset the variable tracking loss of focus to test the resume case
|
||||
consoleLostFocus = false;
|
||||
|
||||
gPanel.target.on("thread-resumed", () => {
|
||||
is(gThreadClient.paused, false,
|
||||
"Should not be paused after resume");
|
||||
// Final test: did we preserve console inputNode focus during resume?
|
||||
is(consoleLostFocus, false, "Resume - console should keep focus");
|
||||
closeDebuggerAndFinish(gPanel);
|
||||
});
|
||||
});
|
||||
|
||||
function getSplitConsole(toolbox, theDebugger) {
|
||||
return new Promise(resolve => {
|
||||
toolbox.once("webconsole-ready", () => {
|
||||
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
|
||||
resolve(jsterm);
|
||||
});
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, theDebugger);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
// We don't want the open split console to confuse other tests..
|
||||
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Debugger test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<button id="start">Start!</button>
|
||||
|
||||
<script type="text/javascript">
|
||||
function normal(aArg) {
|
||||
debugger;
|
||||
var r = 10;
|
||||
var a = squareAndOne(r);
|
||||
var b = squareUntil(r, 99999999999); //recurses 3 times, returns on 4th call
|
||||
var c = addUntil(r, 5, 1050); // recurses 208 times and returns on the 209th call
|
||||
return a + b + c;
|
||||
|
||||
}
|
||||
|
||||
function squareAndOne(arg){
|
||||
return (arg * arg) + 1;
|
||||
}
|
||||
function squareUntil(arg, limit){
|
||||
if(arg * arg >= limit){
|
||||
return arg * arg;
|
||||
}else{
|
||||
return squareUntil(arg * arg, limit);
|
||||
}
|
||||
}
|
||||
|
||||
function addUntil(arg1, arg2, limit){
|
||||
if(arg1 + arg2 > limit){
|
||||
return arg1 + arg2;
|
||||
}else{
|
||||
return addUntil(arg1 + arg2, arg2, limit);
|
||||
}
|
||||
}
|
||||
|
||||
var normalBtn = document.getElementById("start");
|
||||
normalBtn.addEventListener("click", normal, false);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -71,6 +71,7 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
|
|||
[browser_toolbox_theme_registration.js]
|
||||
[browser_toolbox_options_enable_serviceworkers_testing.js]
|
||||
[browser_toolbox_selected_tool_unavailable.js]
|
||||
[browser_toolbox_split_console.js]
|
||||
|
||||
# We want this test to run for mochitest-dt as well, so we include it here:
|
||||
[../../../../browser/base/content/test/general/browser_parsable_css.js]
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that these toolbox split console APIs work:
|
||||
// * toolbox.useKeyWithSplitConsole()
|
||||
// * toolbox.isSplitConsoleFocused
|
||||
|
||||
let gToolbox = null;
|
||||
let panelWin = null;
|
||||
|
||||
const URL = "data:text/html;charset=utf8,test split console key delegation";
|
||||
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
add_task(function*() {
|
||||
let tab = yield addTab(URL);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
gToolbox = yield gDevTools.showToolbox(target, "inspector");
|
||||
panelWin = gToolbox.getPanel("inspector").panelWin;
|
||||
|
||||
yield gToolbox.openSplitConsole();
|
||||
yield testIsSplitConsoleFocused();
|
||||
yield testUseKeyWithSplitConsole();
|
||||
yield testUseKeyWithSplitConsoleWrongTool();
|
||||
|
||||
yield cleanup();
|
||||
});
|
||||
|
||||
function* testIsSplitConsoleFocused() {
|
||||
yield gToolbox.openSplitConsole();
|
||||
// The newly opened split console should have focus
|
||||
ok(gToolbox.isSplitConsoleFocused(), "Split console is focused");
|
||||
panelWin.focus();
|
||||
ok(!gToolbox.isSplitConsoleFocused(), "Split console is no longer focused");
|
||||
}
|
||||
|
||||
// A key bound to the selected tool should trigger it's command
|
||||
function* testUseKeyWithSplitConsole() {
|
||||
let commandCalled = false;
|
||||
|
||||
let keyElm = panelWin.document.createElementNS(XULNS, "key");
|
||||
keyElm.setAttribute("keycode", "VK_F3");
|
||||
keyElm.addEventListener("command", () => {commandCalled = true}, false);
|
||||
panelWin.document.getElementsByTagName('keyset')[0].appendChild(keyElm);
|
||||
|
||||
info("useKeyWithSplitConsole on inspector while inspector is focused");
|
||||
gToolbox.useKeyWithSplitConsole(keyElm, "inspector");
|
||||
|
||||
info("synthesizeKey with the console focused");
|
||||
let consoleInput = gToolbox.getPanel("webconsole").hud.jsterm.inputNode;
|
||||
consoleInput.focus();
|
||||
synthesizeKeyElement(keyElm);
|
||||
|
||||
ok(commandCalled, "Shortcut key should trigger the command");
|
||||
}
|
||||
|
||||
// A key bound to a *different* tool should not trigger it's command
|
||||
function* testUseKeyWithSplitConsoleWrongTool() {
|
||||
let commandCalled = false;
|
||||
|
||||
let keyElm = panelWin.document.createElementNS(XULNS, "key");
|
||||
keyElm.setAttribute("keycode", "VK_F4");
|
||||
keyElm.addEventListener("command", () => {commandCalled = true}, false);
|
||||
panelWin.document.getElementsByTagName('keyset')[0].appendChild(keyElm);
|
||||
|
||||
info("useKeyWithSplitConsole on jsdebugger while inspector is focused");
|
||||
gToolbox.useKeyWithSplitConsole(keyElm, "jsdebugger");
|
||||
|
||||
info("synthesizeKey with the console focused");
|
||||
let consoleInput = gToolbox.getPanel("webconsole").hud.jsterm.inputNode;
|
||||
consoleInput.focus();
|
||||
synthesizeKeyElement(keyElm);
|
||||
|
||||
ok(!commandCalled, "Shortcut key shouldn't trigger the command");
|
||||
}
|
||||
|
||||
function* cleanup() {
|
||||
// We don't want the open split console to confuse other tests..
|
||||
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
|
||||
yield gToolbox.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
gToolbox = panelWin = null;
|
||||
}
|
|
@ -328,6 +328,17 @@ Toolbox.prototype = {
|
|||
get splitConsole() {
|
||||
return this._splitConsole;
|
||||
},
|
||||
/**
|
||||
* Get the focused state of the split console
|
||||
*/
|
||||
isSplitConsoleFocused: function() {
|
||||
if (!this._splitConsole) {
|
||||
return false;
|
||||
}
|
||||
let focusedWin = Services.focus.focusedWindow;
|
||||
return focusedWin && focusedWin ===
|
||||
this.doc.querySelector("#toolbox-panel-iframe-webconsole").contentWindow;
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the toolbox
|
||||
|
@ -483,6 +494,28 @@ Toolbox.prototype = {
|
|||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add a shortcut key that should work when a split console
|
||||
* has focus to the toolbox.
|
||||
*
|
||||
* @param {element} keyElement
|
||||
* They <key> XUL element describing the shortcut key
|
||||
* @param {string} whichTool
|
||||
* The tool the key belongs to. The corresponding command
|
||||
* will only trigger if this tool is active.
|
||||
*/
|
||||
useKeyWithSplitConsole: function(keyElement, whichTool) {
|
||||
let cloned = keyElement.cloneNode();
|
||||
cloned.setAttribute("oncommand", "void(0)");
|
||||
cloned.removeAttribute("command");
|
||||
cloned.addEventListener("command", (e) => {
|
||||
// Only forward the command if the tool is active
|
||||
if (this.currentToolId === whichTool && this.isSplitConsoleFocused()) {
|
||||
keyElement.doCommand();
|
||||
}
|
||||
}, true);
|
||||
this.doc.getElementById("toolbox-keyset").appendChild(cloned);
|
||||
},
|
||||
|
||||
_addReloadKeys: function() {
|
||||
[
|
||||
|
|
Загрузка…
Ссылка в новой задаче