Bug 1463128 - Expose setInputValue and getInputValue at hud level; r=Honza.
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Wed, 27 Feb 2019 10:09:35 +0000
changeset 519307 63ca9c12292c99d7c54d9078d30ed195ae44c67d
parent 519306 3991d2150835c782c7e09178906296ac63b794e5
child 519308 d9fd8225a95f9a83186d4e39a94da62b9d3b83a3
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersHonza
bugs1463128
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1463128 - Expose setInputValue and getInputValue at hud level; r=Honza. Now that the JsTerm is a React component, we shouldn't let external consumers have to get the instance in order to perform some actions on the console input. We start with the most used actions, setInputValue and getInputValue, and might extend that in the future. Differential Revision: https://phabricator.services.mozilla.com/D20685
devtools/client/inspector/markup/markup-context-menu.js
devtools/client/inspector/test/browser_inspector_menu-04-use-in-console.js
devtools/client/shared/webpack/shims/jsterm-stub.js
devtools/client/webconsole/components/App.js
devtools/client/webconsole/components/JSTerm.js
devtools/client/webconsole/components/ReverseSearchInput.js
devtools/client/webconsole/test/mochitest/head.js
devtools/client/webconsole/utils/context-menu.js
devtools/client/webconsole/webconsole-wrapper.js
devtools/client/webconsole/webconsole.js
testing/talos/talos/tests/devtools/addon/content/tests/webconsole/autocomplete.js
--- a/devtools/client/inspector/markup/markup-context-menu.js
+++ b/devtools/client/inspector/markup/markup-context-menu.js
@@ -319,32 +319,31 @@ class MarkupContextMenu {
    * Use in Console.
    *
    * Takes the currently selected node in the inspector and assigns it to a
    * temp variable on the content window.  Also opens the split console and
    * autofills it with the temp variable.
    */
   _useInConsole() {
     this.toolbox.openSplitConsole().then(() => {
-      const panel = this.toolbox.getPanel("webconsole");
-      const jsterm = panel.hud.jsterm;
+      const {hud} = this.toolbox.getPanel("webconsole");
 
       const evalString = `{ let i = 0;
         while (window.hasOwnProperty("temp" + i) && i < 1000) {
           i++;
         }
         window["temp" + i] = $0;
         "temp" + i;
       }`;
 
       const options = {
         selectedNodeActor: this.selection.nodeFront.actorID,
       };
-      jsterm.requestEvaluation(evalString, options).then((res) => {
-        jsterm.setInputValue(res.result);
+      hud.jsterm.requestEvaluation(evalString, options).then((res) => {
+        hud.setInputValue(res.result);
         this.inspector.emit("console-var-ready");
       });
     });
   }
 
   _buildA11YMenuItem(menu) {
     if (!(this.selection.isElementNode() || this.selection.isTextNode()) ||
         !Services.prefs.getBoolPref("devtools.accessibility.enabled")) {
--- a/devtools/client/inspector/test/browser_inspector_menu-04-use-in-console.js
+++ b/devtools/client/inspector/test/browser_inspector_menu-04-use-in-console.js
@@ -23,27 +23,27 @@ add_task(async function() {
     const menuItem = allMenuItems.find(i => i.id === "node-menu-useinconsole");
     menuItem.click();
 
     await inspector.once("console-var-ready");
 
     const hud = toolbox.getPanel("webconsole").hud;
     const jsterm = hud.jsterm;
 
-    is(jsterm.getInputValue(), "temp0", "first console variable is named temp0");
+    is(hud.getInputValue(), "temp0", "first console variable is named temp0");
 
     let result = await jsterm.execute();
     isnot(result.textContent.indexOf('<p id="console-var">'), -1,
           "variable temp0 references correct node");
 
     await selectNode("#console-var-multi", inspector);
     menuItem.click();
     await inspector.once("console-var-ready");
 
-    is(jsterm.getInputValue(), "temp1", "second console variable is named temp1");
+    is(hud.getInputValue(), "temp1", "second console variable is named temp1");
 
     result = await jsterm.execute();
     isnot(result.textContent.indexOf('<p id="console-var-multi">'), -1,
           "variable temp1 references correct node");
 
     hud.ui.wrapper.dispatchClearHistory();
   }
 });
--- a/devtools/client/shared/webpack/shims/jsterm-stub.js
+++ b/devtools/client/shared/webpack/shims/jsterm-stub.js
@@ -43,33 +43,33 @@ JSTerm.prototype = {
    * Sets the value of the input field (command line), and resizes the field to
    * fit its contents. This method is preferred over setting "inputNode.value"
    * directly, because it correctly resizes the field.
    *
    * @param string newValue
    *        The new value to set.
    * @returns void
    */
-  setInputValue(newValue) {
+  _setValue(newValue) {
     this.inputNode.value = newValue;
     // this.resizeInput();
   },
 
   /**
    * Gets the value from the input field
    * @returns string
    */
-  getInputValue() {
+  _getValue() {
     return this.inputNode.value || "";
   },
 
   execute(executeString) {
     return new Promise(resolve => {
       // attempt to execute the content of the inputNode
-      executeString = executeString || this.getInputValue();
+      executeString = executeString || this._getValue();
       if (!executeString) {
         return;
       }
 
       const message = new ConsoleCommand({
         messageText: executeString,
       });
       this.ui.proxy.dispatchMessageAdd(message);
@@ -90,17 +90,17 @@ JSTerm.prototype = {
       };
 
       const options = {
         frame: this.SELECTED_FRAME,
         selectedNodeActor: selectedNodeActor,
       };
 
       this.requestEvaluation(executeString, options).then(onResult, onResult);
-      this.setInputValue("");
+      this._setValue("");
     });
   },
 
   /**
    * Request a JavaScript string evaluation from the server.
    *
    * @param string str
    *        String to execute.
--- a/devtools/client/webconsole/components/App.js
+++ b/devtools/client/webconsole/components/App.js
@@ -239,17 +239,19 @@ class App extends Component {
           }),
           JSTerm({
             webConsoleUI,
             serviceContainer,
             onPaste: this.onPaste,
             codeMirrorEnabled: jstermCodeMirror,
           }),
           ReverseSearchInput({
-            webConsoleUI,
+            setInputValue: serviceContainer.setInputValue,
+            focusInput: serviceContainer.focusInput,
+            evaluateInput: serviceContainer.evaluateInput,
             initialValue: reverseSearchInitialValue,
           })
         ),
         SideBar({
           serviceContainer,
         }),
         ConfirmDialog({
           webConsoleUI,
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -196,17 +196,17 @@ class JSTerm extends Component {
           tabIndex: "0",
           viewportMargin: Infinity,
           disableSearchAddon: true,
           extraKeys: {
             "Enter": () => {
               // No need to handle shift + Enter as it's natively handled by CodeMirror.
 
               const hasSuggestion = this.hasAutocompletionSuggestion();
-              if (!hasSuggestion && !Debugger.isCompilableUnit(this.getInputValue())) {
+              if (!hasSuggestion && !Debugger.isCompilableUnit(this._getValue())) {
                 // incomplete statement
                 return "CodeMirror.Pass";
               }
 
               if (hasSuggestion) {
                 return this.acceptProposedCompletion();
               }
 
@@ -324,17 +324,17 @@ class JSTerm extends Component {
             },
 
             "Home": () => {
               if (this.autocompletePopup.isOpen) {
                 this.autocompletePopup.selectItemAtIndex(0);
                 return null;
               }
 
-              if (!this.getInputValue()) {
+              if (!this._getValue()) {
                 this.webConsoleUI.outputScroller.scrollTop = 0;
                 return null;
               }
 
               if (this.getAutoCompletionText()) {
                 this.clearCompletion();
               }
 
@@ -343,17 +343,17 @@ class JSTerm extends Component {
 
             "End": () => {
               if (this.autocompletePopup.isOpen) {
                 this.autocompletePopup.selectItemAtIndex(
                   this.autocompletePopup.itemCount - 1);
                 return null;
               }
 
-              if (!this.getInputValue()) {
+              if (!this._getValue()) {
                 const {outputScroller} = this.webConsoleUI;
                 outputScroller.scrollTop = outputScroller.scrollHeight;
                 return null;
               }
 
               if (this.getAutoCompletionText()) {
                 this.clearCompletion();
               }
@@ -402,17 +402,17 @@ class JSTerm extends Component {
       ? this.inputNode.getBoundingClientRect().height - this.inputNode.clientHeight
       : 0;
 
     // Update the character and chevron width needed for the popup offset calculations.
     this._inputCharWidth = this._getInputCharWidth();
     this._paddingInlineStart = this.editor ? null : this._getInputPaddingInlineStart();
 
     this.webConsoleUI.window.addEventListener("blur", this._blurEventHandler);
-    this.lastInputValue && this.setInputValue(this.lastInputValue);
+    this.lastInputValue && this._setValue(this.lastInputValue);
   }
 
   componentWillReceiveProps(nextProps) {
     this.imperativeUpdate(nextProps);
   }
 
   shouldComponentUpdate(nextProps) {
     // XXX: For now, everything is handled in an imperative way and we
@@ -572,32 +572,32 @@ class JSTerm extends Component {
     this.webConsoleUI.wrapper.dispatchMessagesAdd(wrappedResults);
   }
 
   /**
    * Execute a string. Execution happens asynchronously in the content process.
    *
    * @param {String} executeString
    *        The string you want to execute. If this is not provided, the current
-   *        user input is used - taken from |this.getInputValue()|.
+   *        user input is used - taken from |this._getValue()|.
    * @returns {Promise}
    *          Resolves with the message once the result is displayed.
    */
   async execute(executeString) {
     // attempt to execute the content of the inputNode
-    executeString = executeString || this.getInputValue();
+    executeString = executeString || this._getValue();
     if (!executeString) {
       return null;
     }
 
     // Append executed expression into the history list.
     this.props.appendToHistory(executeString);
 
     WebConsoleUtils.usageCount++;
-    this.setInputValue("");
+    this._setValue("");
     this.clearCompletion();
 
     let selectedNodeActor = null;
     const inspectorSelection = this.webConsoleUI.hud.getInspectorSelection();
     if (inspectorSelection && inspectorSelection.nodeFront) {
       selectedNodeActor = inspectorSelection.nodeFront.actorID;
     }
 
@@ -712,17 +712,17 @@ class JSTerm extends Component {
    * Sets the value of the input field (command line), and resizes the field to
    * fit its contents. This method is preferred over setting "inputNode.value"
    * directly, because it correctly resizes the field.
    *
    * @param string newValue
    *        The new value to set.
    * @returns void
    */
-  setInputValue(newValue) {
+  _setValue(newValue) {
     newValue = newValue || "";
     this.lastInputValue = newValue;
 
     if (this.props.codeMirrorEnabled) {
       if (this.editor) {
         // In order to get the autocomplete popup to work properly, we need to set the
         // editor text and the cursor in the same operation. If we don't, the text change
         // is done before the cursor is moved, and the autocompletion call to the server
@@ -751,17 +751,17 @@ class JSTerm extends Component {
     this.resizeInput();
     this.emit("set-input-value");
   }
 
   /**
    * Gets the value from the input field
    * @returns string
    */
-  getInputValue() {
+  _getValue() {
     if (this.props.codeMirrorEnabled) {
       return this.editor ? this.editor.getText() || "" : "";
     }
 
     return this.inputNode ? this.inputNode.value || "" : "";
   }
 
   getSelectionStart() {
@@ -790,17 +790,17 @@ class JSTerm extends Component {
     this.setAutoCompletionText("");
   }
 
   /**
    * The inputNode "input" and "keyup" event handler.
    * @private
    */
   _inputEventHandler() {
-    const value = this.getInputValue();
+    const value = this._getValue();
     if (this.lastInputValue !== value) {
       this.resizeInput();
       this.props.autocompleteUpdate();
       this.lastInputValue = value;
     }
   }
 
   /**
@@ -817,17 +817,17 @@ class JSTerm extends Component {
   /**
    * The inputNode "keypress" event handler.
    *
    * @private
    * @param Event event
    */
   _keyPress(event) {
     const inputNode = this.inputNode;
-    const inputValue = this.getInputValue();
+    const inputValue = this._getValue();
     let inputUpdated = false;
 
     if (event.ctrlKey) {
       switch (event.charCode) {
         case 101:
           // control-e
           if (Services.appinfo.OS == "WINNT") {
             break;
@@ -902,17 +902,17 @@ class JSTerm extends Component {
         }
         this.clearCompletion();
         event.preventDefault();
       }
 
       return;
     } else if (event.keyCode == KeyCodes.DOM_VK_RETURN) {
       if (!this.autocompletePopup.isOpen && (
-        event.shiftKey || !Debugger.isCompilableUnit(this.getInputValue())
+        event.shiftKey || !Debugger.isCompilableUnit(this._getValue())
       )) {
         // shift return or incomplete statement
         return;
       }
     }
 
     switch (event.keyCode) {
       case KeyCodes.DOM_VK_ESCAPE:
@@ -1056,57 +1056,57 @@ class JSTerm extends Component {
       getValueFromHistory,
     } = this.props;
 
     if (!history.entries.length) {
       return false;
     }
 
     const newInputValue = getValueFromHistory(direction);
-    const expression = this.getInputValue();
+    const expression = this._getValue();
     updateHistoryPosition(direction, expression);
 
     if (newInputValue != null) {
-      this.setInputValue(newInputValue);
+      this._setValue(newInputValue);
       return true;
     }
 
     return false;
   }
 
   /**
    * Test for empty input.
    *
    * @return boolean
    */
   hasEmptyInput() {
-    return this.getInputValue() === "";
+    return this._getValue() === "";
   }
 
   /**
    * Test for multiline input.
    *
    * @return boolean
    *         True if CR or LF found in node value; else false.
    */
   hasMultilineInput() {
-    return /[\r\n]/.test(this.getInputValue());
+    return /[\r\n]/.test(this._getValue());
   }
 
   /**
    * Check if the caret is at a location that allows selecting the previous item
    * in history when the user presses the Up arrow key.
    *
    * @return boolean
    *         True if the caret is at a location that allows selecting the
    *         previous item in history when the user presses the Up arrow key,
    *         otherwise false.
    */
   canCaretGoPrevious() {
-    const inputValue = this.getInputValue();
+    const inputValue = this._getValue();
 
     if (this.editor) {
       const {line, ch} = this.editor.getCursor();
       return (line === 0 && ch === 0) || (line === 0 && ch === inputValue.length);
     }
 
     const node = this.inputNode;
     if (node.selectionStart != node.selectionEnd) {
@@ -1123,17 +1123,17 @@ class JSTerm extends Component {
    * history when the user presses the Down arrow key.
    *
    * @return boolean
    *         True if the caret is at a location that allows selecting the next
    *         item in history when the user presses the Down arrow key, otherwise
    *         false.
    */
   canCaretGoNext() {
-    const inputValue = this.getInputValue();
+    const inputValue = this._getValue();
     const multiline = /[\r\n]/.test(inputValue);
 
     if (this.editor) {
       const {line, ch} = this.editor.getCursor();
       return (!multiline && ch === 0) ||
         this.editor.getDoc()
           .getRange({line: 0, ch: 0}, {line, ch})
           .length === inputValue.length;
@@ -1186,17 +1186,17 @@ class JSTerm extends Component {
 
     if (items.length > 0) {
       const {preLabel, label} = items[0];
       let suffix = label.substring(preLabel.length);
       if (isElementAccess) {
         if (!matchProp) {
           suffix = label;
         }
-        const inputAfterCursor = this.getInputValue().substring(inputUntilCursor.length);
+        const inputAfterCursor = this._getValue().substring(inputUntilCursor.length);
         // If there's not a bracket after the cursor, add it to the completionText.
         if (!inputAfterCursor.trimLeft().startsWith("]")) {
           suffix = suffix + "]";
         }
       }
       this.setAutoCompletionText(suffix);
     }
 
@@ -1259,17 +1259,17 @@ class JSTerm extends Component {
       // If the user is performing an element access, we need to check if we should add
       // starting and ending quotes, as well as a closing bracket.
       if (isElementAccess) {
         const inputBeforeCursor = this.getInputValueBeforeCursor();
         if (inputBeforeCursor.trim().endsWith("[")) {
           suffix = label;
         }
 
-        const inputAfterCursor = this.getInputValue().substring(inputBeforeCursor.length);
+        const inputAfterCursor = this._getValue().substring(inputBeforeCursor.length);
         // If there's no closing bracket after the cursor, add it to the completionText.
         if (!inputAfterCursor.trimLeft().startsWith("]")) {
           suffix = suffix + "]";
         }
       }
       this.setAutoCompletionText(suffix);
     } else {
       this.setAutoCompletionText("");
@@ -1322,17 +1322,17 @@ class JSTerm extends Component {
       if (isElementAccess) {
         const inputBeforeCursor = this.getInputValueBeforeCursor();
         const lastOpeningBracketIndex = inputBeforeCursor.lastIndexOf("[");
         if (lastOpeningBracketIndex > -1) {
           numberOfCharsToReplaceCharsBeforeCursor =
             inputBeforeCursor.substring(lastOpeningBracketIndex + 1).length;
         }
 
-        const inputAfterCursor = this.getInputValue().substring(inputBeforeCursor.length);
+        const inputAfterCursor = this._getValue().substring(inputBeforeCursor.length);
         // If there's not a bracket after the cursor, add it.
         if (!inputAfterCursor.trimLeft().startsWith("]")) {
           completionText = completionText + "]";
         }
       }
     }
 
     this.clearCompletion();
@@ -1344,45 +1344,45 @@ class JSTerm extends Component {
 
   getInputValueBeforeCursor() {
     if (this.editor) {
       return this.editor.getDoc().getRange({line: 0, ch: 0}, this.editor.getCursor());
     }
 
     if (this.inputNode) {
       const cursor = this.inputNode.selectionStart;
-      return this.getInputValue().substring(0, cursor);
+      return this._getValue().substring(0, cursor);
     }
 
     return null;
   }
 
   /**
    * Insert a string into the console at the cursor location,
    * moving the cursor to the end of the string.
    *
    * @param {string} str
    * @param {int} numberOfCharsToReplaceCharsBeforeCursor - defaults to 0
    */
   insertStringAtCursor(str, numberOfCharsToReplaceCharsBeforeCursor = 0) {
-    const value = this.getInputValue();
+    const value = this._getValue();
     let prefix = this.getInputValueBeforeCursor();
     const suffix = value.replace(prefix, "");
 
     if (numberOfCharsToReplaceCharsBeforeCursor) {
       prefix =
         prefix.substring(0, prefix.length - numberOfCharsToReplaceCharsBeforeCursor);
     }
 
     // We need to retrieve the cursor before setting the new value.
     const editorCursor = this.editor && this.editor.getCursor();
 
     const scrollPosition = this.inputNode ? this.inputNode.parentElement.scrollTop : null;
 
-    this.setInputValue(prefix + str + suffix);
+    this._setValue(prefix + str + suffix);
 
     if (this.inputNode) {
       const newCursor = prefix.length + str.length;
       this.inputNode.selectionStart = this.inputNode.selectionEnd = newCursor;
       this.inputNode.parentElement.scrollTop = scrollPosition;
     } else if (this.editor) {
       // Set the cursor on the same line it was already at, after the autocompleted text
       this.editor.setCursor({
@@ -1451,17 +1451,17 @@ class JSTerm extends Component {
     if (this.editor) {
       const { ch, line } = this.editor.getCursor();
       const lineContent = this.editor.getLine(line);
       const textAfterCursor = lineContent.substring(ch);
       return textAfterCursor === "";
     }
 
     if (this.inputNode) {
-      const value = this.getInputValue();
+      const value = this._getValue();
       const textAfterCursor = value.substring(this.inputNode.selectionStart);
       return textAfterCursor.split("\n")[0] === "";
     }
 
     return false;
   }
 
   /**
--- a/devtools/client/webconsole/components/ReverseSearchInput.js
+++ b/devtools/client/webconsole/components/ReverseSearchInput.js
@@ -23,43 +23,45 @@ loader.lazyRequireGetter(this, "KeyCodes
 
 const Services = require("Services");
 const isMacOS = Services.appinfo.OS === "Darwin";
 
 class ReverseSearchInput extends Component {
   static get propTypes() {
     return {
       dispatch: PropTypes.func.isRequired,
-      webConsoleUI: PropTypes.object.isRequired,
+      setInputValue: PropTypes.func.isRequired,
+      focusInput: PropTypes.func.isRequired,
+      evaluateInput: PropTypes.func.isRequired,
       reverseSearchResult: PropTypes.string,
       reverseSearchTotalResults: PropTypes.number,
       reverseSearchResultPosition: PropTypes.number,
       visible: PropTypes.bool,
       initialValue: PropTypes.string,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.onInputKeyDown = this.onInputKeyDown.bind(this);
   }
 
   componentDidUpdate(prevProps) {
-    const {jsterm} = this.props.webConsoleUI;
+    const {setInputValue, focusInput} = this.props;
     if (
       prevProps.reverseSearchResult !== this.props.reverseSearchResult
       && this.props.visible
       && this.props.reverseSearchTotalResults > 0
     ) {
-      jsterm.setInputValue(this.props.reverseSearchResult);
+      setInputValue(this.props.reverseSearchResult);
     }
 
     if (prevProps.visible === true && this.props.visible === false) {
-      jsterm.focus();
+      focusInput();
     }
 
     if (
       prevProps.visible === false &&
       this.props.visible === true &&
       this.props.initialValue
     ) {
       this.inputNode.value = this.props.initialValue;
@@ -71,25 +73,25 @@ class ReverseSearchInput extends Compone
       keyCode,
       key,
       ctrlKey,
       shiftKey,
     } = event;
 
     const {
       dispatch,
-      webConsoleUI,
+      evaluateInput,
       reverseSearchTotalResults,
     } = this.props;
 
     // On Enter, we trigger an execute.
     if (keyCode === KeyCodes.DOM_VK_RETURN) {
       event.stopPropagation();
       dispatch(actions.reverseSearchInputToggle());
-      webConsoleUI.jsterm.execute();
+      evaluateInput();
       return;
     }
 
     // On Escape (and Ctrl + c on OSX), we close the reverse search input.
     if (
       keyCode === KeyCodes.DOM_VK_ESCAPE || (
         isMacOS && ctrlKey === true && key.toLowerCase() === "c"
       )
--- a/devtools/client/webconsole/test/mochitest/head.js
+++ b/devtools/client/webconsole/test/mochitest/head.js
@@ -394,27 +394,27 @@ function hasFocus(node) {
 
 /**
  * Get the value of the console input .
  *
  * @param {WebConsole} hud: The webconsole
  * @returns {String}: The value of the console input.
  */
 function getInputValue(hud) {
-  return hud.jsterm.getInputValue();
+  return hud.jsterm._getValue();
 }
 
 /**
  * Set the value of the console input .
  *
  * @param {WebConsole} hud: The webconsole
  * @param {String} value : The value to set the console input to.
  */
 function setInputValue(hud, value) {
-  return hud.jsterm.setInputValue(value);
+  return hud.jsterm._setValue(value);
 }
 
 /**
  * Set the value of the console input and its caret position, and wait for the
  * autocompletion to be updated.
  *
  * @param {WebConsole} hud: The webconsole
  * @param {String} value : The value to set the jsterm to.
--- a/devtools/client/webconsole/utils/context-menu.js
+++ b/devtools/client/webconsole/utils/context-menu.js
@@ -112,17 +112,17 @@ function createContextMenu(webConsoleUI,
         "temp" + i;
       }`;
       const options = {
         selectedObjectActor: actor,
       };
 
       webConsoleUI.jsterm.requestEvaluation(evalString, options).then((res) => {
         webConsoleUI.jsterm.focus();
-        webConsoleUI.jsterm.setInputValue(res.result);
+        webConsoleUI.hud.setInputValue(res.result);
       });
     },
   }));
 
   // Copy message or grip.
   menu.append(new MenuItem({
     id: "console-menu-copy",
     label: l10n.getStr("webconsole.menu.copyMessage.label"),
--- a/devtools/client/webconsole/webconsole-wrapper.js
+++ b/devtools/client/webconsole/webconsole-wrapper.js
@@ -149,17 +149,29 @@ class WebConsoleWrapper {
         inputHasSelection: () => {
           const {editor, inputNode} = webConsoleUI.jsterm || {};
           return editor
             ? !!editor.getSelection()
             : (inputNode && inputNode.selectionStart !== inputNode.selectionEnd);
         },
 
         getInputValue: () => {
-          return webConsoleUI.jsterm && webConsoleUI.jsterm.getInputValue();
+          return this.hud.getInputValue();
+        },
+
+        setInputValue: (value) => {
+          this.hud.setInputValue(value);
+        },
+
+        focusInput: () => {
+          return webConsoleUI.jsterm && webConsoleUI.jsterm.focus();
+        },
+
+        evaluateInput: (expression) => {
+          return webConsoleUI.jsterm && webConsoleUI.jsterm.execute(expression);
         },
 
         getInputCursor: () => {
           return webConsoleUI.jsterm && webConsoleUI.jsterm.getSelectionStart();
         },
 
         getSelectedNodeActor: () => {
           const inspectorSelection = this.hud.getInspectorSelection();
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -105,16 +105,41 @@ class WebConsole {
    * @see webconsole.js::JSTerm
    * @type object
    */
   get jsterm() {
     return this.ui ? this.ui.jsterm : null;
   }
 
   /**
+   * Get the value from the input field.
+   * @returns {String|null} returns null if there's no input.
+   */
+  getInputValue() {
+    if (!this.jsterm) {
+      return null;
+    }
+
+    return this.jsterm._getValue();
+  }
+
+  /**
+   * Sets the value of the input field (command line)
+   *
+   * @param {String} newValue: The new value to set.
+   */
+  setInputValue(newValue) {
+    if (!this.jsterm) {
+      return;
+    }
+
+    this.jsterm._setValue(newValue);
+  }
+
+  /**
    * Alias for the WebConsoleUI.setFilterState() method.
    * @see webconsole.js::WebConsoleUI.setFilterState()
    */
   setFilterState() {
     this.ui && this.ui.setFilterState.apply(this.ui, arguments);
   }
 
   /**
--- a/testing/talos/talos/tests/devtools/addon/content/tests/webconsole/autocomplete.js
+++ b/testing/talos/talos/tests/devtools/addon/content/tests/webconsole/autocomplete.js
@@ -65,12 +65,12 @@ function hideAutocompletePopup(jsterm) {
   let onPopUpClosed = jsterm.autocompletePopup.once("popup-closed");
   setJsTermValueForCompletion(jsterm, "");
   return onPopUpClosed;
 }
 
 function setJsTermValueForCompletion(jsterm, value) {
   // setInputValue does not trigger the autocompletion;
   // we need to call the `autocompleteUpdate` action in order to display the popup.
-  jsterm.setInputValue(value);
+  jsterm._setValue(value);
   jsterm.props.autocompleteUpdate();
 }