Bug 1347894 - Remove uses of defer in devtools/client/scratchpad. r=jdescottes
authorsreeise <reeisesean@gmail.com>
Fri, 05 Oct 2018 16:19:14 +0000
changeset 488204 48715242d46a18214ccbe4692b4d77b5110268a2
parent 488203 3e75d7c78e42350683289433ff419c975d63fafc
child 488205 2d5a9a9d3baa744707c58eec07f9c20e65869d30
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersjdescottes
bugs1347894
milestone64.0a1
Bug 1347894 - Remove uses of defer in devtools/client/scratchpad. r=jdescottes Promises using defer are being replaced by new Promise and async await syntax. This is for the devtools/client/scratchpad directory. Also includes refactoring of scratchpad for async await. Differential Revision: https://phabricator.services.mozilla.com/D7247
devtools/client/scratchpad/panel.js
devtools/client/scratchpad/scratchpad.js
devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
devtools/client/scratchpad/test/head.js
--- a/devtools/client/scratchpad/panel.js
+++ b/devtools/client/scratchpad/panel.js
@@ -1,55 +1,53 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const EventEmitter = require("devtools/shared/event-emitter");
-const promise = require("promise");
-const defer = require("devtools/shared/defer");
 
 function ScratchpadPanel(iframeWindow, toolbox) {
   const { Scratchpad } = iframeWindow;
   this._toolbox = toolbox;
   this.panelWin = iframeWindow;
   this.scratchpad = Scratchpad;
 
   Scratchpad.target = this.target;
   Scratchpad.hideMenu();
 
-  const deferred = defer();
-  this._readyObserver = deferred.promise;
-  Scratchpad.addObserver({
-    onReady: function() {
-      Scratchpad.removeObserver(this);
-      deferred.resolve();
-    }
+  this._readyObserver = new Promise(resolve => {
+    Scratchpad.addObserver({
+      onReady() {
+        Scratchpad.removeObserver(this);
+        resolve();
+      }
+    });
   });
 
   EventEmitter.decorate(this);
 }
 exports.ScratchpadPanel = ScratchpadPanel;
 
 ScratchpadPanel.prototype = {
   /**
    * Open is effectively an asynchronous constructor. For the ScratchpadPanel,
    * by the time this is called, the Scratchpad will already be ready.
    */
-  open: function() {
+  open() {
     return this._readyObserver.then(() => {
       this.isReady = true;
       this.emit("ready");
       return this;
     });
   },
 
   get target() {
     return this._toolbox.target;
   },
 
-  destroy: function() {
+  destroy() {
     this.emit("destroyed");
-    return promise.resolve();
+    return Promise.resolve();
   }
 };
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -47,18 +47,16 @@ const VARIABLES_VIEW_URL = "chrome://dev
 const {require, loader} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
 
 const Editor = require("devtools/client/sourceeditor/editor");
 const TargetFactory = require("devtools/client/framework/target").TargetFactory;
 const EventEmitter = require("devtools/shared/event-emitter");
 const {DevToolsWorker} = require("devtools/shared/worker/worker");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const flags = require("devtools/shared/flags");
-const promise = require("promise");
-const defer = require("devtools/shared/defer");
 const Services = require("Services");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const { extend } = require("devtools/shared/extend");
 
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 const {NetUtil} = require("resource://gre/modules/NetUtil.jsm");
 const {ScratchpadManager} = require("resource://devtools/client/scratchpad/scratchpad-manager.jsm");
 const {OS} = require("resource://gre/modules/osfile.jsm");
@@ -474,176 +472,144 @@ var Scratchpad = {
   setText: function SP_setText(value) {
     return this.editor.setText(value);
   },
 
   /**
    * Evaluate a string in the currently desired context, that is either the
    * chrome window or the tab content window object.
    *
-   * @param string aString
+   * @param string string
    *        The script you want to evaluate.
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  evaluate: function SP_evaluate(aString) {
+  async evaluate(string) {
     let connection;
     if (this.target) {
       connection = ScratchpadTarget.consoleFor(this.target);
     } else if (this.executionContext == SCRATCHPAD_CONTEXT_CONTENT) {
       connection = ScratchpadTab.consoleFor(this.gBrowser.selectedTab);
     } else {
       connection = ScratchpadWindow.consoleFor(this.browserWindow);
     }
 
     const evalOptions = { url: this.uniqueName };
-
-    return connection.then(({ debuggerClient, webConsoleClient }) => {
-      const deferred = defer();
+    const { debuggerClient, webConsoleClient } = await connection;
+    this.debuggerClient = debuggerClient;
+    this.webConsoleClient = webConsoleClient;
+    const response = await webConsoleClient.evaluateJSAsync(string, null, evalOptions);
 
-      webConsoleClient.evaluateJSAsync(aString, aResponse => {
-        this.debuggerClient = debuggerClient;
-        this.webConsoleClient = webConsoleClient;
-        if (aResponse.error) {
-          deferred.reject(aResponse);
-        } else if (aResponse.exception !== null) {
-          deferred.resolve([aString, aResponse]);
-        } else {
-          deferred.resolve([aString, undefined, aResponse.result]);
-        }
-      }, evalOptions);
-
-      return deferred.promise;
-    });
+    if (response.error) {
+      throw new Error(response.error);
+    } else if (response.exception !== null) {
+      return [string, response];
+    } else {
+      return [string, undefined, response.result];
+    }
   },
 
   /**
    * Execute the selected text (if any) or the entire editor content in the
    * current context.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  execute: function SP_execute() {
+  execute() {
     WebConsoleUtils.usageCount++;
     const selection = this.editor.getSelection() || this.getText();
     return this.evaluate(selection);
   },
 
   /**
    * Execute the selected text (if any) or the entire editor content in the
    * current context.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  run: function SP_run() {
-    const deferred = defer();
-    const reject = aReason => deferred.reject(aReason);
-
-    this.execute().then(([aString, aError, aResult]) => {
-      const resolve = () => deferred.resolve([aString, aError, aResult]);
-
-      if (aError) {
-        this.writeAsErrorComment(aError).then(resolve, reject);
-      } else {
-        this.editor.dropSelection();
-        resolve();
-      }
-    }, reject);
-
-    return deferred.promise;
+  async run() {
+    const [string, error, result] = await this.execute();
+    if (error) {
+      await this.writeAsErrorComment(error);
+    } else {
+      this.editor.dropSelection();
+    }
+    return [string, error, result];
   },
 
   /**
    * Execute the selected text (if any) or the entire editor content in the
    * current context. The resulting object is inspected up in the sidebar.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  inspect: function SP_inspect() {
-    const deferred = defer();
-    const reject = aReason => deferred.reject(aReason);
-
-    this.execute().then(([aString, aError, aResult]) => {
-      const resolve = () => deferred.resolve([aString, aError, aResult]);
-
-      if (aError) {
-        this.writeAsErrorComment(aError).then(resolve, reject);
-      } else {
-        this.editor.dropSelection();
-        this.sidebar.open(aString, aResult).then(resolve, reject);
-      }
-    }, reject);
-
-    return deferred.promise;
+  async inspect() {
+    const [string, error, result] = await this.execute();
+    if (error) {
+      await this.writeAsErrorComment(error);
+    } else {
+      this.editor.dropSelection();
+      await this.sidebar.open(string, result);
+    }
+    return [string, error, result];
   },
 
   /**
    * Reload the current page and execute the entire editor content when
    * the page finishes loading. Note that this operation should be available
    * only in the content context.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  reloadAndRun: async function SP_reloadAndRun() {
-    const deferred = defer();
-
+  async reloadAndRun() {
     if (this.executionContext !== SCRATCHPAD_CONTEXT_CONTENT) {
       console.error(this.strings
                     .GetStringFromName("scratchpadContext.invalid"));
       return;
     }
 
     const target = await TargetFactory.forTab(this.gBrowser.selectedTab);
-    target.once("navigate", () => {
-      this.run().then(results => deferred.resolve(results));
-    });
-    target.attach().then(() => target.activeTab.reload());
-
-    return deferred.promise;
+    await target.attach();
+    const onNavigate = target.once("navigate");
+    target.activeTab.reload();
+    await onNavigate;
+    await this.run();
   },
 
   /**
    * Execute the selected text (if any) or the entire editor content in the
    * current context. The evaluation result is inserted into the editor after
    * the selected text, or at the end of the editor content if there is no
    * selected text.
    *
    * @return Promise
    *         The promise for the script evaluation result.
    */
-  display: function SP_display() {
-    const deferred = defer();
-    const reject = aReason => deferred.reject(aReason);
-
-    this.execute().then(([aString, aError, aResult]) => {
-      const resolve = () => deferred.resolve([aString, aError, aResult]);
-
-      if (aError) {
-        this.writeAsErrorComment(aError).then(resolve, reject);
-      } else if (VariablesView.isPrimitive({ value: aResult })) {
-        this._writePrimitiveAsComment(aResult).then(resolve, reject);
-      } else {
-        const objectClient = new ObjectClient(this.debuggerClient, aResult);
-        objectClient.getDisplayString(aResponse => {
-          if (aResponse.error) {
-            reportError("display", aResponse);
-            reject(aResponse);
-          } else {
-            this.writeAsComment(aResponse.displayString);
-            resolve();
-          }
-        });
-      }
-    }, reject);
-
-    return deferred.promise;
+  async display() {
+    const [string, error, result] = await this.execute();
+    if (error) {
+      await this.writeAsErrorComment(error);
+      return [string, error, result];
+    } else if (VariablesView.isPrimitive({ value: result })) {
+      await this._writePrimitiveAsComment(result);
+      return [string, error, result];
+    }
+    const objectClient = new ObjectClient(this.debuggerClient, result);
+    const response = await objectClient.getDisplayString();
+    if (response.error) {
+      reportError("display", response);
+      throw new Error(response.error);
+    } else {
+      this.writeAsComment(response.displayString);
+      return [string, error, result];
+    }
   },
 
   _prettyPrintWorker: null,
 
   /**
    * Get or create the worker that handles pretty printing.
    */
   get prettyPrintWorker() {
@@ -797,27 +763,27 @@ var Scratchpad = {
     return functionText;
   },
 
   /**
    * Evaluate the top level function that the cursor is resting in.
    *
    * @returns Promise [text, error, result]
    */
-  evalTopLevelFunction: function SP_evalTopLevelFunction() {
+  evalTopLevelFunction() {
     const text = this.getText();
     const ast = this._parseText(text);
     if (!ast) {
-      return promise.resolve([text, undefined, undefined]);
+      return Promise.resolve([text, undefined, undefined]);
     }
 
     const cursorPos = this.editor.getCursor();
     const funcStatement = this._findTopLevelFunction(ast, cursorPos);
     if (!funcStatement) {
-      return promise.resolve([text, undefined, undefined]);
+      return Promise.resolve([text, undefined, undefined]);
     }
 
     let functionText = this._getFunctionText(funcStatement, text);
 
     // TODO: This is a work around for bug 940086. It should be removed when
     // that is fixed.
     if (funcStatement.type == "FunctionDeclaration"
         && !functionText.startsWith("function ")) {
@@ -842,144 +808,132 @@ var Scratchpad = {
     return this.evaluate(functionText);
   },
 
   /**
    * Writes out a primitive value as a comment. This handles values which are
    * to be printed directly (number, string) as well as grips to values
    * (null, undefined, longString).
    *
-   * @param any aValue
+   * @param any value
    *        The value to print.
    * @return Promise
    *         The promise that resolves after the value has been printed.
    */
-  _writePrimitiveAsComment: function SP__writePrimitiveAsComment(aValue) {
-    const deferred = defer();
-
-    if (aValue.type == "longString") {
+  async _writePrimitiveAsComment(value) {
+    if (value.type == "longString") {
       const client = this.webConsoleClient;
-      client.longString(aValue).substring(0, aValue.length, aResponse => {
-        if (aResponse.error) {
-          reportError("display", aResponse);
-          deferred.reject(aResponse);
-        } else {
-          deferred.resolve(aResponse.substring);
-        }
-      });
+      const response = await client.longString(value).substring(0, value.length);
+      if (response.error) {
+        reportError("display", response);
+        throw new Error(response.error);
+      } else {
+        this.writeAsComment(response.substring);
+      }
     } else {
-      deferred.resolve(aValue.type || aValue);
+      this.writeAsComment(value.type || value);
     }
-
-    return deferred.promise.then(aComment => {
-      this.writeAsComment(aComment);
-    });
   },
 
   /**
    * Write out a value at the next line from the current insertion point.
    * The comment block will always be preceded by a newline character.
-   * @param object aValue
+   * @param object value
    *        The Object to write out as a string
    */
-  writeAsComment: function SP_writeAsComment(aValue) {
-    const value = "\n/*\n" + aValue + "\n*/";
+  writeAsComment(value) {
+    const comment = "\n/*\n" + value + "\n*/";
 
     if (this.editor.somethingSelected()) {
       const from = this.editor.getCursor("end");
-      this.editor.replaceSelection(this.editor.getSelection() + value);
-      const to = this.editor.getPosition(this.editor.getOffset(from) + value.length);
+      this.editor.replaceSelection(this.editor.getSelection() + comment);
+      const to = this.editor.getPosition(this.editor.getOffset(from) + comment.length);
       this.editor.setSelection(from, to);
       return;
     }
 
     const text = this.editor.getText();
-    this.editor.setText(text + value);
+    this.editor.setText(text + comment);
 
-    const [ from, to ] = this.editor.getPosition(text.length, (text + value).length);
+    const [ from, to ] = this.editor.getPosition(text.length, (text + comment).length);
     this.editor.setSelection(from, to);
   },
 
   /**
    * Write out an error at the current insertion point as a block comment
-   * @param object aValue
+   * @param object error
    *        The error object to write out the message and stack trace. It must
    *        contain an |exception| property with the actual error thrown, but it
    *        will often be the entire response of an evaluateJS request.
    * @return Promise
    *         The promise that indicates when writing the comment completes.
    */
-  writeAsErrorComment: function SP_writeAsErrorComment(aError) {
-    const deferred = defer();
-
-    if (VariablesView.isPrimitive({ value: aError.exception })) {
-      const error = aError.exception;
-      const type = error.type;
-      if (type == "undefined" ||
-          type == "null" ||
-          type == "Infinity" ||
-          type == "-Infinity" ||
-          type == "NaN" ||
-          type == "-0") {
-        deferred.resolve(type);
-      } else if (type == "longString") {
-        deferred.resolve(error.initial + "\u2026");
+  writeAsErrorComment(error) {
+    return new Promise(async (resolve, reject) => {
+      const exception = error.exception;
+      if (VariablesView.isPrimitive({ value: exception })) {
+        const type = exception.type;
+        if (type == "undefined" ||
+            type == "null" ||
+            type == "Infinity" ||
+            type == "-Infinity" ||
+            type == "NaN" ||
+            type == "-0") {
+          resolve(type);
+        } else if (type == "longString") {
+          resolve(exception.initial + "\u2026");
+        } else {
+          resolve(exception);
+        }
+      } else if ("preview" in exception) {
+        const stack = this._constructErrorStack(exception.preview);
+        if (typeof error.exceptionMessage == "string") {
+          resolve(error.exceptionMessage + stack);
+        } else {
+          resolve(stack);
+        }
       } else {
-        deferred.resolve(error);
-      }
-    } else if ("preview" in aError.exception) {
-      const error = aError.exception;
-      const stack = this._constructErrorStack(error.preview);
-      if (typeof aError.exceptionMessage == "string") {
-        deferred.resolve(aError.exceptionMessage + stack);
-      } else {
-        deferred.resolve(stack);
-      }
-    } else {
-      // If there is no preview information, we need to ask the server for more.
-      const objectClient = new ObjectClient(this.debuggerClient, aError.exception);
-      objectClient.getPrototypeAndProperties(aResponse => {
-        if (aResponse.error) {
-          deferred.reject(aResponse);
+        // If there is no preview information, we need to ask the server for more.
+        const objectClient = new ObjectClient(this.debuggerClient, exception);
+        const response = await objectClient.getPrototypeAndProperties();
+        if (response.error) {
+          reject(response);
           return;
         }
 
-        const { ownProperties, safeGetterValues } = aResponse;
+        const {ownProperties, safeGetterValues} = response;
         const error = Object.create(null);
 
         // Combine all the property descriptor/getter values into one object.
         for (const key of Object.keys(safeGetterValues)) {
           error[key] = safeGetterValues[key].getterValue;
         }
 
         for (const key of Object.keys(ownProperties)) {
           error[key] = ownProperties[key].value;
         }
 
         const stack = this._constructErrorStack(error);
 
         if (typeof error.message == "string") {
-          deferred.resolve(error.message + stack);
+          resolve(error.message + stack);
         } else {
-          objectClient.getDisplayString(aResponse => {
-            if (aResponse.error) {
-              deferred.reject(aResponse);
-            } else if (typeof aResponse.displayString == "string") {
-              deferred.resolve(aResponse.displayString + stack);
-            } else {
-              deferred.resolve(stack);
-            }
-          });
+          const response = await objectClient.getDisplayString();
+          if (response.error) {
+            reject(response);
+          } else if (typeof response.displayString == "string") {
+            resolve(response.displayString + stack);
+          } else {
+            resolve(stack);
+          }
         }
-      });
-    }
-
-    return deferred.promise.then(aMessage => {
-      console.error(aMessage);
-      this.writeAsComment("Exception: " + aMessage);
+      }
+    }).then((message) => {
+      console.error(message);
+      this.writeAsComment("Exception: " + message);
     });
   },
 
   /**
    * Assembles the best possible stack from the properties of the provided
    * error.
    */
   _constructErrorStack(error) {
@@ -1018,51 +972,50 @@ var Scratchpad = {
    */
   openScratchpad: function SP_openScratchpad() {
     return ScratchpadManager.openScratchpad();
   },
 
   /**
    * Export the textbox content to a file.
    *
-   * @param nsIFile aFile
+   * @param nsIFile file
    *        The file where you want to save the textbox content.
-   * @param boolean aNoConfirmation
+   * @param boolean noConfirmation
    *        If the file already exists, ask for confirmation?
-   * @param boolean aSilentError
+   * @param boolean silentError
    *        True if you do not want to display an error when file save fails,
    *        false otherwise.
-   * @param function aCallback
+   * @param function callback
    *        Optional function you want to call when file save completes. It will
    *        get the following arguments:
    *        1) the nsresult status code for the export operation.
    */
-  exportToFile: function SP_exportToFile(aFile, aNoConfirmation, aSilentError,
-                                         aCallback) {
-    if (!aNoConfirmation && aFile.exists() &&
+  async exportToFile(file, noConfirmation, silentError, callback) {
+    if (!noConfirmation && file.exists() &&
         !window.confirm(this.strings
                         .GetStringFromName("export.fileOverwriteConfirmation"))) {
       return;
     }
 
     const encoder = new TextEncoder();
     const buffer = encoder.encode(this.getText());
-    const writePromise = OS.File.writeAtomic(aFile.path, buffer, {tmpPath: aFile.path + ".tmp"});
-    writePromise.then(value => {
-      if (aCallback) {
-        aCallback.call(this, Cr.NS_OK);
+    try {
+      await OS.File.writeAtomic(file.path, buffer, {tmpPath: file.path + ".tmp"});
+      if (callback) {
+        callback.call(this, Cr.NS_OK);
       }
-    }, reason => {
-      if (!aSilentError) {
+    } catch (error) {
+      if (!silentError) {
         window.alert(this.strings.GetStringFromName("saveFile.failed"));
       }
-      if (aCallback) {
-        aCallback.call(this, Cr.NS_ERROR_UNEXPECTED);
+      if (callback) {
+        callback.call(this, Cr.NS_ERROR_UNEXPECTED);
       }
-    });
+    }
   },
 
   /**
    * Get a list of applicable charsets.
    * The best charset, defaulting to "UTF-8"
    *
    * @param string aBestCharset
    * @return array of strings
@@ -1433,35 +1386,35 @@ var Scratchpad = {
         resolve(aStatus);
       });
     });
   },
 
   /**
    * Save the textbox content to a new file.
    *
-   * @param function aCallback
+   * @param function callback
    *        Optional function you want to call when file is saved
    * @return Promise
    */
-  saveFileAs: function SP_saveFileAs(aCallback) {
+  saveFileAs(callback) {
     return new Promise(resolve => {
       const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
-      const fpCallback = aResult => {
-        if (aResult != Ci.nsIFilePicker.returnCancel) {
+      const fpCallback = result => {
+        if (result != Ci.nsIFilePicker.returnCancel) {
           this.setFilename(fp.file.path);
-          this.exportToFile(fp.file, true, false, aStatus => {
-            if (Components.isSuccessCode(aStatus)) {
+          this.exportToFile(fp.file, true, false, status => {
+            if (Components.isSuccessCode(status)) {
               this.dirty = false;
               this.setRecentFile(fp.file);
             }
-            if (aCallback) {
-              aCallback(aStatus);
+            if (callback) {
+              callback(status);
             }
-            resolve(aStatus);
+            resolve(status);
           });
         }
       };
 
       fp.init(window, this.strings.GetStringFromName("saveFileAs"),
         Ci.nsIFilePicker.modeSave);
       fp.defaultString = "scratchpad.js";
       fp.appendFilter("JavaScript Files", "*.js; *.jsm; *.json");
@@ -2039,69 +1992,66 @@ ScratchpadTab.prototype = {
   /**
    * The promise for the connection.
    */
   _connector: null,
 
   /**
    * Initialize a debugger client and connect it to the debugger server.
    *
-   * @param object aSubject
+   * @param object subject
    *        The tab or window to obtain the connection for.
    * @return Promise
    *         The promise for the result of connecting to this tab or window.
    */
-  connect: function ST_connect(aSubject) {
+  connect(subject) {
     if (this._connector) {
       return this._connector;
     }
 
-    const deferred = defer();
-    this._connector = deferred.promise;
-
-    const connectTimer = setTimeout(() => {
-      deferred.reject({
-        error: "timeout",
-        message: Scratchpad.strings.GetStringFromName("connectionTimeout"),
-      });
-    }, REMOTE_TIMEOUT);
-
-    deferred.promise.then(() => clearTimeout(connectTimer));
+    this._connector = new Promise(async (resolve, reject) => {
+      const connectTimer = setTimeout(() => {
+        reject({
+          error: "timeout",
+          message: Scratchpad.strings.GetStringFromName("connectionTimeout"),
+        });
+      }, REMOTE_TIMEOUT);
 
-    this._attach(aSubject).then(aTarget => {
-      const consoleActor = aTarget.form.consoleActor;
-      const client = aTarget.client;
-      client.attachConsole(consoleActor, [])
-        .then(([aResponse, aWebConsoleClient]) => {
-          deferred.resolve({
-            webConsoleClient: aWebConsoleClient,
-            debuggerClient: client
-          });
-        }, error => {
-          reportError("attachConsole", error);
-          deferred.reject(error);
+      const target = await this._attach(subject);
+      const consoleActor = target.form.consoleActor;
+      const client = target.client;
+      try {
+        const [, webConsoleClient] = await client.attachConsole(consoleActor, []);
+        clearTimeout(connectTimer);
+        resolve({
+          webConsoleClient,
+          debuggerClient: client
         });
+      } catch (error) {
+        reportError("attachConsole", error);
+        reject(error);
+      }
     });
 
-    return deferred.promise;
+    return this._connector;
   },
 
   /**
    * Attach to this tab.
    *
-   * @param object aSubject
+   * @param object subject
    *        The tab or window to obtain the connection for.
    * @return Promise
    *         The promise for the TabTarget for this tab.
    */
-  _attach: async function ST__attach(aSubject) {
+  async _attach(subject) {
     const target = await TargetFactory.forTab(this._tab);
     target.once("close", () => {
       if (scratchpadTargets) {
-        scratchpadTargets.delete(aSubject);
+        scratchpadTargets.delete(subject);
       }
     });
     return target.attach().then(() => target);
   },
 };
 
 /**
  * Represents the DebuggerClient connection to a specific window as used by the
@@ -2113,40 +2063,38 @@ ScratchpadWindow.consoleFor = Scratchpad
 
 ScratchpadWindow.prototype = extend(ScratchpadTab.prototype, {
   /**
    * Attach to this window.
    *
    * @return Promise
    *         The promise for the target for this window.
    */
-  _attach: function SW__attach() {
+  async _attach() {
     DebuggerServer.init();
     DebuggerServer.registerAllActors();
     DebuggerServer.allowChromeProcess = true;
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
-    return client.connect()
-      .then(() => client.getProcess())
-      .then(aResponse => {
-        return { form: aResponse.form, client: client };
-      });
+    await client.connect();
+    const response = await client.getProcess();
+    return { form: response.form, client };
   }
 });
 
 function ScratchpadTarget(aTarget) {
   this._target = aTarget;
 }
 
 ScratchpadTarget.consoleFor = ScratchpadTab.consoleFor;
 
 ScratchpadTarget.prototype = extend(ScratchpadTab.prototype, {
-  _attach: function ST__attach() {
+  _attach() {
     if (this._target.isRemote) {
-      return promise.resolve(this._target);
+      return Promise.resolve(this._target);
     }
     return this._target.attach().then(() => this._target);
   }
 });
 
 /**
  * Encapsulates management of the sidebar containing the VariablesView for
  * object inspection.
@@ -2177,67 +2125,65 @@ ScratchpadSidebar.prototype = {
    * Whether the sidebar is currently shown.
    */
   visible: false,
 
   /**
    * Open the sidebar, if not open already, and populate it with the properties
    * of the given object.
    *
-   * @param string aString
+   * @param string string
    *        The string that was evaluated.
-   * @param object aObject
+   * @param object obj
    *        The object to inspect, which is the aEvalString evaluation result.
    * @return Promise
    *         A promise that will resolve once the sidebar is open.
    */
-  open: function SS_open(aEvalString, aObject) {
+  open(string, obj) {
     this.show();
 
-    const deferred = defer();
+    return new Promise(resolve => {
+      const onTabReady = () => {
+        if (this.variablesView) {
+          this.variablesView.controller.releaseActors();
+        } else {
+          const window = this._sidebar.getWindowForTab("variablesview");
+          const container = window.document.querySelector("#variables");
 
-    const onTabReady = () => {
-      if (this.variablesView) {
-        this.variablesView.controller.releaseActors();
-      } else {
-        const window = this._sidebar.getWindowForTab("variablesview");
-        const container = window.document.querySelector("#variables");
-
-        this.variablesView = new VariablesView(container, {
-          searchEnabled: true,
-          searchPlaceholder: this._scratchpad.strings
-                             .GetStringFromName("propertiesFilterPlaceholder")
-        });
+          this.variablesView = new VariablesView(container, {
+            searchEnabled: true,
+            searchPlaceholder: this._scratchpad.strings
+              .GetStringFromName("propertiesFilterPlaceholder")
+          });
 
-        VariablesViewController.attach(this.variablesView, {
-          getEnvironmentClient: aGrip => {
-            return new EnvironmentClient(this._scratchpad.debuggerClient, aGrip);
-          },
-          getObjectClient: aGrip => {
-            return new ObjectClient(this._scratchpad.debuggerClient, aGrip);
-          },
-          getLongStringClient: aActor => {
-            return this._scratchpad.webConsoleClient.longString(aActor);
-          },
-          releaseActor: aActor => {
-            this._scratchpad.debuggerClient.release(aActor);
-          }
-        });
+          VariablesViewController.attach(this.variablesView, {
+            getEnvironmentClient: grip => {
+              return new EnvironmentClient(this._scratchpad.debuggerClient, grip);
+            },
+            getObjectClient: grip => {
+              return new ObjectClient(this._scratchpad.debuggerClient, grip);
+            },
+            getLongStringClient: actor => {
+              return this._scratchpad.webConsoleClient.longString(actor);
+            },
+            releaseActor: actor => {
+              this._scratchpad.debuggerClient.release(actor);
+            }
+          });
+        }
+        this._update(obj).then(resolve);
+      };
+
+      if (this._sidebar.getCurrentTabID() == "variablesview") {
+        onTabReady();
+      } else {
+        this._sidebar.once("variablesview-ready", onTabReady);
+        this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, {selected: true});
       }
-      this._update(aObject).then(() => deferred.resolve());
-    };
-
-    if (this._sidebar.getCurrentTabID() == "variablesview") {
-      onTabReady();
-    } else {
-      this._sidebar.once("variablesview-ready", onTabReady);
-      this._sidebar.addTab("variablesview", VARIABLES_VIEW_URL, {selected: true});
-    }
-
-    return deferred.promise;
+    });
   },
 
   /**
    * Show the sidebar.
    */
   show: function SS_show() {
     if (!this.visible) {
       this.visible = true;
--- a/devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
@@ -232,18 +232,18 @@ var PreferenceObserver = {
       return;
     }
 
     this.branch = Services.prefs.getBranch("devtools.scratchpad.");
     this.branch.addObserver("", this);
     this._initialized = true;
   },
 
-  observe: async function PO_observe(aMessage, aTopic, aData) {
-    if (aTopic != "nsPref:changed") {
+  async observe(message, topic, data) {
+    if (topic != "nsPref:changed") {
       return;
     }
 
     if (this._inProgress) {
       await this._inProgress;
     }
 
     this._inProgress = new Promise(async resolve => {
--- a/devtools/client/scratchpad/test/head.js
+++ b/devtools/client/scratchpad/test/head.js
@@ -6,18 +6,16 @@
 
 const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {});
 const {FileUtils} = ChromeUtils.import("resource://gre/modules/FileUtils.jsm", {});
 const {ScratchpadManager} = ChromeUtils.import("resource://devtools/client/scratchpad/scratchpad-manager.jsm", {});
 const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
 const {gDevTools} = require("devtools/client/framework/devtools");
 const Services = require("Services");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
-const promise = require("promise");
-const defer = require("devtools/shared/defer");
 
 var gScratchpadWindow; // Reference to the Scratchpad chrome window object
 
 /**
  * Open a Scratchpad window.
  *
  * @param function aReadyCallback
  *        Optional. The function you want invoked when the Scratchpad instance
@@ -76,17 +74,17 @@ function openScratchpad(aReadyCallback, 
  *        are supported:
  *        - tabContent
  *          A string providing the html content of the tab.
  * @return Promise
  */
 function openTabAndScratchpad(aOptions = {}) {
   waitForExplicitFinish();
   // eslint-disable-next-line new-cap
-  return new promise(resolve => {
+  return new Promise(resolve => {
     gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
     const {selectedBrowser} = gBrowser;
     BrowserTestUtils.browserLoaded(selectedBrowser).then(function() {
       openScratchpad((win, sp) => resolve([win, sp]), aOptions);
     });
     BrowserTestUtils.loadURI(gBrowser, "data:text/html;charset=utf8," + (aOptions.tabContent || ""));
   });
 }
@@ -123,51 +121,49 @@ function createTempFile(aName, aContent,
   NetUtil.asyncCopy(fileContentStream, fout, function(aStatus) {
     aCallback(aStatus, file);
   });
 }
 
 /**
  * Run a set of asychronous tests sequentially defined by input and output.
  *
- * @param Scratchpad aScratchpad
+ * @param Scratchpad scratchpad
  *        The scratchpad to use in running the tests.
- * @param array aTests
+ * @param array tests
  *        An array of test objects, each with the following properties:
  *        - method
  *          Scratchpad method to use, one of "run", "display", or "inspect".
  *        - code
  *          Code to run in the scratchpad.
  *        - result
  *          Expected code that will be in the scratchpad upon completion.
  *        - label
  *          The tests label which will be logged in the test runner output.
  * @return Promise
  *         The promise that will be resolved when all tests are finished.
  */
-function runAsyncTests(aScratchpad, aTests) {
-  const deferred = defer();
-
-  (function runTest() {
-    if (aTests.length) {
-      const test = aTests.shift();
-      aScratchpad.setText(test.code);
-      aScratchpad[test.method]().then(function success() {
-        is(aScratchpad.getText(), test.result, test.label);
-        runTest();
-      }, function failure(error) {
-        ok(false, error.stack + " " + test.label);
-        runTest();
-      });
-    } else {
-      deferred.resolve();
-    }
-  })();
-
-  return deferred.promise;
+function runAsyncTests(scratchpad, tests) {
+  return new Promise(resolve => {
+    (function runTest() {
+      if (tests.length) {
+        const test = tests.shift();
+        scratchpad.setText(test.code);
+        scratchpad[test.method]().then(function success() {
+          is(scratchpad.getText(), test.result, test.label);
+          runTest();
+        }, function failure(error) {
+          ok(false, error.stack + " " + test.label);
+          runTest();
+        });
+      } else {
+        resolve();
+      }
+    })();
+  });
 }
 
 /**
  * Run a set of asychronous tests sequentially with callbacks to prepare each
  * test and to be called when the test result is ready.
  *
  * @param Scratchpad aScratchpad
  *        The scratchpad to use in running the tests.