Bug 1451659 - Enable ESLint for devtools/client/{canvasdebugger,framework,scratchpad,shadereditor}/. r?jdescottes draft
authorMark Banner <standard8@mozilla.com>
Wed, 04 Apr 2018 23:24:04 +0100
changeset 777911 3973ca9c1e342c43343687dfebb47ae9ed94dc83
parent 777830 47b35ecbeadd0460cd9423ecb65d5d3ed2879528
child 777912 cd003b0e47621e74a47ae5e4e1cc4c1eb5a06892
push id105326
push userbmo:standard8@mozilla.com
push dateThu, 05 Apr 2018 14:11:08 +0000
reviewersjdescottes
bugs1451659
milestone61.0a1
Bug 1451659 - Enable ESLint for devtools/client/{canvasdebugger,framework,scratchpad,shadereditor}/. r?jdescottes Disable rules with many failures for now, in a way that mentored bugs can easily pick them up. Fix other minor issues raised by various rules. MozReview-Commit-ID: 71OQI7jLihe
.eslintignore
devtools/.eslintrc.js
devtools/client/canvasdebugger/callslist.js
devtools/client/canvasdebugger/snapshotslist.js
devtools/client/canvasdebugger/test/browser_profiling-webgl.js
devtools/client/framework/sidebar.js
devtools/client/framework/test/browser_browser_toolbox_debugger.js
devtools/client/framework/test/browser_toolbox_options_disable_js.html
devtools/client/framework/test/browser_toolbox_options_disable_js_iframe.html
devtools/client/framework/test/browser_toolbox_transport_events.js
devtools/client/framework/test/browser_toolbox_window_shortcuts.js
devtools/client/scratchpad/scratchpad-commands.js
devtools/client/scratchpad/scratchpad-panel.js
devtools/client/scratchpad/scratchpad.js
devtools/client/scratchpad/test/browser_scratchpad_open.js
devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
devtools/client/scratchpad/test/browser_scratchpad_remember_view_options.js
devtools/client/scratchpad/test/browser_scratchpad_revert_to_saved.js
devtools/client/scratchpad/test/head.js
devtools/client/shadereditor/panel.js
devtools/client/shadereditor/shadereditor.js
devtools/client/shadereditor/test/head.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -96,33 +96,21 @@ browser/extensions/activity-stream/vendo
 # The only file in browser/locales/ is pre-processed.
 browser/locales/**
 # imported from chromium
 browser/extensions/mortar/**
 # Generated data files
 browser/extensions/formautofill/phonenumberutils/PhoneNumberMetaData.jsm
 
 # devtools/ exclusions
-devtools/client/canvasdebugger/**
-devtools/client/commandline/**
-devtools/client/debugger/**
-devtools/client/framework/**
-!devtools/client/framework/devtools.js
-!devtools/client/framework/devtools-browser.js
-!devtools/client/framework/selection.js
-!devtools/client/framework/target*
-!devtools/client/framework/toolbox*
 devtools/client/inspector/markup/test/doc_markup_events_*.html
 devtools/client/inspector/rules/test/doc_media_queries.html
 devtools/client/memory/test/chrome/*.html
 devtools/client/performance/components/test/test_jit_optimizations_01.html
-devtools/client/projecteditor/**
 devtools/client/responsive.html/test/browser/touch.html
-devtools/client/scratchpad/**
-devtools/client/shadereditor/**
 devtools/client/shared/*.jsm
 devtools/client/shared/components/reps/reps.js
 devtools/client/shared/components/reps/test/mochitest/*.html
 !devtools/client/shared/components/reps/test/mochitest/test_reps_infinity.html
 !devtools/client/shared/components/reps/test/mochitest/test_reps_nan.html
 !devtools/client/shared/components/reps/test/mochitest/test_reps_promise.html
 !devtools/client/shared/components/reps/test/mochitest/test_reps_symbol.html
 !devtools/client/shared/components/reps/test/mochitest/test_reps_text-node.html
@@ -149,50 +137,54 @@ devtools/server/tests/browser/storage-*.
 !devtools/server/tests/browser/storage-unsecured-iframe.html
 devtools/server/tests/browser/stylesheets-nested-iframes.html
 devtools/server/tests/unit/xpcshell_debugging_script.js
 devtools/client/shared/webpack/shims/test/test_clipboard.html
 devtools/shared/qrcode/tests/mochitest/test_decode.html
 devtools/shared/tests/mochitest/*.html
 devtools/shared/webconsole/test/test_*.html
 
+# Soon to be removed
+devtools/client/commandline/**
+# Soon to be removed, the new/ directory is explicitly excluded below due to
+# also being an imported repository.
+devtools/client/debugger/**
+
+# Ignore devtools imported repositories
+devtools/client/debugger/new/**
+
 # Ignore devtools preferences files
 devtools/client/preferences/**
 devtools/startup/devtools-startup-prefs.js
 
 # Ignore devtools third-party libs
 devtools/shared/jsbeautify/*
 devtools/shared/acorn/*
 devtools/shared/gcli/source/*
 devtools/shared/node-properties/*
 devtools/shared/pretty-fast/*
 devtools/shared/sourcemap/*
 devtools/shared/sprintfjs/*
 devtools/shared/qrcode/decoder/*
 devtools/shared/qrcode/encoder/*
+devtools/client/inspector/markup/test/lib_*
+devtools/client/jsonview/lib/require.js
 devtools/client/shared/demangle.js
 devtools/client/shared/source-map/*
 devtools/client/shared/vendor/*
 devtools/client/sourceeditor/codemirror/*.js
 devtools/client/sourceeditor/codemirror/**/*.js
 devtools/client/sourceeditor/tern/*
 devtools/client/sourceeditor/test/cm_mode_ruby.js
 devtools/client/sourceeditor/test/codemirror/*
-devtools/client/inspector/markup/test/lib_*
-devtools/client/jsonview/lib/require.js
 devtools/server/actors/utils/automation-timeline.js
 
 # Ignore devtools files testing sourcemaps / code style
-devtools/client/debugger/test/mochitest/code_binary_search.js
-devtools/client/debugger/test/mochitest/code_binary_search_absolute.js
-devtools/client/debugger/test/mochitest/code_math.min.js
-devtools/client/debugger/test/mochitest/code_math_bogus_map.js
-devtools/client/debugger/test/mochitest/code_ugly*
-devtools/client/debugger/test/mochitest/code_worker-source-map.js
-devtools/client/framework/test/code_ugly*
+devtools/client/debugger/test/mochitest/code_*.js
+devtools/client/framework/test/code_*
 devtools/client/inspector/markup/test/events_bundle.js
 devtools/client/netmonitor/test/xhr_bundle.js
 devtools/client/webconsole/new-console-output/test/mochitest/code_bundle_nosource.js
 devtools/client/webconsole/new-console-output/test/mochitest/code_bundle_invalidmap.js
 devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
 devtools/server/tests/unit/setBreakpoint*
 devtools/server/tests/unit/sourcemapped.js
 
--- a/devtools/.eslintrc.js
+++ b/devtools/.eslintrc.js
@@ -11,22 +11,132 @@ module.exports = {
     "module": true,
     "reportError": true,
     "require": true,
   },
   "overrides": [{
     // XXX Bug 1230193. We're still working on enabling no-undef for these test
     // directories.
     "files": [
+      "client/framework/test/**",
+      "client/scratchpad/**",
       "server/tests/mochitest/**",
       "shared/tests/unit/**",
     ],
     "rules": {
       "no-undef": "off",
     }
+  }, {
+    "files": [
+      "client/framework/**",
+    ],
+    "rules": {
+      "no-return-assign": "off",
+      "no-unused-vars": "off",
+    }
+  }, {
+    "files": [
+      "client/scratchpad/scratchpad-manager.jsm",
+      "client/scratchpad/scratchpad.js",
+    ],
+    "rules": {
+      "camelcase": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "consistent-return": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "max-nested-callbacks": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "max-len": "off",
+    }
+  }, {
+    "files": [
+      "client/scratchpad/test/browser_scratchpad_inspect.js",
+      "client/scratchpad/test/browser_scratchpad_inspect_primitives.js",
+    ],
+    "rules": {
+      "no-labels": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "mozilla/no-aArgs": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/test/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "mozilla/var-only-at-top-level": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "no-shadow": "off",
+    }
+  }, {
+    "files": [
+      "client/framework/**",
+      "client/scratchpad/**",
+    ],
+    "rules": {
+      "strict": "off",
+    }
+  }, {
+    "files": [
+      // Note: Bug 1403938 may be removing canvasdebugger, check before
+      // doing more work on enabling these rules.
+      "client/canvasdebugger/**",
+      // Note: Bug 1342237 may be removing shadereditor, check before
+      // doing more work on enabling these rules.
+      "client/shadereditor/**",
+    ],
+    "rules": {
+      "consistent-return": "off",
+      "max-len": "off",
+      "mozilla/no-aArgs": "off",
+      "mozilla/var-only-at-top-level": "off",
+      "no-return-assign": "off",
+      "no-shadow": "off",
+      "no-undef": "off",
+      "no-unused-vars": "off",
+      "strict": "off",
+    }
+  }, {
+    // For all head*.js files, turn off no-unused-vars at a global level
+    "files": [
+      "**/head*.js",
+    ],
+    "rules": {
+      "no-unused-vars": ["error", {"args": "none", "vars": "local"}],
+    }
   }],
   "rules": {
     // These are the rules that have been configured so far to match the
     // devtools coding style.
 
     // Rules from the mozilla plugin
     "mozilla/no-aArgs": "error",
     "mozilla/no-single-arg-cu-import": "error",
--- a/devtools/client/canvasdebugger/callslist.js
+++ b/devtools/client/canvasdebugger/callslist.js
@@ -362,19 +362,18 @@ var CallsListView = extend(WidgetMethods
       window.emit(EVENTS.CALL_STACK_DISPLAYED);
     };
 
     // If this animation snapshot is loaded from disk, there are no corresponding
     // backend actors available and the data is immediately available.
     let functionCall = callItem.attachment.actor;
     if (functionCall.isLoadedFromDisk) {
       display(functionCall.stack);
-    }
-    // ..otherwise we need to request the function call stack from the backend.
-    else {
+    } else {
+      // ..otherwise we need to request the function call stack from the backend.
       callItem.attachment.actor.getDetails().then(fn => display(fn.stack));
     }
   },
 
   /**
    * The click listener for a location link in the call stack.
    *
    * @param string file
--- a/devtools/client/canvasdebugger/snapshotslist.js
+++ b/devtools/client/canvasdebugger/snapshotslist.js
@@ -301,22 +301,21 @@ var SnapshotsListView = extend(WidgetMet
    * or if a recording times out.
    */
   async _stopRecordingAnimation() {
     clearNamedTimeout("canvas-actor-recording");
     let actorCanStop = await gTarget.actorHasMethod("canvas", "stopRecordingAnimationFrame");
 
     if (actorCanStop) {
       await gFront.stopRecordingAnimationFrame();
-    }
-    // If actor does not have the method to stop recording (Fx39+),
-    // manually call the record failure method. This will call a connection failure
-    // on disconnect as a result of `gFront.recordAnimationFrame()` never resolving,
-    // but this is better than it hanging when there is no requestAnimationFrame anyway.
-    else {
+    } else {
+      // If actor does not have the method to stop recording (Fx39+),
+      // manually call the record failure method. This will call a connection failure
+      // on disconnect as a result of `gFront.recordAnimationFrame()` never resolving,
+      // but this is better than it hanging when there is no requestAnimationFrame anyway.
       this._onRecordFailure();
     }
 
     this._recording = false;
     $("#record-snapshot").removeAttribute("checked");
     this._enableRecordButton();
   },
 
@@ -366,19 +365,20 @@ var SnapshotsListView = extend(WidgetMet
         uri: NetUtil.newURI(fp.file), loadUsingSystemPrincipal: true});
       channel.contentType = "text/plain";
 
       NetUtil.asyncFetch(channel, (inputStream, status) => {
         if (!Components.isSuccessCode(status)) {
           console.error("Could not import recorded animation frame snapshot file.");
           return;
         }
+        var data;
         try {
           let string = NetUtil.readInputStreamToString(inputStream, inputStream.available());
-          var data = JSON.parse(string);
+          data = JSON.parse(string);
         } catch (e) {
           console.error("Could not read animation frame snapshot file.");
           return;
         }
         if (data.fileType != CALLS_LIST_SERIALIZER_IDENTIFIER) {
           console.error("Unrecognized animation frame snapshot file.");
           return;
         }
--- a/devtools/client/canvasdebugger/test/browser_profiling-webgl.js
+++ b/devtools/client/canvasdebugger/test/browser_profiling-webgl.js
@@ -37,17 +37,19 @@ async function ifTestingSupported() {
   is(animationOverview.primitive.tris, 5, "The count of triangles is correct.");
   is(animationOverview.primitive.vertices, 26, "The count of vertices is correct.");
   is(animationOverview.primitive.points, 4, "The count of points is correct.");
   is(animationOverview.primitive.lines, 8, "The count of lines is correct.");
 
   await removeTab(target.tab);
 
   info("Start to estimate WebGL drawElements function.");
-  var { target, front } = await initCanvasDebuggerBackend(WEBGL_DRAW_ELEMENTS);
+  let result = await initCanvasDebuggerBackend(WEBGL_DRAW_ELEMENTS);
+  target = result.target;
+  front = result.front;
 
   navigated = once(target, "navigate");
 
   await front.setup({ reload: true });
   ok(true, "The front was setup up successfully.");
 
   await navigated;
   ok(true, "Target automatically navigated when the front was set up.");
--- a/devtools/client/framework/sidebar.js
+++ b/devtools/client/framework/sidebar.js
@@ -63,19 +63,20 @@ function ToolSidebar(tabbox, panel, uid,
   this._uid = uid;
   this._panelDoc = this._tabbox.ownerDocument;
   this._toolPanel = panel;
   this._options = options;
 
   this._onTabBoxOverflow = this._onTabBoxOverflow.bind(this);
   this._onTabBoxUnderflow = this._onTabBoxUnderflow.bind(this);
 
-  try {
-    this._width = Services.prefs.getIntPref("devtools.toolsidebar-width." + this._uid);
-  } catch (e) {}
+  let width = Services.prefs.getIntPref("devtools.toolsidebar-width." + this._uid, undefined);
+  if (width) {
+    this._width = width;
+  }
 
   if (!options.disableTelemetry) {
     this._telemetry = new Telemetry();
   }
 
   this._tabbox.tabpanels.addEventListener("select", this, true);
 
   this._tabs = new Map();
--- a/devtools/client/framework/test/browser_browser_toolbox_debugger.js
+++ b/devtools/client/framework/test/browser_browser_toolbox_debugger.js
@@ -103,16 +103,18 @@ add_task(async function runTest() {
     // test_browser_toolbox_debugger.js uses waitForPaused, which relies on waitUntil
     // which is normally provided by shared-head.js
     const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm", {});
     function waitUntil(predicate, interval = 10) {
       if (predicate()) {
         return Promise.resolve(true);
       }
       return new Promise(resolve => {
+        // TODO: fixme.
+        // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
         setTimeout(function() {
           waitUntil(predicate, interval).then(() => resolve(true));
         }, interval);
       });
     }
   }).toSource().replace(/^\(function \(\) \{|\}\)$/g, "");
   // Stringify testHead's function and remove `(function {` prefix and `})` suffix
   // to ensure inner symbols gets exposed to next pieces of code
--- a/devtools/client/framework/test/browser_toolbox_options_disable_js.html
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_js.html
@@ -19,16 +19,17 @@
       h1 {
         font-size: 20px
       }
     </style>
     <script type="application/javascript">
       function log(msg) {
         let output = document.getElementById("output");
 
+        // eslint-disable-next-line no-unsanitized/property
         output.innerHTML = msg;
       }
     </script>
   </head>
   <body>
     <h1>Test in page</h1>
     <input id="logJSEnabled"
            type="button"
--- a/devtools/client/framework/test/browser_toolbox_options_disable_js_iframe.html
+++ b/devtools/client/framework/test/browser_toolbox_options_disable_js_iframe.html
@@ -9,16 +9,17 @@
         border: 1px solid #000;
         margin-top: 10px;
       }
     </style>
     <script type="application/javascript">
       function log(msg) {
         let output = document.getElementById("output");
 
+        // eslint-disable-next-line no-unsanitized/property
         output.innerHTML = msg;
       }
     </script>
   </head>
   <body>
     <input id="logJSEnabled"
            type="button"
            value="Log JS Enabled"
--- a/devtools/client/framework/test/browser_toolbox_transport_events.js
+++ b/devtools/client/framework/test/browser_toolbox_transport_events.js
@@ -25,16 +25,18 @@ function testResults(toolbox) {
   cleanUp(toolbox);
 }
 
 function cleanUp(toolbox) {
   gDevTools.off("toolbox-created", onToolboxCreated);
   off(DebuggerClient, "connect", onDebuggerClientConnect);
 
   toolbox.destroy().then(function() {
+    // TODO: fixme.
+    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     setTimeout(() => {
       gBrowser.removeCurrentTab();
       executeSoon(function() {
         finish();
       });
     }, 1000);
   });
 }
--- a/devtools/client/framework/test/browser_toolbox_window_shortcuts.js
+++ b/devtools/client/framework/test/browser_toolbox_window_shortcuts.js
@@ -18,22 +18,18 @@ function test() {
       let shortcut = Startup.KeyShortcuts.filter(s => s.toolId == id)[0];
       if (!shortcut) {
         continue;
       }
       toolIDs.push(id);
       toolShortcuts.push(shortcut);
 
       // Enable disabled tools
-      let pref = definition.visibilityswitch, prefValue;
-      try {
-        prefValue = Services.prefs.getBoolPref(pref);
-      } catch (e) {
-        continue;
-      }
+      let pref = definition.visibilityswitch;
+      let prefValue = Services.prefs.getBoolPref(pref, false);
       if (!prefValue) {
         modifiedPrefs.push(pref);
         Services.prefs.setBoolPref(pref, true);
       }
     }
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     idIndex = 0;
     gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.WINDOW)
--- a/devtools/client/scratchpad/scratchpad-commands.js
+++ b/devtools/client/scratchpad/scratchpad-commands.js
@@ -1,16 +1,15 @@
 /* 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 l10n = require("gcli/l10n");
-const {Cu} = require("chrome");
 
 exports.items = [{
   item: "command",
   runAt: "client",
   name: "scratchpad",
   buttonId: "command-button-scratchpad",
   buttonClass: "command-button",
   tooltipText: l10n.lookup("scratchpadOpenTooltip"),
--- a/devtools/client/scratchpad/scratchpad-panel.js
+++ b/devtools/client/scratchpad/scratchpad-panel.js
@@ -1,16 +1,15 @@
 /* -*- 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 {Cu} = require("chrome");
 const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 
 function ScratchpadPanel(iframeWindow, toolbox) {
   let { Scratchpad } = iframeWindow;
   this._toolbox = toolbox;
   this.panelWin = iframeWindow;
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -51,22 +51,22 @@ 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 {addDebuggerToGlobal} = require("resource://gre/modules/jsdebugger.jsm");
 const {OS} = require("resource://gre/modules/osfile.jsm");
 const {Reflect} = require("resource://gre/modules/reflect.jsm");
 
 // Use privileged promise in panel documents to prevent having them to freeze
 // during toolbox destruction. See bug 1402779.
+// eslint-disable-next-line no-unused-vars
 const Promise = require("Promise");
 
 XPCOMUtils.defineConstant(this, "SCRATCHPAD_CONTEXT_CONTENT", SCRATCHPAD_CONTEXT_CONTENT);
 XPCOMUtils.defineConstant(this, "SCRATCHPAD_CONTEXT_BROWSER", SCRATCHPAD_CONTEXT_BROWSER);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_SAVE", BUTTON_POSITION_SAVE);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_CANCEL", BUTTON_POSITION_CANCEL);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_DONT_SAVE", BUTTON_POSITION_DONT_SAVE);
 XPCOMUtils.defineConstant(this, "BUTTON_POSITION_REVERT", BUTTON_POSITION_REVERT);
@@ -1074,32 +1074,32 @@ var Scratchpad = {
    * Get content converted to unicode, using a list of input charset to try.
    *
    * @param string aContent
    * @param array of string aCharsetArray
    * @return string
    */
   _getUnicodeContent: function SP__getUnicodeContent(aContent, aCharsetArray) {
     let content = null,
-      converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter),
-      success = aCharsetArray.some(charset => {
-        try {
-          converter.charset = charset;
-          content = converter.ConvertToUnicode(aContent);
-          return true;
-        } catch (e) {
-          this.notificationBox.appendNotification(
-              this.strings.formatStringFromName("importFromFile.convert.failed",
-                                                [ charset ], 1),
-              "file-import-convert-failed",
-              null,
-              this.notificationBox.PRIORITY_WARNING_HIGH,
-              null);
-        }
-      });
+      converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
+    aCharsetArray.some(charset => {
+      try {
+        converter.charset = charset;
+        content = converter.ConvertToUnicode(aContent);
+        return true;
+      } catch (e) {
+        this.notificationBox.appendNotification(
+            this.strings.formatStringFromName("importFromFile.convert.failed",
+                                              [ charset ], 1),
+            "file-import-convert-failed",
+            null,
+            this.notificationBox.PRIORITY_WARNING_HIGH,
+            null);
+      }
+    });
     return content;
   },
 
   /**
    * Read the content of a file and put it into the textbox.
    *
    * @param nsIFile aFile
    *        The file you want to save the textbox content into.
@@ -1276,20 +1276,19 @@ var Scratchpad = {
         // same file has been opened in two or more windows.
         this.populateRecentFilesMenu();
         return;
       }
 
       // It is not the most recent file. Remove it from the list, we add it as
       // the most recent farther down.
       filePaths.splice(pathIndex, 1);
-    }
-    // If we are not storing the file and the 'recent files'-list is full,
-    // remove the oldest file from the list.
-    else if (filesCount === maxRecent) {
+    } else if (filesCount === maxRecent) {
+      // If we are not storing the file and the 'recent files'-list is full,
+      // remove the oldest file from the list.
       filePaths.shift();
     }
 
     filePaths.push(aFile.path);
 
     Services.prefs.getBranch("devtools.scratchpad.")
             .setStringPref("recentFilePaths", JSON.stringify(filePaths));
   },
--- a/devtools/client/scratchpad/test/browser_scratchpad_open.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_open.js
@@ -66,17 +66,17 @@ function testOpenWithState() {
 
 function testOpenInvalidState() {
   let win = openScratchpad(null, {state: 7});
   ok(!win, "no scratchpad opened if state is not an object");
   done();
 }
 
 function testOpenTestFile() {
-  let win = openScratchpad(function(win) {
+  openScratchpad(function(win) {
     ok(win, "scratchpad opened for file open");
     try {
       win.Scratchpad.importFromFile(
         "http://example.com/browser/devtools/client/scratchpad/test/NS_ERROR_ILLEGAL_INPUT.txt",
         "silent",
         function(aStatus, content) {
           let nb = win.document.querySelector("#scratchpad-notificationbox");
           is(nb.querySelectorAll("notification").length, 1, "There is just one notification");
--- a/devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_recent_files.js
@@ -22,17 +22,16 @@ var lists = {
 
 // Temporary file names.
 var gFileName01 = "file01_ForBug651942.tmp";
 var gFileName02 = "☕"; // See bug 783858 for more information
 var gFileName03 = "file03_ForBug651942.tmp";
 var gFileName04 = "file04_ForBug651942.tmp";
 
 // Content for the temporary files.
-var gFileContent;
 var gFileContent01 = "hello.world.01('bug651942');";
 var gFileContent02 = "hello.world.02('bug651942');";
 var gFileContent03 = "hello.world.03('bug651942');";
 var gFileContent04 = "hello.world.04('bug651942');";
 
 function startTest() {
   gScratchpad = gScratchpadWindow.Scratchpad;
 
--- a/devtools/client/scratchpad/test/browser_scratchpad_remember_view_options.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_remember_view_options.js
@@ -16,17 +16,16 @@ function test() {
     openScratchpad(runTests);
   });
 
   gBrowser.loadURI("data:text/html,<title>Bug 1140839</title>" +
                    "<p>test Scratchpad should remember View options");
 }
 
 function runTests() {
-  let sp = gScratchpadWindow.Scratchpad;
   let doc = gScratchpadWindow.document;
 
   let testData = [
     {itemMenuId: "sp-menu-line-numbers", prefId: "devtools.scratchpad.lineNumbers", expectedVal: false},
     {itemMenuId: "sp-menu-word-wrap", prefId: "devtools.scratchpad.wrapText", expectedVal: true},
     {itemMenuId: "sp-menu-highlight-trailing-space", prefId: "devtools.scratchpad.showTrailingSpace", expectedVal: true},
     {itemMenuId: "sp-menu-larger-font", prefId: "devtools.scratchpad.editorFontSize", expectedVal: 13},
     {itemMenuId: "sp-menu-normal-size-font", prefId: "devtools.scratchpad.editorFontSize", expectedVal: 12},
--- a/devtools/client/scratchpad/test/browser_scratchpad_revert_to_saved.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_revert_to_saved.js
@@ -10,17 +10,16 @@ var gScratchpad;
 var gFile;
 
 // Temporary file name.
 var gFileName = "testFileForBug751744.tmp";
 
 // Content for the temporary file.
 var gFileContent = "/* this file is already saved */\n" +
                    "function foo() { alert('bar') }";
-var gLength = gFileContent.length;
 
 // Reference to the menu entry.
 var menu;
 
 function startTest() {
   gScratchpad = gScratchpadWindow.Scratchpad;
   menu = gScratchpadWindow.document.getElementById("sp-cmd-revert");
   createAndLoadTemporaryFile();
--- a/devtools/client/scratchpad/test/head.js
+++ b/devtools/client/scratchpad/test/head.js
@@ -81,16 +81,17 @@ function openScratchpad(aReadyCallback, 
  *        to the options supported by openScratchpad, the following options
  *        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 => {
     gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
     let {selectedBrowser} = gBrowser;
     BrowserTestUtils.browserLoaded(selectedBrowser).then(function() {
       openScratchpad((win, sp) => resolve([win, sp]), aOptions);
     });
     gBrowser.loadURI("data:text/html;charset=utf8," + (aOptions.tabContent || ""));
   });
--- a/devtools/client/shadereditor/panel.js
+++ b/devtools/client/shadereditor/panel.js
@@ -1,16 +1,15 @@
 /* -*- 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 { Cc, Ci, Cu, Cr } = require("chrome");
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { WebGLFront } = require("devtools/shared/fronts/webgl");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
 function ShaderEditorPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
@@ -62,15 +61,15 @@ ShaderEditorPanel.prototype = {
   },
 
   destroy: function() {
     // Make sure this panel is not already destroyed.
     if (this._destroyer) {
       return this._destroyer;
     }
 
-    return this._destroyer = this.panelWin.shutdownShaderEditor().then(() => {
+    return (this._destroyer = this.panelWin.shutdownShaderEditor().then(() => {
       // Destroy front to ensure packet handler is removed from client
       this.panelWin.gFront.destroy();
       this.emit("destroyed");
-    });
+    }));
   }
 };
--- a/devtools/client/shadereditor/shadereditor.js
+++ b/devtools/client/shadereditor/shadereditor.js
@@ -1,30 +1,32 @@
 /* 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";
 
+/* exported startupShaderEditor, shutdownShaderEditor */
+
 const {require} = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
 const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
 const {SideMenuWidget} = require("resource://devtools/client/shared/widgets/SideMenuWidget.jsm");
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const {Task} = require("devtools/shared/task");
-const Services = require("Services");
 const EventEmitter = require("devtools/shared/event-emitter");
 const Tooltip = require("devtools/client/shared/widgets/tooltip/Tooltip");
 const Editor = require("devtools/client/sourceeditor/editor");
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const {extend} = require("devtools/shared/extend");
 const {WidgetMethods, setNamedTimeout} =
   require("devtools/client/shared/widgets/view-helpers");
 
 // Use privileged promise in panel documents to prevent having them to freeze
 // during toolbox destruction. See bug 1402779.
+// eslint-disable-next-line no-unused-vars
 const Promise = require("Promise");
 
 // The panel's window global is an EventEmitter firing the following events:
 const EVENTS = {
   // When new programs are received from the server.
   NEW_PROGRAM: "ShaderEditor:NewProgram",
   PROGRAMS_ADDED: "ShaderEditor:ProgramsAdded",
 
--- a/devtools/client/shadereditor/test/head.js
+++ b/devtools/client/shadereditor/test/head.js
@@ -68,17 +68,17 @@ function ifWebGLUnsupported() {
   finish();
 }
 
 async function test() {
   let generator = isWebGLSupported(document) ? ifWebGLSupported : ifWebGLUnsupported;
   try {
     await generator();
   } catch (e) {
-    handlError(e);
+    handleError(e);
   }
 }
 
 function createCanvas() {
   return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 }
 
 function observe(aNotificationName, aOwnsWeak = false) {
@@ -110,17 +110,18 @@ function ensurePixelIs(aFront, aPosition
     let pixel = await aFront.getPixel({ selector: aSelector, position: aPosition });
     if (isApproxColor(pixel, aColor)) {
       ok(true, "Expected pixel is shown at: " + aPosition.toSource());
       return;
     }
 
     if (aWaitFlag) {
       await aFront.waitForFrame();
-      return ensurePixelIs(aFront, aPosition, aColor, aWaitFlag, aSelector);
+      await ensurePixelIs(aFront, aPosition, aColor, aWaitFlag, aSelector);
+      return;
     }
 
     ok(false, "Expected pixel was not already shown at: " + aPosition.toSource());
     throw new Error("Expected pixel was not already shown at: " + aPosition.toSource());
   })();
 }
 
 function navigateInHistory(aTarget, aDirection, aWaitForTargetEvent = "navigate") {