Bug 1474236 - Remove defer usage in JsTerm.js; r=Honza. draft
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Mon, 09 Jul 2018 08:59:14 +0200
changeset 816015 33524201c35d52a78de477fa3dfe9f67667e6cc5
parent 815985 a675c5d7eb76887a3e4b24548d621c9cc05a1545
push id115720
push userbmo:nchevobbe@mozilla.com
push dateTue, 10 Jul 2018 13:06:27 +0000
reviewersHonza
bugs1474236
milestone63.0a1
Bug 1474236 - Remove defer usage in JsTerm.js; r=Honza. This patch removes defer usage and now relies on async function. Functions that was using callbacks are also moved to async, since the callback only purpose was to resolve the deferred promise. MozReview-Commit-ID: 3Y7cDrS1fkm
devtools/client/webconsole/components/JSTerm.js
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -5,17 +5,16 @@
 "use strict";
 
 const {Utils: WebConsoleUtils} = require("devtools/client/webconsole/utils");
 const Services = require("Services");
 
 loader.lazyServiceGetter(this, "clipboardHelper",
                          "@mozilla.org/widget/clipboardhelper;1",
                          "nsIClipboardHelper");
-loader.lazyRequireGetter(this, "defer", "devtools/shared/defer");
 loader.lazyRequireGetter(this, "Debugger", "Debugger");
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 loader.lazyRequireGetter(this, "AutocompletePopup", "devtools/client/shared/autocomplete-popup");
 loader.lazyRequireGetter(this, "PropTypes", "devtools/client/shared/vendor/react-prop-types");
 loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
 loader.lazyRequireGetter(this, "KeyCodes", "devtools/client/shared/keycodes", true);
 loader.lazyRequireGetter(this, "Editor", "devtools/client/sourceeditor/editor");
 loader.lazyRequireGetter(this, "Telemetry", "devtools/client/shared/telemetry");
@@ -315,29 +314,26 @@ class JSTerm extends Component {
       this.inputNode.focus();
     }
   }
 
   /**
    * The JavaScript evaluation response handler.
    *
    * @private
-   * @param function [callback]
-   *        Optional function to invoke when the evaluation result is added to
-   *        the output.
    * @param object response
    *        The message received from the server.
    */
-  async _executeResultCallback(callback, response) {
+  async _executeResultCallback(response) {
     if (!this.hud) {
-      return;
+      return null;
     }
     if (response.error) {
       console.error("Evaluation error " + response.error + ": " + response.message);
-      return;
+      return null;
     }
     let errorMessage = response.exceptionMessage;
 
     // Wrap thrown strings in Error objects, so `throw "foo"` outputs "Error: foo"
     if (typeof response.exception === "string") {
       errorMessage = new Error(errorMessage).toString();
     }
     const result = response.result;
@@ -368,31 +364,32 @@ class JSTerm extends Component {
         case "copyValueToClipboard":
           clipboardHelper.copyString(helperResult.value);
           break;
         case "screenshotOutput":
           const { args, value } = helperResult;
           const results = await processScreenshot(this.hud.window, args, value);
           this.screenshotNotify(results);
           // early return as screenshot notify has dispatched all necessary messages
-          return;
+          return null;
       }
     }
 
     // Hide undefined results coming from JSTerm helper functions.
     if (!errorMessage && result && typeof result == "object" &&
       result.type == "undefined" &&
       helperResult && !helperHasRawOutput) {
-      callback && callback();
-      return;
+      return null;
     }
 
     if (this.hud.consoleOutput) {
-      this.hud.consoleOutput.dispatchMessageAdd(response, true).then(callback);
+      return this.hud.consoleOutput.dispatchMessageAdd(response, true);
     }
+
+    return null;
   }
 
   inspectObjectActor(objectActor) {
     this.hud.consoleOutput.dispatchMessageAdd({
       helperResult: {
         type: "inspectObject",
         object: objectActor
       }
@@ -403,29 +400,23 @@ class JSTerm extends Component {
   screenshotNotify(results) {
     const wrappedResults = results.map(result => ({ result }));
     this.hud.consoleOutput.dispatchMessagesAdd(wrappedResults);
   }
 
   /**
    * Execute a string. Execution happens asynchronously in the content process.
    *
-   * @param string [executeString]
+   * @param {String} executeString
    *        The string you want to execute. If this is not provided, the current
    *        user input is used - taken from |this.getInputValue()|.
-   * @param function [callback]
-   *        Optional function to invoke when the result is displayed.
-   *        This is deprecated - please use the promise return value instead.
-   * @returns Promise
+   * @returns {Promise}
    *          Resolves with the message once the result is displayed.
    */
-  async execute(executeString, callback) {
-    const deferred = defer();
-    const resultCallback = msg => deferred.resolve(msg);
-
+  async execute(executeString) {
     // attempt to execute the content of the inputNode
     executeString = executeString || this.getInputValue();
     if (!executeString) {
       return null;
     }
 
     // Append executed expression into the history list.
     this.props.appendToHistory(executeString);
@@ -436,32 +427,33 @@ class JSTerm extends Component {
 
     let selectedNodeActor = null;
     const inspectorSelection = this.hud.owner.getInspectorSelection();
     if (inspectorSelection && inspectorSelection.nodeFront) {
       selectedNodeActor = inspectorSelection.nodeFront.actorID;
     }
 
     const { ConsoleCommand } = require("devtools/client/webconsole/types");
-    const message = new ConsoleCommand({
+    const cmdMessage = new ConsoleCommand({
       messageText: executeString,
     });
-    this.hud.proxy.dispatchMessageAdd(message);
-
-    const onResult = this._executeResultCallback.bind(this, resultCallback);
+    this.hud.proxy.dispatchMessageAdd(cmdMessage);
 
     const options = {
       frame: this.SELECTED_FRAME,
-      selectedNodeActor: selectedNodeActor,
+      selectedNodeActor,
     };
 
     const mappedString = await this.hud.owner.getMappedExpression(executeString);
-    this.requestEvaluation(mappedString, options).then(onResult, onResult);
-
-    return deferred.promise;
+    // Even if requestEvaluation rejects (because of webConsoleClient.evaluateJSAsync),
+    // we still need to pass the error response to executeResultCallback.
+    const onEvaluated = this.requestEvaluation(mappedString, options)
+      .then(res => res, res => res);
+    const response = await onEvaluated;
+    return this._executeResultCallback(response);
   }
 
   /**
    * Request a JavaScript string evaluation from the server.
    *
    * @param string str
    *        String to execute.
    * @param object [options]
@@ -480,48 +472,37 @@ class JSTerm extends Component {
    *        in the Inspector, if such a selection exists. This is used by
    *        helper functions that can evaluate on the current selection.
    * @return object
    *         A promise object that is resolved when the server response is
    *         received.
    */
   requestEvaluation(str, options = {}) {
     const toolbox = gDevTools.getToolbox(this.hud.owner.target);
-    const deferred = defer();
 
-    function onResult(response) {
-      if (!response.error) {
-        deferred.resolve(response);
-      } else {
-        deferred.reject(response);
-      }
-    }
+    // Send telemetry event. If we are in the browser toolbox we send -1 as the
+    // toolbox session id.
+    this._telemetry.recordEvent("devtools.main", "execute_js", "webconsole", null, {
+      "lines": str.split(/\n/).length,
+      "session_id": toolbox ? toolbox.sessionId : -1
+    });
 
     let frameActor = null;
     if ("frame" in options) {
       frameActor = this.getFrameActor(options.frame);
     }
 
     const evalOptions = {
       bindObjectActor: options.bindObjectActor,
-      frameActor: frameActor,
+      frameActor,
       selectedNodeActor: options.selectedNodeActor,
       selectedObjectActor: options.selectedObjectActor,
     };
 
-    this.webConsoleClient.evaluateJSAsync(str, onResult, evalOptions);
-
-    // Send telemetry event. If we are in the browser toolbox we send -1 as the
-    // toolbox session id.
-    this._telemetry.recordEvent("devtools.main", "execute_js", "webconsole", null, {
-      "lines": str.split(/\n/).length,
-      "session_id": toolbox ? toolbox.sessionId : -1
-    });
-
-    return deferred.promise;
+    return this.webConsoleClient.evaluateJSAsync(str, null, evalOptions);
   }
 
   /**
    * Copy the object/variable by invoking the server
    * which invokes the `copy(variable)` command and makes it
    * available in the clipboard
    * @param evalString - string which has the evaluation string to be copied
    * @param options - object - Options for evaluation