diff --git a/browser/devtools/webconsole/test/Makefile.in b/browser/devtools/webconsole/test/Makefile.in index 84cb0cc3303a..2441e4c9daab 100644 --- a/browser/devtools/webconsole/test/Makefile.in +++ b/browser/devtools/webconsole/test/Makefile.in @@ -132,6 +132,7 @@ MOCHITEST_BROWSER_FILES = \ browser_bug_871156_ctrlw_close_tab.js \ browser_console_private_browsing.js \ browser_console_nsiconsolemessage.js \ + browser_webconsole_bug_817834_add_edited_input_to_history.js \ head.js \ $(NULL) diff --git a/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js b/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js new file mode 100644 index 000000000000..2f075a3a4719 --- /dev/null +++ b/browser/devtools/webconsole/test/browser_webconsole_bug_817834_add_edited_input_to_history.js @@ -0,0 +1,61 @@ +/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* ***** BEGIN LICENSE BLOCK ***** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + * + * Contributor(s): + * zmgmoz + * + * ***** END LICENSE BLOCK ***** */ + +// Test that user input that is not submitted in the command line input is not +// lost after navigating in history. +// See https://bugzilla.mozilla.org/show_bug.cgi?id=817834 + +function test() { + addTab("data:text/html;charset=utf-8,Web Console test for bug 817834"); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); + openConsole(null, testEditedInputHistory); + }, true); +} + +function testEditedInputHistory(HUD) { + let jsterm = HUD.jsterm; + let inputNode = jsterm.inputNode; + ok(!inputNode.value, "inputNode.value is empty"); + is(inputNode.selectionStart, 0); + is(inputNode.selectionEnd, 0); + + jsterm.setInputValue('"first item"'); + EventUtils.synthesizeKey("VK_UP", {}); + is(inputNode.value, '"first item"', "null test history up"); + EventUtils.synthesizeKey("VK_DOWN", {}); + is(inputNode.value, '"first item"', "null test history down"); + + jsterm.execute(); + is(inputNode.value, "", "cleared input line after submit"); + + jsterm.setInputValue('"editing input 1"'); + EventUtils.synthesizeKey("VK_UP", {}); + is(inputNode.value, '"first item"', "test history up"); + EventUtils.synthesizeKey("VK_DOWN", {}); + is(inputNode.value, '"editing input 1"', + "test history down restores in-progress input"); + + jsterm.setInputValue('"second item"'); + jsterm.execute(); + jsterm.setInputValue('"editing input 2"'); + EventUtils.synthesizeKey("VK_UP", {}); + is(inputNode.value, '"second item"', "test history up"); + EventUtils.synthesizeKey("VK_UP", {}); + is(inputNode.value, '"first item"', "test history up"); + EventUtils.synthesizeKey("VK_DOWN", {}); + is(inputNode.value, '"second item"', "test history down"); + EventUtils.synthesizeKey("VK_DOWN", {}); + is(inputNode.value, '"editing input 2"', + "test history down restores new in-progress input again"); + + executeSoon(finishTest); +} diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js index e9bd387068aa..8e6ac70716ad 100644 --- a/browser/devtools/webconsole/webconsole.js +++ b/browser/devtools/webconsole/webconsole.js @@ -2683,8 +2683,14 @@ function JSTerm(aWebConsoleFrame) this.lastCompletion = { value: null }; this.history = []; - this.historyIndex = 0; - this.historyPlaceHolder = 0; // this.history.length; + + // Holds the number of entries in history. This value is incremented in + // this.execute(). + this.historyIndex = 0; // incremented on this.execute() + + // Holds the index of the history entry that the user is currently viewing. + // This is reset to this.history.length when this.execute() is invoked. + this.historyPlaceHolder = 0; this._objectActorsInVariablesViews = new Map(); this._keyPress = this.keyPress.bind(this); @@ -2954,8 +2960,10 @@ JSTerm.prototype = { let options = { frame: this.SELECTED_FRAME }; this.requestEvaluation(aExecuteString, options).then(onResult, onResult); - this.history.push(aExecuteString); - this.historyIndex++; + // Append a new value in the history of executed code, or overwrite the most + // recent entry. The most recent entry may contain the last edited input + // value that was not evaluated yet. + this.history[this.historyIndex++] = aExecuteString; this.historyPlaceHolder = this.history.length; this.setInputValue(""); this.clearCompletion(); @@ -3937,27 +3945,26 @@ JSTerm.prototype = { if (this.historyPlaceHolder <= 0) { return false; } - let inputVal = this.history[--this.historyPlaceHolder]; - if (inputVal){ - this.setInputValue(inputVal); + + // Save the current input value as the latest entry in history, only if + // the user is already at the last entry. + // Note: this code does not store changes to items that are already in + // history. + if (this.historyPlaceHolder+1 == this.historyIndex) { + this.history[this.historyIndex] = this.inputNode.value || ""; } + + this.setInputValue(inputVal); } // Down Arrow key else if (aDirection == HISTORY_FORWARD) { - if (this.historyPlaceHolder == this.history.length - 1) { - this.historyPlaceHolder ++; - this.setInputValue(""); - } - else if (this.historyPlaceHolder >= (this.history.length)) { + if (this.historyPlaceHolder >= (this.history.length-1)) { return false; } - else { - let inputVal = this.history[++this.historyPlaceHolder]; - if (inputVal){ - this.setInputValue(inputVal); - } - } + + let inputVal = this.history[++this.historyPlaceHolder]; + this.setInputValue(inputVal); } else { throw new Error("Invalid argument 0");