Bug 1498041 - Turn on ESLint in mail/base/modules. r=aceman
authorGeoff Lankow <geoff@darktrojan.net>
Mon, 15 Oct 2018 20:47:51 +1300
changeset 33385 436e28c477f716f6f30716f16aee3f67584e6b88
parent 33384 6dda9a7770fc8002defb8324162fcbe3c5420c7f
child 33386 09c71123e1fac034addde969cbd595fb9435fd4f
push id387
push userclokep@gmail.com
push dateMon, 10 Dec 2018 21:30:47 +0000
reviewersaceman
bugs1498041
Bug 1498041 - Turn on ESLint in mail/base/modules. r=aceman
.eslintignore
mail/base/modules/AttachmentChecker.jsm
mail/base/modules/DBViewWrapper.jsm
mail/base/modules/DisplayNameUtils.jsm
mail/base/modules/MailConsts.jsm
mail/base/modules/MailInstrumentation.jsm
mail/base/modules/MailMigrator.jsm
mail/base/modules/MailUtils.jsm
mail/base/modules/MailViewManager.jsm
mail/base/modules/MsgHdrSyntheticView.jsm
mail/base/modules/QuickFilterManager.jsm
mail/base/modules/SearchSpec.jsm
mail/base/modules/SessionStoreManager.jsm
mail/base/modules/SummaryFrameManager.jsm
mail/base/modules/TBDistCustomizer.jsm
mail/base/modules/ThemeVariableMap.jsm
mail/base/modules/Windows8WindowFrameColor.jsm
--- a/.eslintignore
+++ b/.eslintignore
@@ -44,17 +44,18 @@ mailnews/news/*
 mailnews/test/*
 
 # mailnews/extensions exclusions
 mailnews/extensions/*
 !mailnews/extensions/newsblog
 
 # mail exclusions
 mail/app/**
-mail/base/**
+mail/base/content/**
+mail/base/test/**
 mail/branding/**
 mail/config/**
 mail/extensions/**
 mail/installer/**
 mail/locales/**
 mail/test/**
 mail/themes/**
 
--- a/mail/base/modules/AttachmentChecker.jsm
+++ b/mail/base/modules/AttachmentChecker.jsm
@@ -8,95 +8,92 @@ var AttachmentChecker = {
   getAttachmentKeywords,
 };
 
 /**
  * Check whether the character is a CJK character or not.
  *
  * @return true if it is a CJK character.
  */
-function IsCJK(code)
-{
+function IsCJK(code) {
   if (code >= 0x2000 && code <= 0x9fff) {
     // Hiragana, Katakana and Kanaji
     return true;
-  }
-  else if (code >= 0xac00 && code <= 0xd7ff) {
+  } else if (code >= 0xac00 && code <= 0xd7ff) {
     // Hangul
     return true;
-  }
-  else if (code >= 0xf900 && code <= 0xffff) {
+  } else if (code >= 0xf900 && code <= 0xffff) {
     // Hiragana, Katakana and Kanaji
     return true;
   }
   return false;
 }
 
 /**
  * Get the (possibly-empty) list of attachment keywords in this message.
  *
  * @return the (possibly-empty) list of attachment keywords in this message
  **/
-function getAttachmentKeywords(mailData,keywordsInCsv)
-{
+function getAttachmentKeywords(mailData, keywordsInCsv) {
   // The empty string would get split to an array of size 1.  Avoid that...
   var keywordsArray = (keywordsInCsv) ? keywordsInCsv.split(",") : [];
 
-  function escapeRegxpSpecials(inputString)
-  {
+  function escapeRegxpSpecials(inputString) {
     const specials = [".", "\\", "^", "$", "*", "+", "?", "|",
-                      "(", ")" , "[", "]", "{", "}"];
-    var re = new RegExp("(\\"+specials.join("|\\")+")", "g");
+                      "(", ")", "[", "]", "{", "}"];
+    var re = new RegExp("(\\" + specials.join("|\\") + ")", "g");
     inputString = inputString.replace(re, "\\$1");
     return inputString.replace(" ", "\\s+");
   }
 
   // NOT_W is the character class that isn't in the Unicode classes "Ll",
   // "Lu" and "Lt".  It should work like \W, if \W knew about Unicode.
   const NOT_W = "[^\\u0041-\\u005a\\u0061-\\u007a\\u00aa\\u00b5\\u00ba\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u01ba\\u01bc-\\u01bf\\u01c4-\\u02ad\\u0386\\u0388-\\u0481\\u048c-\\u0556\\u0561-\\u0587\\u10a0-\\u10c5\\u1e00-\\u1fbc\\u1fbe\\u1fc2-\\u1fcc\\u1fd0-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ffc\\u207f\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2131\\u2133\\u2134\\u2139\\ufb00-\\ufb17\\uff21-\\uff3a\\uff41-\\uff5a]";
 
   var keywordsFound = [];
   for (var i = 0; i < keywordsArray.length; i++) {
     var kw = escapeRegxpSpecials(keywordsArray[i]);
     // If the keyword starts (ends) with a CJK character, we don't care
     // what the previous (next) character is, because the words aren't
     // space delimited.
     if (keywordsArray[i].charAt(0) == ".") { // like .pdf
       // For this case we want to match the whole document name.
-      var start = "(([^\\s]*)\\b)";
-      var end = IsCJK(kw.charCodeAt(kw.length - 1)) ? "" : "(\\s|$)";
-      var re = new RegExp(start + kw + end, "ig");
-      var matching = mailData.match(re);
+      let start = "(([^\\s]*)\\b)";
+      let end = IsCJK(kw.charCodeAt(kw.length - 1)) ? "" : "(\\s|$)";
+      let re = new RegExp(start + kw + end, "ig");
+      let matching = mailData.match(re);
       if (matching) {
         for (var j = 0; j < matching.length; j++) {
           // Ignore the match if it was in a URL.
           if (!(/^(https?|ftp):\/\//i.test(matching[j]))) {
             // We can have several *different* matches for one dot-keyword.
             // E.g. foo.pdf and bar.pdf would both match for .pdf.
             var m = matching[j].trim();
             if (!keywordsFound.includes(m))
               keywordsFound.push(m);
           }
         }
       }
-    }
-    else {
-      var start = IsCJK(kw.charCodeAt(0)) ? "" : ("((^|\\s)\\S*)");
-      var end = IsCJK(kw.charCodeAt(kw.length - 1)) ? "" : "(" + NOT_W + "|$)";
-      var re = new RegExp(start + kw + end, "ig");
-      var matching;
+    } else {
+      let start = IsCJK(kw.charCodeAt(0)) ? "" : ("((^|\\s)\\S*)");
+      let end = IsCJK(kw.charCodeAt(kw.length - 1)) ? "" : "(" + NOT_W + "|$)";
+      let re = new RegExp(start + kw + end, "ig");
+      let matching;
       while ((matching = re.exec(mailData)) !== null) {
         // Ignore the match if it was in a URL.
         if (!(/^(https?|ftp):\/\//i.test(matching[0].trim()))) {
           keywordsFound.push(keywordsArray[i]);
           break;
         }
       }
     }
   }
   return keywordsFound;
 }
 
+// This file is also used as a Worker.
+/* exported onmessage */
+/* globals postMessage */
 var onmessage = function(event) {
   var keywordsFound = AttachmentChecker.getAttachmentKeywords(event.data[0], event.data[1]);
   postMessage(keywordsFound);
 };
 
--- a/mail/base/modules/DBViewWrapper.jsm
+++ b/mail/base/modules/DBViewWrapper.jsm
@@ -1,25 +1,23 @@
 /* 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/. */
 
-this.EXPORTED_SYMBOLS = ['DBViewWrapper', 'IDBViewWrapperListener'];
+this.EXPORTED_SYMBOLS = ["DBViewWrapper", "IDBViewWrapperListener"];
 
 ChromeUtils.import("resource:///modules/MailServices.jsm");
-ChromeUtils.import("resource:///modules/MailViewManager.jsm");
+const {
+  MailViewConstants,
+  MailViewManager,
+} = ChromeUtils.import("resource:///modules/MailViewManager.jsm", null);
 ChromeUtils.import("resource:///modules/SearchSpec.jsm");
-ChromeUtils.import("resource:///modules/virtualFolderWrapper.js");
-
-var nsMsgFolderFlags = Ci.nsMsgFolderFlags;
-var nsMsgViewType = Ci.nsMsgViewType;
-var nsMsgViewFlagsType = Ci.nsMsgViewFlagsType;
-var nsMsgViewSortType = Ci.nsMsgViewSortType;
-var nsMsgViewSortOrder = Ci.nsMsgViewSortOrder;
-var nsMsgMessageFlags = Ci.nsMsgMessageFlags;
+const {
+  VirtualFolderHelper,
+} = ChromeUtils.import("resource:///modules/virtualFolderWrapper.js", null);
 
 var MSG_VIEW_FLAG_DUMMY = 0x20000000;
 
 var nsMsgViewIndex_None = 0xffffffff;
 
 /**
  * Helper singleton for DBViewWrapper that tells instances when something
  *  interesting is happening to the folder(s) they care about.  The rationale
@@ -49,17 +47,17 @@ var FolderNotificationHelper = {
    */
    _curiousWrappers: [],
 
   /**
    * Initialize our listeners.  We currently don't bother cleaning these up
    *  because we are a singleton and if anyone imports us, they probably want
    *  us for as long as their application so shall live.
    */
-  _init: function FolderNotificationHelper__init() {
+  _init() {
     // register with the session for our folded loaded notifications
     MailServices.mailSession.AddFolderListener(this,
                                                Ci.nsIFolderListener.event |
                                                Ci.nsIFolderListener.intPropertyChanged);
 
     // register with the notification service for deleted folder notifications
     MailServices.mfn.addListener(this,
       Ci.nsIMsgFolderNotificationService.folderDeleted |
@@ -69,47 +67,42 @@ var FolderNotificationHelper = {
   },
 
   /**
    * Call updateFolder, and assuming all goes well, request that the provided
    *  FolderDisplayWidget be notified when the folder is loaded.  This method
    *  performs the updateFolder call for you so there is less chance of leaking.
    * In the event the updateFolder call fails, we will propagate the exception.
    */
-  updateFolderAndNotifyOnLoad:
-      function FolderNotificationHelper_notifyOnLoad(aFolder,
-                                                     aFolderDisplay,
-                                                     aMsgWindow) {
+  updateFolderAndNotifyOnLoad(aFolder, aFolderDisplay, aMsgWindow) {
     // set up our datastructure first in case of wacky event sequences
     let folderURI = aFolder.URI;
     let wrappers = this._pendingFolderUriToViewWrapperLists[folderURI];
     if (wrappers == null)
       wrappers = this._pendingFolderUriToViewWrapperLists[folderURI] = [];
     wrappers.push(aFolderDisplay);
     try {
       aFolder.updateFolder(aMsgWindow);
-    }
-    catch (ex) {
+    } catch (ex) {
       // uh-oh, that didn't work.  tear down the data structure...
       wrappers.pop();
       if (wrappers.length == 0)
         delete this._pendingFolderUriToViewWrapperLists[folderURI];
       throw ex;
     }
   },
 
   /**
    * Request notification of every little thing these folders do.
    *
    * @param aFolders The folders.
    * @param aNotherFolder A folder that may or may not be in aFolders.
    * @param aViewWrapper The view wrapper that is up to no good.
    */
-  stalkFolders: function FolderNotificationHelper_stalkFolders(
-      aFolders, aNotherFolder, aViewWrapper) {
+  stalkFolders(aFolders, aNotherFolder, aViewWrapper) {
     let folders = aFolders ? aFolders.concat() : [];
     if (aNotherFolder && !folders.includes(aNotherFolder))
       folders.push(aNotherFolder);
     for (let folder of folders) {
       let wrappers = this._interestedWrappers[folder.URI];
       if (wrappers == null)
         wrappers = this._interestedWrappers[folder.URI] = [];
       wrappers.push(aViewWrapper);
@@ -117,43 +110,42 @@ var FolderNotificationHelper = {
   },
 
   /**
    * Request notification of every little thing every folder does.
    *
    * @param aViewWrapper - the viewWrapper interested in every notification.
    *                       This will be a search results view of some sort.
    */
-  noteCuriosity: function FolderNotificationHelper_noteCuriosity(aViewWrapper) {
+  noteCuriosity(aViewWrapper) {
     this._curiousWrappers.push(aViewWrapper);
   },
 
   /**
    * Removal helper for use by removeNotifications.
    *
    * @param aTable The table mapping URIs to list of view wrappers.
    * @param aFolder The folder we care about.
    * @param aViewWrapper The view wrapper of interest.
    */
-  _removeWrapperFromListener: function(aTable, aFolder, aViewWrapper) {
+  _removeWrapperFromListener(aTable, aFolder, aViewWrapper) {
     let wrappers = aTable[aFolder.URI];
     if (wrappers) {
       let index = wrappers.indexOf(aViewWrapper);
       if (index >= 0)
       wrappers.splice(index, 1);
       if (wrappers.length == 0)
         delete aTable[aFolder.URI];
     }
   },
   /**
    * Remove notification requests on the provided folders by the given view
    *  wrapper.
    */
-  removeNotifications: function FolderNotificationHelper_removeNotifications(
-      aFolders, aViewWrapper) {
+  removeNotifications(aFolders, aViewWrapper) {
     if (!aFolders) {
       this._curiousWrappers.splice(this._curiousWrappers.indexOf(aViewWrapper), 1);
       return;
     }
     for (let folder of aFolders) {
       this._removeWrapperFromListener(
         this._interestedWrappers, folder, aViewWrapper);
       this._removeWrapperFromListener(
@@ -161,90 +153,78 @@ var FolderNotificationHelper = {
     }
   },
 
   /**
    * @return true if there are any listeners still registered.  This is intended
    *     to support debugging code.  If you are not debug code, you are a bad
    *     person/code.
    */
-  haveListeners: function FolderNotificationHelper_haveListeners() {
-    for (let folderURI in this._pendingFolderUriToViewWrapperLists) {
-      let wrappers = this._pendingFolderUriToViewWrapperLists[folderURI];
+  haveListeners() {
+    if (Object.keys(this._pendingFolderUriToViewWrapperLists).length > 0)
       return true;
-    }
-    for (let folderURI in this._interestedWrappers) {
-      let wrappers = this._interestedWrappers[folderURI];
+    if (Object.keys(this._interestedWrappers).length > 0)
       return true;
-    }
     return this._curiousWrappers.length != 0;
   },
 
   /* ***** Notifications ***** */
-  _notifyHelper: function FolderNotificationHelper__notifyHelper(aFolder,
-                                                                 aHandlerName) {
+  _notifyHelper(aFolder, aHandlerName) {
     let wrappers = this._interestedWrappers[aFolder.URI];
     if (wrappers) {
       // clone the list to avoid confusing mutation by listeners
       for (let wrapper of wrappers.concat()) {
         wrapper[aHandlerName](aFolder);
       }
     }
     for (let wrapper of this._curiousWrappers)
       wrapper[aHandlerName](aFolder);
   },
 
-  OnItemEvent: function FolderNotificationHelper_OnItemEvent(
-      aFolder, aEvent) {
+  OnItemEvent(aFolder, aEvent) {
     if (aEvent == "FolderLoaded") {
       let folderURI = aFolder.URI;
       let widgets = this._pendingFolderUriToViewWrapperLists[folderURI];
       if (widgets) {
         for (let widget of widgets) {
           // we are friends, this is an explicit relationship.
           // (we don't use a generic callback mechanism because the 'this' stuff
           //  gets ugly and no one else should be hooking in at this level.)
           try {
             widget._folderLoaded(aFolder);
-          }
-          catch (ex) {
+          } catch (ex) {
             dump("``` EXCEPTION DURING NOTIFY: " + ex.fileName + ":" +
                  ex.lineNumber + ": " + ex + "\n");
             if (ex.stack)
               dump("STACK: " + ex.stack + "\n");
             Cu.reportError(ex);
           }
         }
         delete this._pendingFolderUriToViewWrapperLists[folderURI];
       }
-    }
-    else if (aEvent == "AboutToCompact") {
+    } else if (aEvent == "AboutToCompact") {
       this._notifyHelper(aFolder, "_aboutToCompactFolder");
-    }
-    else if (aEvent == "CompactCompleted") {
+    } else if (aEvent == "CompactCompleted") {
       this._notifyHelper(aFolder, "_compactedFolder");
-    }
-    else if (aEvent == "DeleteOrMoveMsgCompleted") {
+    } else if (aEvent == "DeleteOrMoveMsgCompleted") {
       this._notifyHelper(aFolder, "_deleteCompleted");
-    }
-    else if (aEvent == "DeleteOrMoveMsgFailed") {
+    } else if (aEvent == "DeleteOrMoveMsgFailed") {
       this._notifyHelper(aFolder, "_deleteFailed");
-    }
-    else if (aEvent == "RenameCompleted") {
+    } else if (aEvent == "RenameCompleted") {
       this._notifyHelper(aFolder, "_renameCompleted");
     }
   },
 
-  OnItemIntPropertyChanged: function(aFolder, aProperty, aOldValue, aNewValue) {
+  OnItemIntPropertyChanged(aFolder, aProperty, aOldValue, aNewValue) {
     if ((aProperty == "TotalMessages") ||
         (aProperty == "TotalUnreadMessages"))
       this._notifyHelper(aFolder, "_messageCountsChanged");
   },
 
-  _folderMoveHelper: function(aOldFolder, aNewFolder) {
+  _folderMoveHelper(aOldFolder, aNewFolder) {
     let oldURI = aOldFolder.URI;
     let newURI = aNewFolder.URI;
     // fix up our listener tables.
     if (oldURI in this._pendingFolderUriToViewWrapperLists) {
       this._pendingFolderUriToViewWrapperLists[newURI] =
         this._pendingFolderUriToViewWrapperLists[oldURI];
       delete this._pendingFolderUriToViewWrapperLists[oldURI];
     }
@@ -261,32 +241,28 @@ var FolderNotificationHelper = {
         wrapper._folderMoved(aOldFolder, aNewFolder);
       }
     }
   },
 
   /**
    * Update our URI mapping tables when renames happen.
    */
-  folderRenamed: function FolderNotificationHelper_folderRenamed(aOrigFolder,
-                                                                 aNewFolder) {
+  folderRenamed(aOrigFolder, aNewFolder) {
     this._folderMoveHelper(aOrigFolder, aNewFolder);
   },
 
-  folderMoveCopyCompleted:
-      function FolderNotificationHelper_folderMoveCopyCompleted(aMove,
-                                                                aSrcFolder,
-                                                                aDestFolder) {
+  folderMoveCopyCompleted(aMove, aSrcFolder, aDestFolder) {
      if (aMove) {
        let aNewFolder = aDestFolder.getChildNamed(aSrcFolder.prettyName);
        this._folderMoveHelper(aSrcFolder, aNewFolder);
      }
   },
 
-  folderDeleted: function FolderNotificationHelper_folderDeleted(aFolder) {
+  folderDeleted(aFolder) {
     let wrappers = this._interestedWrappers[aFolder.URI];
     if (wrappers) {
       // clone the list to avoid confusing mutation by listeners
       for (let wrapper of wrappers.concat()) {
         wrapper._folderDeleted(aFolder);
       }
       // if the folder is deleted, it's not going to ever do anything again
       delete this._interestedWrappers[aFolder.URI];
@@ -340,142 +316,140 @@ IDBViewWrapperListener.prototype = {
    * For the record, this functionality should not remotely be in the core.
    *
    * @param aMsgFolder The folder we are leaving and are unsure if we should
    *     mark all its messages read.  I pass the folder instead of the server
    *     type because having a crazy feature like this will inevitably lead to
    *     a more full-featured crazy feature (why not on a per-folder basis, eh?)
    * @return true if we should mark all the dudes as read, false if not.
    */
-  shouldMarkMessagesReadOnLeavingFolder: function (aMsgFolder) {
+  shouldMarkMessagesReadOnLeavingFolder(aMsgFolder) {
     return false;
   },
 
   /* ===== Event Notifications ===== */
   /* === Status Changes === */
   /**
    * We tell you when we start and stop loading the folder.  This is a good
    *  time to mess with the hour-glass cursor machinery if you are inclined to
    *  do so.
    */
-  onFolderLoading: function (aIsFolderLoading) {
-
+  onFolderLoading(aIsFolderLoading) {
   },
 
   /**
    * We tell you when we start and stop searching.  This is a good time to mess
    *  with progress spinners (meteors) and the like, if you are so inclined.
    */
-  onSearching: function (aIsSearching) {
-
+  onSearching(aIsSearching) {
   },
 
   /**
    * This event is generated when a new view has been created.  It is intended
    *  to be used to provide the MsgCreateDBView notification so that custom
    *  columns can add themselves to the view.
    * The notification is not generated by the DBViewWrapper itself because this
    *  is fundamentally a UI issue.  Additionally, because the MsgCreateDBView
    *  notification consumers assume gDBView whose exposure is affected by tabs,
    *  the tab logic needs to be involved.
    */
-  onCreatedView: function() {
+  onCreatedView() {
   },
 
   /**
    * This event is generated just before we close/destroy a message view.
    *
    * @param aFolderIsComingBack Indicates whether we are planning to create a
    *     new view to display the same folder after we destroy this view.  This
    *     will be the case unless we are switching to display a new folder or
    *     closing the view wrapper entirely.
    */
-  onDestroyingView: function(aFolderIsComingBack) {
+  onDestroyingView(aFolderIsComingBack) {
   },
 
   /**
    * Generated when we are loading information about the folder from its
    *  dbFolderInfo.  The dbFolderInfo object is passed in.
    * The DBViewWrapper has already restored its state when this function is
    *  called, but has not yet created the dbView.  A view update is in process,
    *  so the view settings can be changed and will take effect when the update
    *  is closed.
    * |onDisplayingFolder| is the next expected notification following this
    *  notification.
    */
-  onLoadingFolder: function(aDbFolderInfo) {
+  onLoadingFolder(aDbFolderInfo) {
   },
 
   /**
    * Generated when the folder is being entered for display.  This is the chance
    *  for the listener to affect any UI-related changes to the folder required.
    *  Currently, this just means setting the header cache size (which needs to
    *  be proportional to the number of lines in the tree view, and is thus a
    *  UI issue.)
    * The dbView has already been created and is valid when this function is
    *  called.
    * |onLoadingFolder| is called before this notification.
    */
-  onDisplayingFolder: function() {
+  onDisplayingFolder() {
   },
 
   /**
    * Generated when we are leaving a folder.
    */
-  onLeavingFolder: function() {
+  onLeavingFolder() {
   },
 
   /**
    * Things to do once all the messages that should show up in a folder have
    *  shown up.  For a real folder, this happens when the folder is entered.
    *  For a (multi-folder) virtual folder, this happens when the search
    *  completes.
    * You may get onMessagesLoaded called with aAll false immediately after
    * the view is opened. You will definitely get onMessagesLoaded(true)
    * when we've finished getting the headers for the view.
    */
-  onMessagesLoaded: function(aAll) {
+  onMessagesLoaded(aAll) {
   },
 
   /**
    * The mail view changed.  The mail view widget is likely to care about this.
    */
-  onMailViewChanged: function() {
+  onMailViewChanged() {
   },
 
   /**
    * The active sort changed, and that is all that changed.  If the sort is
    *  changing because the view is being destroyed and re-created, this event
    *  will not be generated.
    */
-  onSortChanged: function() {
+  onSortChanged() {
   },
 
   /**
    * This event is generated when messages in one of the folders backing the
    *  view have been removed by message moves / deletion.  If there is a search
    *  in effect, it is possible that the removed messages were not visible in
    *  the view in the first place.
    */
-  onMessagesRemoved: function () {
+  onMessagesRemoved() {
   },
 
   /**
    * Like onMessagesRemoved, but something went awry in the move/deletion and
    *  it failed.  Although this is not a very interesting event on its own,
    *  it is useful in cases where the listener was expecting an
    *  onMessagesRemoved and might need to clean some state up.
    */
-  onMessageRemovalFailed: function () {
+  onMessageRemovalFailed() {
   },
 
   /**
    * The total message count or total unread message counts changed.
    */
-  onMessageCountsChanged: function () {
+  onMessageCountsChanged() {
   },
 };
 
 /**
  * Encapsulates everything related to working with our nsIMsgDBView
  *  implementations.
  *
  * Things we do not do and why we do not do them:
@@ -502,17 +476,17 @@ function DBViewWrapper(aListener) {
   // see the _viewFlags getter and setter for info on our use of __viewFlags.
   this.__viewFlags = null;
 
   /**
    * It's possible to support grouped view thread expand/collapse, and also sort
    * by thread despite the back end (see nsMsgQuickSearchDBView::SortThreads).
    * Also, nsMsgQuickSearchDBView does not respect the kExpandAll flag, fix that.
    */
-  this._threadExpandAll = true,
+  this._threadExpandAll = true;
 
   this.dbView = null;
   this.search = null;
 
   this._folderLoading = false;
   this._searching = false;
 }
 DBViewWrapper.prototype = {
@@ -573,31 +547,31 @@ DBViewWrapper.prototype = {
   /**
    * Check if the folder in question backs the currently displayed folder.  For
    *  a virtual folder, this is a test of whether the virtual folder includes
    *  messages from the given folder.  For a 'real' single folder, this is
    *  effectively a test against displayedFolder.
    * If you want to see if the displayed folder is a folder, just compare
    *  against the displayedFolder attribute.
    */
-  isUnderlyingFolder: function DBViewWrapper_isUnderlyingFolder(aFolder) {
+  isUnderlyingFolder(aFolder) {
     return this._underlyingFolders.some(underlyingFolder => aFolder == underlyingFolder);
   },
 
   /**
    * Refresh the view by re-creating the view.  You would do this to get rid of
    *  messages that no longer match the view but are kept around for view
    *  stability reasons.  (In other words, in an unread-messages view, you would
    *  go insane if when you clicked on a message it immediately disappeared
    *  because it no longer matched.)
    * This method was adding for testing purposes and does not have a (legacy) UI
    *  reason for existing.  (The 'open' method is intended to behave identically
    *  to the legacy UI if you click on the currently displayed folder.)
    */
-  refresh: function DBViewWrapper_refresh() {
+  refresh() {
     this._applyViewChanges();
   },
 
   /**
    * Null out the folder's database to avoid memory bloat if we don't have a
    *  reason to keep the database around.  Currently, we keep all Inboxes
    *  around and null out everyone else.  This is a standard stopgap measure
    *  until we have something more clever going on.
@@ -610,27 +584,27 @@ DBViewWrapper.prototype = {
    *
    * Another heuristic we could theoretically use is use the mail session's
    *  isFolderOpenInWindow call, except that uses the outmoded concept that each
    *  window will have at most one folder open.  So nuts to that.
    *
    * Note: regrettably a unit test cannot verify that we did this; msgDatabase
    *  is a getter that will always try and load the message database!
    */
-  _releaseFolderDatabase: function DBViewWrapper__nullFolderDatabase(aFolder) {
-    if (!aFolder.isSpecialFolder(nsMsgFolderFlags.Inbox, false))
+  _releaseFolderDatabase(aFolder) {
+    if (!aFolder.isSpecialFolder(Ci.nsMsgFolderFlags.Inbox, false))
       aFolder.msgDatabase = null;
   },
 
   /**
    * Clone this DBViewWrapper and its underlying nsIMsgDBView.
    *
    * @param aListener {IDBViewWrapperListener} The listener to use on the new view.
    */
-  clone: function DBViewWrapper_clone(aListener) {
+  clone(aListener) {
     let doppel = new DBViewWrapper(aListener);
 
     // -- copy attributes
     doppel.displayedFolder = this.displayedFolder;
     doppel._underlyingData = this._underlyingData;
     doppel._underlyingFolders = this._underlyingFolders ?
                                   this._underlyingFolders.concat() : null;
     doppel._syntheticView = this._syntheticView;
@@ -674,17 +648,17 @@ DBViewWrapper.prototype = {
    *  the resources associated with this view wrapper.  You would not do this
    *  for UI reasons like the user de-selecting the node in the tree; we should
    *  always be displaying something when used in a UI context!
    *
    * @param aFolderIsDead If true, tells us not to try and tidy up on our way
    *     out by virtue of the fact that the folder is dead and should not be
    *     messed with.
    */
-  close: function DBViewWrapper_close(aFolderIsDead) {
+  close(aFolderIsDead) {
     if (this.displayedFolder != null) {
       // onLeavingFolder does all the application-level stuff related to leaving
       //  the folder (marking as read, etc.)  We only do this when the folder
       //  is not dead (for obvious reasons).
       if (!aFolderIsDead) {
         // onLeavingFolder must be called before we potentially null out its
         //  msgDatabase, which we will do in the upcoming underlyingFolders loop
         this.onLeavingFolder(); // application logic
@@ -740,17 +714,17 @@ DBViewWrapper.prototype = {
 
     this.search = null;
   },
 
   /**
    * Open the passed-in nsIMsgFolder folder.  Use openSynthetic for synthetic
    *  view providers.
    */
-  open: function DBViewWrapper_open(aFolder) {
+  open(aFolder) {
     if (aFolder == null) {
       this.close();
       return;
     }
 
     // If we are in the same folder, there is nothing to do unless we are a
     //  virtual folder.  Virtual folders apparently want to try and get updated.
     if (this.displayedFolder == aFolder) {
@@ -794,17 +768,17 @@ DBViewWrapper.prototype = {
     //  is already outstanding.
     if (this.shouldShowMessagesForFolderImmediately())
       this._enterFolder();
   },
 
   /**
    * Open a synthetic view provider as backing our view.
    */
-  openSynthetic: function DBViewWrapper_openSynthetic(aSyntheticView) {
+  openSynthetic(aSyntheticView) {
     this.close();
 
     this._underlyingData = this.kUnderlyingSynthetic;
     this._syntheticView = aSyntheticView;
 
     this.search = new SearchSpec(this);
     this._sort = this._syntheticView.defaultSort.concat();
 
@@ -815,35 +789,35 @@ DBViewWrapper.prototype = {
 
   /**
    * Makes us irrevocavbly be a search view, for use in search windows.
    *  Once you call this, you are not allowed to use us for anything
    *  but a search view!
    * We add a 'searchFolders' property that allows you to control what
    *  folders we are searching over.
    */
-  openSearchView: function DBViewWrapper_openSearchView() {
+  openSearchView() {
     this.close();
 
     this._underlyingData = this.kUnderlyingSearchView;
     this._underlyingFolders = [];
 
     let dis = this;
-    this.__defineGetter__('searchFolders', function() {
+    this.__defineGetter__("searchFolders", function() {
                             return dis._underlyingFolders;
                           });
-    this.__defineSetter__('searchFolders', function(aSearchFolders) {
+    this.__defineSetter__("searchFolders", function(aSearchFolders) {
                             dis._underlyingFolders = aSearchFolders;
                             dis._applyViewChanges();
                           });
 
     this.search = new SearchSpec(this);
     // the search view uses the order in which messages are added as the
     //  order by default.
-    this._sort = [[nsMsgViewSortType.byNone, nsMsgViewSortOrder.ascending]];
+    this._sort = [[Ci.nsMsgViewSortType.byNone, Ci.nsMsgViewSortOrder.ascending]];
 
     FolderNotificationHelper.noteCuriosity(this);
     this._applyViewChanges();
   },
 
   get folderLoading() {
     return this._folderLoading;
   },
@@ -888,77 +862,74 @@ DBViewWrapper.prototype = {
    *   there is an obvious hole in this logic because of the virtual folder case
    *   above.
    *
    * @pre this.folderDisplayed is the folder we are talking about.
    *
    * @return true if the folder should be shown immediately, false if we should
    *     wait for updateFolder to complete.
    */
-  shouldShowMessagesForFolderImmediately:
-      function DBViewWrapper_showShowMessagesForFolderImmediately() {
+  shouldShowMessagesForFolderImmediately() {
     return (this.isVirtual ||
             !(this._underlyingFolders == null ||
               this.listener.shouldDeferMessageDisplayUntilAfterServerConnect));
   },
   /**
    * Extract information about the view from the dbFolderInfo (e.g., sort type,
    * sort order, current view flags, etc), and save in the view wrapper.
    */
-  _prepareToLoadView:
-      function DBViewWrapper_prepareToLoadView(msgDatabase, aFolder) {
+  _prepareToLoadView(msgDatabase, aFolder) {
     let dbFolderInfo = msgDatabase.dBFolderInfo;
     // - retrieve persisted sort information
     this._sort = [[dbFolderInfo.sortType, dbFolderInfo.sortOrder]];
 
     // - retrieve persisted display settings
     this.__viewFlags = dbFolderInfo.viewFlags;
     // - retrieve persisted thread last expanded state.
-    this._threadExpandAll = Boolean(this.__viewFlags & nsMsgViewFlagsType.kExpandAll);
+    this._threadExpandAll = Boolean(this.__viewFlags & Ci.nsMsgViewFlagsType.kExpandAll);
 
     // Make sure the threaded bit is set if group-by-sort is set.  The views
     //  encode 3 states in 2-bits, and we want to avoid that odd-man-out
     //  state.
     // The expand flag must be set when opening a single virtual folder
     //  (quicksearch) in grouped view. The user's last set expand/collapse state
     //  for grouped/threaded in this use case is restored later.
-    if (this.__viewFlags & nsMsgViewFlagsType.kGroupBySort) {
-      this.__viewFlags |= nsMsgViewFlagsType.kThreadedDisplay;
-      this.__viewFlags |= nsMsgViewFlagsType.kExpandAll;
+    if (this.__viewFlags & Ci.nsMsgViewFlagsType.kGroupBySort) {
+      this.__viewFlags |= Ci.nsMsgViewFlagsType.kThreadedDisplay;
+      this.__viewFlags |= Ci.nsMsgViewFlagsType.kExpandAll;
       this._ensureValidSort();
     }
 
     // See if the last-used view was one of the special views.  If so, put us in
     //  that special view mode.  We intentionally do this after restoring the
     //  view flags because _setSpecialView enforces threading.
     // The nsMsgDBView is the one who persists this information for us.  In this
     //  case the nsMsgThreadedDBView superclass of the special views triggers it
     //  when opened.
     let viewType = dbFolderInfo.viewType;
-    if ((viewType == nsMsgViewType.eShowThreadsWithUnread) ||
-        (viewType == nsMsgViewType.eShowWatchedThreadsWithUnread))
+    if ((viewType == Ci.nsMsgViewType.eShowThreadsWithUnread) ||
+        (viewType == Ci.nsMsgViewType.eShowWatchedThreadsWithUnread))
       this._setSpecialView(viewType);
 
     // - retrieve virtual folder configuration
-    if (aFolder.flags & nsMsgFolderFlags.Virtual) {
+    if (aFolder.flags & Ci.nsMsgFolderFlags.Virtual) {
       let virtFolder = VirtualFolderHelper.wrapVirtualFolder(aFolder);
       // Filter out the server roots; they only exist for UI reasons.
       this._underlyingFolders =
         virtFolder.searchFolders.filter(folder => !folder.isServer);
       this._underlyingData = (this._underlyingFolders.length > 1) ?
                              this.kUnderlyingMultipleFolder :
                              this.kUnderlyingRealFolder;
 
       // figure out if we are using online IMAP searching
       this.search.onlineSearch = virtFolder.onlineSearch;
 
       // retrieve and chew the search query
       this.search.virtualFolderTerms = virtFolder.searchTerms;
-    }
-    else {
+    } else {
       this._underlyingData = this.kUnderlyingRealFolder;
       this._underlyingFolders = [this.displayedFolder];
     }
 
     FolderNotificationHelper.stalkFolders(this._underlyingFolders,
                                           this.displayedFolder,
                                           this);
 
@@ -971,45 +942,44 @@ DBViewWrapper.prototype = {
       // "0" and "1" are all and unread views, respectively, from 2.0
       if (mailViewTag && mailViewTag != "0" && mailViewTag != "1") {
         // the tag gets stored with a ":" on the front, presumably done
         //  as a means of name-spacing that was never subsequently leveraged.
         if (mailViewTag.startsWith(":"))
           mailViewTag = mailViewTag.substr(1);
         // (the true is so we don't persist)
         this.setMailView(MailViewConstants.kViewItemTags, mailViewTag, true);
-      }
-      // otherwise it's just an index. we kinda-sorta migrate from old-school
-      //  $label tags, except someone reused one of the indices for
-      //  kViewItemNotDeleted, which means that $label2 can no longer be
-      //  migrated.
-      else {
+      } else {
+        // otherwise it's just an index. we kinda-sorta migrate from old-school
+        //  $label tags, except someone reused one of the indices for
+        //  kViewItemNotDeleted, which means that $label2 can no longer be
+        //  migrated.
         let mailViewIndex = dbFolderInfo.getUint32Property(
                               MailViewConstants.kViewCurrent,
                               MailViewConstants.kViewItemAll);
         // label migration per above
         if ((mailViewIndex == MailViewConstants.kViewItemTags) ||
             ((MailViewConstants.kViewItemTags + 2 <= mailViewIndex) &&
              (mailViewIndex < MailViewConstants.kViewItemVirtual)))
           this.setMailView(MailViewConstants.kViewItemTags,
-                           "$label" + (mailViewIndex-1));
+                           "$label" + (mailViewIndex - 1));
         else
           this.setMailView(mailViewIndex);
       }
     }
 
     this.listener.onLoadingFolder(dbFolderInfo);
   },
 
   /**
    * Creates a view appropriate to the current settings of the folder display
    *  widget, returning it.  The caller is responsible to assign the result to
    *  this.dbView (or whatever it wants to do with it.)
    */
-  _createView: function DBViewWrapper__createView() {
+  _createView() {
     let dbviewContractId = "@mozilla.org/messenger/msgdbview;1?type=";
 
     // we will have saved these off when closing our view
     let viewFlags = this.__viewFlags || 0;
 
     // real folders are subject to the most interest set of possibilities...
     if (this._underlyingData == this.kUnderlyingRealFolder) {
       // quick-search inherits from threaded which inherits from group, so this
@@ -1019,36 +989,34 @@ DBViewWrapper.prototype = {
       else if (this.showGroupedBySort)
         dbviewContractId += "group";
       else if (this.specialViewThreadsWithUnread)
         dbviewContractId += "threadswithunread";
       else if (this.specialViewWatchedThreadsWithUnread)
         dbviewContractId += "watchedthreadswithunread";
       else
         dbviewContractId += "threaded";
-    }
-    // if we're dealing with virtual folders, the answer is always an xfvf
-    else if (this._underlyingData == this.kUnderlyingMultipleFolder) {
+    } else if (this._underlyingData == this.kUnderlyingMultipleFolder) {
+      // if we're dealing with virtual folders, the answer is always an xfvf
       dbviewContractId += "xfvf";
-    }
-    else { // kUnderlyingSynthetic or kUnderlyingSearchView
+    } else { // kUnderlyingSynthetic or kUnderlyingSearchView
       dbviewContractId += "search";
     }
 
     // and now zero the saved-off flags.
     this.__viewFlags = null;
 
     let dbView = Cc[dbviewContractId]
                    .createInstance(Ci.nsIMsgDBView);
     dbView.init(this.listener.messenger, this.listener.msgWindow,
                 this.listener.threadPaneCommandUpdater);
     // use the least-specific sort so we can clock them back through to build up
     //  the correct sort order...
     let [sortType, sortOrder, sortCustomCol] =
-      this._getSortDetails(this._sort.length-1);
+      this._getSortDetails(this._sort.length - 1);
     let outCount = {};
     // when the underlying folder is a single real folder (virtual or no), we
     //  tell the view about the underlying folder.
     if (this.isSingleFolder) {
       // If the folder is virtual, m_viewFolder needs to be set before the
       //  folder is opened, otherwise persisted sort info will not be restored
       //  from the right dbFolderInfo. The use case is for a single folder
       //  backed saved search. Currently, sort etc. changes in quick filter are
@@ -1066,49 +1034,48 @@ DBViewWrapper.prototype = {
       //  dbFolderInfo.)  This also goes for cases where the quick search is
       //  active; the C++ code explicitly nulls out the view folder for no
       //  good/documented reason, so we need to set it again if we want changes
       //  made with the quick filter applied.  (We don't just change the C++
       //  code because there could be SeaMonkey fallout.)  See bug 502767 for
       //  info about the quick-search part of the problem.
       if (this.search.hasSearchTerms)
         dbView.viewFolder = this.displayedFolder;
-    }
-    // when we're dealing with a multi-folder virtual folder, we just tell the
-    //  db view about the display folder.  (It gets its own XFVF view, so it
-    //  knows what to do.)
-    // and for a synthetic folder, displayedFolder is null anyways
-    else {
+    } else {
+      // when we're dealing with a multi-folder virtual folder, we just tell the
+      //  db view about the display folder.  (It gets its own XFVF view, so it
+      //  knows what to do.)
+      // and for a synthetic folder, displayedFolder is null anyways
       dbView.open(this.displayedFolder, sortType, sortOrder, viewFlags,
                   outCount);
     }
     if (sortCustomCol)
       dbView.curCustomColumn = sortCustomCol;
 
     // we all know it's a tree view, make sure the interface is available
     //  so no one else has to do this.
     dbView.QueryInterface(Ci.nsITreeView);
 
     // clock through the rest of the sorts, if there are any
-    for (let iSort = this._sort.length - 2; iSort >=0; iSort--) {
+    for (let iSort = this._sort.length - 2; iSort >= 0; iSort--) {
       [sortType, sortOrder, sortCustomCol] = this._getSortDetails(iSort);
       if (sortCustomCol)
         dbView.curCustomColumn = sortCustomCol;
       dbView.sort(sortType, sortOrder);
     }
 
     return dbView;
   },
 
   /**
    * Callback method invoked by FolderNotificationHelper when our folder is
    *  loaded.  Assuming we are still interested in the folder, we enter the
    *  folder via _enterFolder.
    */
-  _folderLoaded: function DBViewWrapper__folderLoaded(aFolder) {
+  _folderLoaded(aFolder) {
     if (aFolder == this.displayedFolder) {
       this.folderLoading = false;
       // If _underlyingFolders is null, DBViewWrapper_open probably got
       // an exception trying to open the db, but after reparsing the local
       // folder, we should have a db, so set up the view based on info
       // from the db.
       if (this._underlyingFolders == null) {
         this._prepareToLoadView(aFolder.msgDatabase, aFolder);
@@ -1120,17 +1087,17 @@ DBViewWrapper.prototype = {
 
   /**
    * Enter this.displayedFolder if we have not yet entered it.
    *
    * Things we do on entering a folder:
    * - clear the folder's biffState!
    * - set the message database's header cache size
    */
-  _enterFolder: function DBViewWrapper__enterFolder() {
+  _enterFolder() {
     if (this._enteredFolder)
       return;
 
     this.displayedFolder.biffState =
       Ci.nsIMsgFolder.nsMsgBiffState_NoMail;
 
     // we definitely want a view at this point; force the view.
     this._viewUpdateDepth = 0;
@@ -1140,17 +1107,17 @@ DBViewWrapper.prototype = {
 
     this._enteredFolder = true;
   },
 
   /**
    * Renames, moves to the trash, it's all crazy.  We have to update all our
    *  references when this happens.
    */
-  _folderMoved: function DBViewWrapper__folderMoved(aOldFolder, aNewFolder) {
+  _folderMoved(aOldFolder, aNewFolder) {
     if (aOldFolder == this.displayedFolder)
       this.displayedFolder = aNewFolder;
 
     // indexOf doesn't work for this (reliably)
     for (let [i, underlyingFolder] of this._underlyingFolders.entries()) {
       if (aOldFolder == underlyingFolder) {
         this._underlyingFolders[i] = aNewFolder;
         break;
@@ -1167,33 +1134,33 @@ DBViewWrapper.prototype = {
    *  displaying (real or virtual), this closes it.  If we are virtual and
    *  backed by a single folder, this closes us.  If we are backed by multiple
    *  folders, we just update ourselves.  (Currently, cross-folder views are
    *  not clever enough to purge the mooted messages, so we need to do this to
    *  help them out.)
    * We do not update virtual folder definitions as a result of deletion; we are
    *  a display abstraction.  That (hopefully) happens elsewhere.
    */
-  _folderDeleted: function DBViewWrapper__folderDeleted(aFolder) {
+  _folderDeleted(aFolder) {
     // XXX When we empty the trash, we're actually sending a folder deleted
     // notification around. This check ensures we don't think we've really
     // deleted the trash folder in the DBViewWrapper, and that stops nasty
     // things happening, like forgetting we've got the trash folder selected.
-    if (aFolder.isSpecialFolder(nsMsgFolderFlags.Trash, false))
+    if (aFolder.isSpecialFolder(Ci.nsMsgFolderFlags.Trash, false))
       return;
 
     if (aFolder == this.displayedFolder) {
       this.close();
       return;
     }
 
     // indexOf doesn't work for this (reliably)
     for (let [i, underlyingFolder] of this._underlyingFolders.entries()) {
       if (aFolder == underlyingFolder) {
-        this._underlyingFolders.splice(i,1);
+        this._underlyingFolders.splice(i, 1);
         break;
       }
     }
 
     if (this._underlyingFolders.length == 0) {
       this.close();
       return;
     }
@@ -1203,17 +1170,17 @@ DBViewWrapper.prototype = {
   },
 
   /**
    * Compacting a local folder nukes its message keys, requiring the view to be
    *  rebuilt.  If the folder is IMAP, it doesn't matter because the UIDs are
    *  the message keys and we can ignore it.  In the local case we want to
    *  notify our listener so they have a chance to save the selected messages.
    */
-  _aboutToCompactFolder: function DBViewWrapper__aboutToCompactFolder(aFolder) {
+  _aboutToCompactFolder(aFolder) {
     // IMAP compaction does not affect us unless we are holding headers
     if (aFolder.server.type == "imap")
       return;
 
     // we will have to re-create the view, so nuke the view now.
     if (this.dbView) {
       this.listener.onDestroyingView(true);
       this.search.dissociateView(this.dbView);
@@ -1221,62 +1188,62 @@ DBViewWrapper.prototype = {
       this.dbView = null;
     }
   },
 
   /**
    * Compaction is all done, let's re-create the view!  (Unless the folder is
    *  IMAP, in which case we are ignoring this event sequence.)
    */
-  _compactedFolder: function DBViewWrapper__compactedFolder(aFolder) {
+  _compactedFolder(aFolder) {
     // IMAP compaction does not affect us unless we are holding headers
     if (aFolder.server.type == "imap")
       return;
 
     this.refresh();
   },
 
   /**
    * DB Views need help to know when their move / deletion operations complete.
    *  This happens in both single-folder and multiple-folder backed searches.
    *  In the latter case, there is potential danger that we tell a view that did
    *  not initiate the move / deletion but has kicked off its own about the
    *  completion and confuse it.  However, that's on the view code.
    */
-  _deleteCompleted: function DBViewWrapper__deleteCompleted(aFolder) {
+  _deleteCompleted(aFolder) {
     if (this.dbView)
       this.dbView.onDeleteCompleted(true);
     this.listener.onMessagesRemoved();
   },
 
   /**
    * See _deleteCompleted for an explanation of what is going on.
    */
-  _deleteFailed: function DBViewWrapper__deleteFailed(aFolder) {
+  _deleteFailed(aFolder) {
     if (this.dbView)
       this.dbView.onDeleteCompleted(false);
     this.listener.onMessageRemovalFailed();
   },
 
-  _forceOpen: function DBViewWrapper__forceOpen(aFolder) {
+  _forceOpen(aFolder) {
     this.displayedFolder = null;
     this.open(aFolder);
   },
 
-  _renameCompleted: function DBViewWrapper__renameCompleted(aFolder) {
+  _renameCompleted(aFolder) {
     if (aFolder == this.displayedFolder)
       this._forceOpen(aFolder);
   },
 
   /**
    * If the displayed folder had its total message count or total unread message
    *  count change, notify the listener.  (Note: only for the display folder;
    *  not the underlying folders!)
    */
-  _messageCountsChanged: function DBViewWrapper__messageCountsChanged(aFolder) {
+  _messageCountsChanged(aFolder) {
     if (aFolder == this.displayedFolder)
       this.listener.onMessageCountsChanged();
   },
 
   /**
    * @return the current set of viewFlags.  This may be:
    * - A modified set of flags that are pending application because a view
    *    update is in effect and we don't want to modify the view when it's just
@@ -1320,51 +1287,49 @@ DBViewWrapper.prototype = {
 
     let setViewFlags = true;
     let reSort = false;
     let oldFlags = this.dbView.viewFlags;
     let changedFlags = oldFlags ^ aViewFlags;
 
     if (this.isVirtual) {
       if (this.isMultiFolder &&
-          (changedFlags & nsMsgViewFlagsType.kThreadedDisplay &&
-           !(changedFlags & nsMsgViewFlagsType.kGroupBySort)))
+          (changedFlags & Ci.nsMsgViewFlagsType.kThreadedDisplay &&
+           !(changedFlags & Ci.nsMsgViewFlagsType.kGroupBySort)))
         reSort = true;
       if (this.isSingleFolder)
         // ugh, and the single folder case needs us to re-apply his sort...
         reSort = true;
-    }
-    else {
+    } else {
       // The regular single folder case.
-      if (changedFlags & (nsMsgViewFlagsType.kGroupBySort |
-                          nsMsgViewFlagsType.kUnreadOnly |
-                          nsMsgViewFlagsType.kShowIgnored)) {
+      if (changedFlags & (Ci.nsMsgViewFlagsType.kGroupBySort |
+                          Ci.nsMsgViewFlagsType.kUnreadOnly |
+                          Ci.nsMsgViewFlagsType.kShowIgnored)) {
         setViewFlags = false;
       }
       // ugh, and the single folder case needs us to re-apply his sort...
       reSort = true;
     }
 
     if (setViewFlags) {
       this.dbView.viewFlags = aViewFlags;
       if (reSort)
         this.dbView.sort(this.dbView.sortType, this.dbView.sortOrder);
       this.listener.onSortChanged();
-    }
-    else {
+    } else {
       this.__viewFlags = aViewFlags;
       this._applyViewChanges();
     }
   },
 
   /**
    * Apply accumulated changes to the view.  If we are in a batch, we do
    *  nothing, relying on endDisplayUpdate to call us.
    */
-  _applyViewChanges: function DBViewWrapper__applyViewChanges() {
+  _applyViewChanges() {
     // if we are in a batch, wait for endDisplayUpdate to be called to get us
     //  out to zero.
     if (this._viewUpdateDepth)
       return;
     // make the dbView stop being a search listener if it is one
     if (this.dbView) {
       // save the view's flags if it has any and we haven't already overridden
       //  them.
@@ -1400,33 +1365,33 @@ DBViewWrapper.prototype = {
     if (!this.searching && !this.folderLoading)
       this.listener.onMessagesLoaded(true);
     else if (this.dbView.numMsgsInView > 0)
       this.listener.onMessagesLoaded(false);
   },
 
   get isMailFolder() {
     return Boolean(this.displayedFolder &&
-                   (this.displayedFolder.flags & nsMsgFolderFlags.Mail));
+                   (this.displayedFolder.flags & Ci.nsMsgFolderFlags.Mail));
   },
 
   get isNewsFolder() {
     return Boolean(this.displayedFolder &&
-                   (this.displayedFolder.flags & nsMsgFolderFlags.Newsgroup));
+                   (this.displayedFolder.flags & Ci.nsMsgFolderFlags.Newsgroup));
   },
 
   get isFeedFolder() {
     return Boolean(this.displayedFolder &&
                    this.displayedFolder.server.type == "rss");
   },
 
-  OUTGOING_FOLDER_FLAGS: nsMsgFolderFlags.SentMail |
-                         nsMsgFolderFlags.Drafts |
-                         nsMsgFolderFlags.Queue |
-                         nsMsgFolderFlags.Templates,
+  OUTGOING_FOLDER_FLAGS: Ci.nsMsgFolderFlags.SentMail |
+                         Ci.nsMsgFolderFlags.Drafts |
+                         Ci.nsMsgFolderFlags.Queue |
+                         Ci.nsMsgFolderFlags.Templates,
   /**
    * @return true if the folder is an outgoing folder by virtue of being a
    *     sent mail folder, drafts folder, queue folder, or template folder,
    *     or being a sub-folder of one of those types of folders.
    */
   get isOutgoingFolder() {
     return this.displayedFolder &&
            this.displayedFolder.isSpecialFolder(this.OUTGOING_FOLDER_FLAGS,
@@ -1437,40 +1402,40 @@ DBViewWrapper.prototype = {
    *     or the descendent of a special outgoing folder.
    */
   get isIncomingFolder() {
     return !this.isOutgoingFolder;
   },
 
   get isVirtual() {
     return Boolean(this.displayedFolder &&
-                   (this.displayedFolder.flags & nsMsgFolderFlags.Virtual));
+                   (this.displayedFolder.flags & Ci.nsMsgFolderFlags.Virtual));
   },
 
   /**
    * Prevent view updates from running until a paired |endViewUpdate| call is
    *  made.  This is an advisory method intended to aid us in performing
    *  redundant view re-computations and does not forbid us from building the
    *  view earlier if we have a good reason.
    * Since calling endViewUpdate will compel a view update when the update
    *  depth reaches 0, you should only call this method if you are sure that
    *  you will need the view to be re-built.  If you are doing things like
    *  changing to/from threaded mode that do not cause the view to be rebuilt,
    *  you should just set those attributes directly.
    */
-  beginViewUpdate: function DBViewWrapper_beginViewUpdate() {
+  beginViewUpdate() {
     this._viewUpdateDepth++;
   },
 
   /**
    * Conclude a paired call to |beginViewUpdate|.  Assuming the view depth has
    *  reached 0 with this call, the view will be re-created with the current
    *  settings.
    */
-  endViewUpdate: function DBViewWrapper_endViewUpdate(aForceLevel) {
+  endViewUpdate(aForceLevel) {
     if (--this._viewUpdateDepth == 0)
       this._applyViewChanges();
     // Avoid pathological situations.
     if (this._viewUpdateDepth < 0)
       this._viewUpdateDepth = 0;
   },
 
   /**
@@ -1489,74 +1454,73 @@ DBViewWrapper.prototype = {
     return this._sort[0][1];
   },
 
   /**
    * @return true if the dominant sort is ascending.
    */
   get isSortedAscending() {
     return this._sort.length &&
-           this._sort[0][1] == nsMsgViewSortOrder.ascending;
+           this._sort[0][1] == Ci.nsMsgViewSortOrder.ascending;
   },
   /**
    * @return true if the dominant sort is descending.
    */
   get isSortedDescending() {
     return this._sort.length &&
-           this._sort[0][1] == nsMsgViewSortOrder.descending;
+           this._sort[0][1] == Ci.nsMsgViewSortOrder.descending;
   },
   /**
    * Indicate if we are sorting by time or something correlated with time.
    *
    * @return true if the dominant sort is by time.
    */
   get sortImpliesTemporalOrdering() {
     if (!this._sort.length)
       return false;
     let sortType = this._sort[0][0];
-    return sortType == nsMsgViewSortType.byDate ||
-           sortType == nsMsgViewSortType.byReceived ||
-           sortType == nsMsgViewSortType.byId ||
-           sortType == nsMsgViewSortType.byThread;
+    return sortType == Ci.nsMsgViewSortType.byDate ||
+           sortType == Ci.nsMsgViewSortType.byReceived ||
+           sortType == Ci.nsMsgViewSortType.byId ||
+           sortType == Ci.nsMsgViewSortType.byThread;
   },
 
-  sortAscending: function() {
+  sortAscending() {
     if (!this.isSortedAscending)
-      this.magicSort(this._sort[0][0], nsMsgViewSortOrder.ascending);
+      this.magicSort(this._sort[0][0], Ci.nsMsgViewSortOrder.ascending);
   },
-  sortDescending: function() {
+  sortDescending() {
     if (!this.isSortedDescending)
-      this.magicSort(this._sort[0][0], nsMsgViewSortOrder.descending);
+      this.magicSort(this._sort[0][0], Ci.nsMsgViewSortOrder.descending);
   },
 
   /**
    * Explicit sort command.  We ignore all previous sort state and only apply
    *  what you tell us.  If you want implied secondary sort, use |magicSort|.
    * You must use this sort command, and never directly call the sort commands
    *  on the underlying db view!  If you do not, make sure to fight us every
    *   step of the way, because we will keep clobbering your manually applied
    *   sort.
    * For secondary and multiple custom column support, a byCustom aSortType and
    *  aSecondaryType must be the column name string.
    */
-  sort: function DBViewWrapper_sort(aSortType, aSortOrder,
-                                    aSecondaryType, aSecondaryOrder) {
+  sort(aSortType, aSortOrder, aSecondaryType, aSecondaryOrder) {
     // For sort changes, do not make a random selection if there is not
     // actually anything selected; some views do this (looking at xfvf).
     if (this.dbView.selection && this.dbView.selection.count == 0)
       this.dbView.selection.currentIndex = -1;
 
     this._sort = [[aSortType, aSortOrder]];
     if (aSecondaryType != null && aSecondaryOrder != null)
       this._sort.push([aSecondaryType, aSecondaryOrder]);
     // make sure the sort won't make the view angry...
     this._ensureValidSort();
     // if we are not in a view update, invoke the sort.
     if ((this._viewUpdateDepth == 0) && this.dbView) {
-      for (let iSort = this._sort.length - 1; iSort >=0; iSort--) {
+      for (let iSort = this._sort.length - 1; iSort >= 0; iSort--) {
         // apply them in the reverse order
         let [sortType, sortOrder, sortCustomCol] = this._getSortDetails(iSort);
         if (sortCustomCol)
           this.dbView.curCustomColumn = sortCustomCol;
         this.dbView.sort(sortType, sortOrder);
       }
       // (only generate the event since we're not in a update batch)
       this.listener.onSortChanged();
@@ -1566,38 +1530,38 @@ DBViewWrapper.prototype = {
   },
 
   /**
    * Logic that compensates for custom column identifiers being provided as
    *  sort types.
    *
    * @return [sort type, sort order, sort custom column name]
    */
-  _getSortDetails: function(aIndex) {
+  _getSortDetails(aIndex) {
     let [sortType, sortOrder] = this._sort[aIndex];
     let sortCustomColumn = null;
     let sortTypeType = typeof(sortType);
     if (sortTypeType != "number") {
       sortCustomColumn = (sortTypeType == "string") ? sortType : sortType.id;
-      sortType = nsMsgViewSortType.byCustom;
+      sortType = Ci.nsMsgViewSortType.byCustom;
     }
 
     return [sortType, sortOrder, sortCustomColumn];
   },
 
   /**
    * Accumulates implied secondary sorts based on multiple calls to this method.
    *  This is intended to be hooked up to be controlled by the UI.
    * Because we are lazy, we actually just poke the view's sort method and save
    *  the apparent secondary sort.  This also allows perfect compliance with the
    *  way this used to be implemented!
    * For secondary and multiple custom column support, a byCustom aSortType must
    *  be the column name string.
    */
-  magicSort: function DBViewWrapper_magicSort(aSortType, aSortOrder) {
+  magicSort(aSortType, aSortOrder) {
     if (this.dbView) {
       // For sort changes, do not make a random selection if there is not
       // actually anything selected; some views do this (looking at xfvf).
       if (this.dbView.selection && this.dbView.selection.count == 0)
         this.dbView.selection.currentIndex = -1;
 
       // so, the thing we just set obviously will be there
       this._sort = [[aSortType, aSortOrder]];
@@ -1605,19 +1569,19 @@ DBViewWrapper.prototype = {
       this._ensureValidSort();
       // get sort details, handle custom column as string sortType
       let [sortType, sortOrder, sortCustomCol] = this._getSortDetails(0);
       if (sortCustomCol)
         this.dbView.curCustomColumn = sortCustomCol;
       // apply the sort to see what happens secondary-wise
       this.dbView.sort(sortType, sortOrder);
       // there is only a secondary sort if it's not none and not the same.
-      if (this.dbView.secondarySortType != nsMsgViewSortType.byNone &&
+      if (this.dbView.secondarySortType != Ci.nsMsgViewSortType.byNone &&
           (this.dbView.secondarySortType != sortType ||
-           (this.dbView.secondarySortType == nsMsgViewSortType.byCustom &&
+           (this.dbView.secondarySortType == Ci.nsMsgViewSortType.byCustom &&
             this.dbView.secondaryCustomColumn != sortCustomCol)))
         this._sort.push([this.dbView.secondaryCustomColumn || this.dbView.secondarySortType,
                          this.dbView.secondarySortOrder]);
       // only tell our listener if we're not in a view update batch
       if (this._viewUpdateDepth == 0)
         this.listener.onSortChanged();
     }
   },
@@ -1625,145 +1589,145 @@ DBViewWrapper.prototype = {
   /**
    * Make sure the current sort is valid under our other constraints, make it
    *  safe if it is not.  Most specifically, some sorts are illegal when
    *  grouping by sort, and we reset the sort to date in those cases.
    *
    * @param aViewFlags Optional set of view flags to consider instead of the
    *     potentially live view flags.
    */
-  _ensureValidSort: function DBViewWrapper_ensureValidSort(aViewFlags) {
+  _ensureValidSort(aViewFlags) {
     if ((aViewFlags != null ? aViewFlags : this._viewFlags) &
-        nsMsgViewFlagsType.kGroupBySort) {
+        Ci.nsMsgViewFlagsType.kGroupBySort) {
       // We cannot be sorting by thread, id, none, or size.  If we are, switch
       //  to sorting by date.
       for (let sortPair of this._sort) {
         let sortType = sortPair[0];
-        if (sortType == nsMsgViewSortType.byThread ||
-            sortType == nsMsgViewSortType.byId ||
-            sortType == nsMsgViewSortType.byNone ||
-            sortType == nsMsgViewSortType.bySize) {
-          this._sort = [[nsMsgViewSortType.byDate, this._sort[0][1]]];
+        if (sortType == Ci.nsMsgViewSortType.byThread ||
+            sortType == Ci.nsMsgViewSortType.byId ||
+            sortType == Ci.nsMsgViewSortType.byNone ||
+            sortType == Ci.nsMsgViewSortType.bySize) {
+          this._sort = [[Ci.nsMsgViewSortType.byDate, this._sort[0][1]]];
           break;
         }
       }
     }
   },
 
   /**
    * @return true if we are grouped-by-sort, false if not.  If we are not
    *     grouped by sort, then we are either threaded or unthreaded; check
    *     the showThreaded property to find out which of those it is.
    */
   get showGroupedBySort() {
-    return Boolean(this._viewFlags & nsMsgViewFlagsType.kGroupBySort);
+    return Boolean(this._viewFlags & Ci.nsMsgViewFlagsType.kGroupBySort);
   },
   /**
    * Enable grouped-by-sort which is mutually exclusive with threaded display
    *  (as controlled/exposed by showThreaded).  Grouped-by-sort is not legal
    *  for sorts by thread/id/size/none and enabling this will cause us to change
    *  our sort to by date in those cases.
    */
   set showGroupedBySort(aShowGroupBySort) {
     if (this.showGroupedBySort != aShowGroupBySort) {
       if (aShowGroupBySort) {
         // For virtual single folders, the kExpandAll flag must be set.
         // Do not apply the flag change until we have made the sort safe.
         let viewFlags = this._viewFlags |
-                        nsMsgViewFlagsType.kGroupBySort |
-                        nsMsgViewFlagsType.kExpandAll |
-                        nsMsgViewFlagsType.kThreadedDisplay;
+                        Ci.nsMsgViewFlagsType.kGroupBySort |
+                        Ci.nsMsgViewFlagsType.kExpandAll |
+                        Ci.nsMsgViewFlagsType.kThreadedDisplay;
         this._ensureValidSort(viewFlags);
         this._viewFlags = viewFlags;
+      } else {
+        // maybe we shouldn't do anything in this case?
+        this._viewFlags &= ~(Ci.nsMsgViewFlagsType.kGroupBySort |
+                             Ci.nsMsgViewFlagsType.kThreadedDisplay);
       }
-      // maybe we shouldn't do anything in this case?
-      else
-        this._viewFlags &= ~(nsMsgViewFlagsType.kGroupBySort |
-                             nsMsgViewFlagsType.kThreadedDisplay);
     }
   },
 
   /**
    * Are we showing ignored/killed threads?
    */
   get showIgnored() {
-    return Boolean(this._viewFlags & nsMsgViewFlagsType.kShowIgnored);
+    return Boolean(this._viewFlags & Ci.nsMsgViewFlagsType.kShowIgnored);
   },
   /**
    * Set whether we are showing ignored/killed threads.
    */
   set showIgnored(aShowIgnored) {
     if (this.showIgnored == aShowIgnored)
       return;
 
     if (aShowIgnored)
-      this._viewFlags |= nsMsgViewFlagsType.kShowIgnored;
+      this._viewFlags |= Ci.nsMsgViewFlagsType.kShowIgnored;
     else
-      this._viewFlags &= ~nsMsgViewFlagsType.kShowIgnored;
+      this._viewFlags &= ~Ci.nsMsgViewFlagsType.kShowIgnored;
   },
 
   /**
    * @return true if we are in threaded display (as opposed to grouped or
    *     unthreaded.)
    */
   get showThreaded() {
-    return (this._viewFlags & nsMsgViewFlagsType.kThreadedDisplay) &&
-           !(this._viewFlags & nsMsgViewFlagsType.kGroupBySort);
+    return (this._viewFlags & Ci.nsMsgViewFlagsType.kThreadedDisplay) &&
+           !(this._viewFlags & Ci.nsMsgViewFlagsType.kGroupBySort);
   },
   /**
    * Set us to threaded display mode when set to true.  If we are already in
    *  threaded display mode, we do nothing.  If you want to set us to unthreaded
    *  mode, set |showUnthreaded| to true.  (Because we have three modes of
    *  operation: unthreaded, threaded, and grouped-by-sort, we are a tri-state
    *  and setting us to false is ambiguous.  We should probably be using a
    *  single attribute with three constants...)
    */
   set showThreaded(aShowThreaded) {
     if (this.showThreaded != aShowThreaded) {
       let viewFlags = this._viewFlags;
       if (aShowThreaded)
-        viewFlags |= nsMsgViewFlagsType.kThreadedDisplay;
+        viewFlags |= Ci.nsMsgViewFlagsType.kThreadedDisplay;
       // maybe we shouldn't do anything in this case?
       else
-        viewFlags &= ~nsMsgViewFlagsType.kThreadedDisplay;
+        viewFlags &= ~Ci.nsMsgViewFlagsType.kThreadedDisplay;
       // lose the group bit...
-      viewFlags &= ~nsMsgViewFlagsType.kGroupBySort;
+      viewFlags &= ~Ci.nsMsgViewFlagsType.kGroupBySort;
       this._viewFlags = viewFlags;
     }
   },
 
   /**
    * @return true if we are in unthreaded mode (which means not threaded and
    *     not grouped by sort).
    */
   get showUnthreaded() {
-    return Boolean(!(this._viewFlags & (nsMsgViewFlagsType.kGroupBySort |
-                                        nsMsgViewFlagsType.kThreadedDisplay)));
+    return Boolean(!(this._viewFlags & (Ci.nsMsgViewFlagsType.kGroupBySort |
+                                        Ci.nsMsgViewFlagsType.kThreadedDisplay)));
   },
   /**
    * Set to true to put us in unthreaded mode (which means not threaded and
    *  not grouped by sort).
    */
   set showUnthreaded(aShowUnthreaded) {
     if (this.showUnthreaded != aShowUnthreaded) {
       if (aShowUnthreaded)
-        this._viewFlags &= ~(nsMsgViewFlagsType.kGroupBySort |
-                             nsMsgViewFlagsType.kThreadedDisplay);
+        this._viewFlags &= ~(Ci.nsMsgViewFlagsType.kGroupBySort |
+                             Ci.nsMsgViewFlagsType.kThreadedDisplay);
       // maybe we shouldn't do anything in this case?
       else
-        this._viewFlags = (this._viewFlags & ~nsMsgViewFlagsType.kGroupBySort) |
-                            nsMsgViewFlagsType.kThreadedDisplay;
+        this._viewFlags = (this._viewFlags & ~Ci.nsMsgViewFlagsType.kGroupBySort) |
+                            Ci.nsMsgViewFlagsType.kThreadedDisplay;
     }
   },
 
   /**
    * @return true if we are showing only unread messages.
    */
   get showUnreadOnly() {
-    return Boolean(this._viewFlags & nsMsgViewFlagsType.kUnreadOnly);
+    return Boolean(this._viewFlags & Ci.nsMsgViewFlagsType.kUnreadOnly);
   },
   /**
    * Enable/disable showing only unread messages using the view's flag-based
    *  mechanism.  This functionality can also be approximated using a mail
    *  view (or other search) for unread messages.  There also exist special
    *  views for showing messages with unread threads which is different and
    *  has serious limitations because of its nature.
    * Setting anything to this value clears any active special view because the
@@ -1773,19 +1737,19 @@ DBViewWrapper.prototype = {
   set showUnreadOnly(aShowUnreadOnly) {
     if (this._specialView || (this.showUnreadOnly != aShowUnreadOnly)) {
       let viewRebuildRequired = (this._specialView != null);
       this._specialView = null;
       if (viewRebuildRequired)
         this.beginViewUpdate();
 
       if (aShowUnreadOnly)
-        this._viewFlags |= nsMsgViewFlagsType.kUnreadOnly;
+        this._viewFlags |= Ci.nsMsgViewFlagsType.kUnreadOnly;
       else
-        this._viewFlags &= ~nsMsgViewFlagsType.kUnreadOnly;
+        this._viewFlags &= ~Ci.nsMsgViewFlagsType.kUnreadOnly;
 
       if (viewRebuildRequired)
         this.endViewUpdate();
     }
   },
 
   /**
    * Read-only attribute indicating if a 'special view' is in use.  There are
@@ -1799,63 +1763,63 @@ DBViewWrapper.prototype = {
     return this._specialView != null;
   },
   /**
    * Private helper for use by the specialView* setters that handles the common
    *  logic.  We don't want this method to be public because we want it to be
    *  feasible for the view hierarchy and its enumerations to go away without
    *  code outside this class having to care so much.
    */
-  _setSpecialView: function DBViewWrapper__setSpecialView(aViewEnum) {
+  _setSpecialView(aViewEnum) {
     // special views simply cannot work for virtual folders.  explode.
     if (this.isVirtual)
-      throw new Exception("Virtual folders cannot use special views!");
+      throw new Error("Virtual folders cannot use special views!");
     this.beginViewUpdate();
     // all special views imply a threaded view
     this.showThreaded = true;
     this._specialView = aViewEnum;
     // We clear the search for paranoia/correctness reasons.  However, the UI
     //  layer is currently responsible for making sure these are already zeroed
     //  out.
     this.search.clear();
     this.endViewUpdate();
   },
   /**
    * @return true if the special view that shows threads with unread messages
    *     in them is active.
    */
   get specialViewThreadsWithUnread() {
-    return this._specialView == nsMsgViewType.eShowThreadsWithUnread;
+    return this._specialView == Ci.nsMsgViewType.eShowThreadsWithUnread;
   },
   /**
    * If true is assigned, attempts to enable the special view that shows threads
    *  with unread messages in them.  This will not work on virtual folders
    *  because of the inheritance hierarchy.
    * Any mechanism that requires search terms (quick search, mailviews) will be
    *  reset/disabled when enabling this view.
    */
   set specialViewThreadsWithUnread(aSpecial) {
-    this._setSpecialView(nsMsgViewType.eShowThreadsWithUnread);
+    this._setSpecialView(Ci.nsMsgViewType.eShowThreadsWithUnread);
   },
   /**
    * @return true if the special view that shows watched threads with unread
    *     messages in them is active.
    */
   get specialViewWatchedThreadsWithUnread() {
-    return this._specialView == nsMsgViewType.eShowWatchedThreadsWithUnread;
+    return this._specialView == Ci.nsMsgViewType.eShowWatchedThreadsWithUnread;
   },
   /**
    * If true is assigned, attempts to enable the special view that shows watched
    *  threads with unread messages in them.  This will not work on virtual
    *  folders because of the inheritance hierarchy.
    * Any mechanism that requires search terms (quick search, mailviews) will be
    *  reset/disabled when enabling this view.
    */
   set specialViewWatchedThreadsWithUnread(aSpecial) {
-    this._setSpecialView(nsMsgViewType.eShowWatchedThreadsWithUnread);
+    this._setSpecialView(Ci.nsMsgViewType.eShowWatchedThreadsWithUnread);
   },
 
   get mailViewIndex() {
     return this._mailViewIndex;
   },
 
   get mailViewData() {
     return this._mailViewData;
@@ -1869,18 +1833,17 @@ DBViewWrapper.prototype = {
    * @param aMailViewIndex The view to use, one of the kViewItem* constants from
    *     msgViewPickerOverlay.js OR the name of a custom view.  (It's really up
    *     to MailViewManager.getMailViewByIndex...)
    * @param aData Some piece of data appropriate to the mail view, currently
    *     this is only used for the tag name for kViewItemTags (sans the ":").
    * @param aDoNotPersist If true, we don't save this change to the db folder
    *     info.  This is intended for internal use only.
    */
-  setMailView: function DBViewWrapper_setMailView(aMailViewIndex, aData,
-                                                  aDoNotPersist) {
+  setMailView(aMailViewIndex, aData, aDoNotPersist) {
     let mailViewDef = MailViewManager.getMailViewByIndex(aMailViewIndex);
 
     this._mailViewIndex = aMailViewIndex;
     this._mailViewData = aData;
 
     // - update the search terms
     // (this triggers a view update if we are not in a batch)
     this.search.viewTerms = mailViewDef.makeTerms(this.search.session,
@@ -1907,44 +1870,43 @@ DBViewWrapper.prototype = {
     // we don't need to notify the view picker to update because the makeActive
     //  that cascades out of the view update will do it for us.
   },
 
   /**
    * @return true if the row at the given index contains a collapsed thread,
    *     false if the row is a collapsed group or anything else.
    */
-  isCollapsedThreadAtIndex:
-      function DBViewWrapper_isCollapsedThreadAtIndex(aViewIndex) {
+  isCollapsedThreadAtIndex(aViewIndex) {
     let flags = this.dbView.getFlagsAt(aViewIndex);
-    return (flags & nsMsgMessageFlags.Elided) &&
+    return (flags & Ci.nsMsgMessageFlags.Elided) &&
            !(flags & MSG_VIEW_FLAG_DUMMY) &&
            this.dbView.isContainer(aViewIndex);
   },
 
   /**
    * @return true if the row at the given index is a grouped view dummy header
    *     row, false if anything else.
    */
-  isGroupedByHeaderAtIndex: function(aViewIndex) {
+  isGroupedByHeaderAtIndex(aViewIndex) {
     if (aViewIndex < 0 || aViewIndex >= this.dbView.rowCount ||
         !this.showGroupedBySort)
       return false;
     return Boolean(this.dbView.getFlagsAt(aViewIndex) & MSG_VIEW_FLAG_DUMMY);
   },
 
   /**
    * Perform application-level behaviors related to leaving a folder that have
    *  nothing to do with our abstraction.
    *
    * Things we do on leaving a folder:
    * - Mark the folder's messages as no longer new
    * - Mark all messages read in the folder _if so configured_.
    */
-  onLeavingFolder: function DBViewWrapper_onLeavingFolder() {
+  onLeavingFolder() {
     // Suppress useless InvalidateRange calls to the tree by the dbView.
     if (this.dbView)
       this.dbView.suppressChangeNotifications = true;
     this.displayedFolder.clearNewMessages();
     this.displayedFolder.hasNewMessages = false;
     try {
       // For legacy reasons, we support marking all messages as read when we
       //  leave a folder based on the server type.  It's this listener's job
@@ -1953,18 +1915,18 @@ DBViewWrapper.prototype = {
       // Mark all messages of aFolder as read:
       // We can't use the command controller, because it is already tuned in to
       // the new folder, so we just mimic its behaviour wrt
       // goDoCommand('cmd_markAllRead').
       if (this.dbView &&
           this.listener.shouldMarkMessagesReadOnLeavingFolder(
             this.displayedFolder))
         this.dbView.doCommand(Ci.nsMsgViewCommandType.markAllRead);
+    } catch (e) {
     }
-    catch(e){/* ignore */}
   },
 
   /**
    * Returns the view index for this message header in this view.
    *
    * - If this is a single folder view, we first check whether the folder is the
    *   right one. If it is, we call the db view's findIndexOfMsgHdr. We do the
    *   first check because findIndexOfMsgHdr only checks for whether the message
@@ -1979,18 +1941,17 @@ DBViewWrapper.prototype = {
    *                     message. The dropping of view filters is persistent, so
    *                     use with care. Defaults to false.
    *
    * @returns the view index for this header, or nsMsgViewIndex_None if it isn't
    *          found.
    *
    * @public
    */
-  getViewIndexForMsgHdr: function DBViewWrapper_getViewIndexForMsgHdr(aMsgHdr,
-      aForceFind) {
+  getViewIndexForMsgHdr(aMsgHdr, aForceFind) {
     if (this.dbView) {
       if (this.isSingleFolder && aMsgHdr.folder != this.dbView.msgFolder)
         return nsMsgViewIndex_None;
 
       let viewIndex = this.dbView.findIndexOfMsgHdr(aMsgHdr, true);
 
       if (aForceFind && viewIndex == nsMsgViewIndex_None) {
         // Consider dropping view filters.
@@ -2029,18 +1990,17 @@ DBViewWrapper.prototype = {
    *  our semantics are limited to telling you about only the first one we find.
    *
    * @param aMessageId The message-id of the message you want.
    * @return The first nsIMsgDBHdr found in any of the underlying folders with
    *     the given message header, null if none are found.  The fact that we
    *     return something does not guarantee that it is actually visible in the
    *     view.  (The search may be filtering it out.)
    */
-  getMsgHdrForMessageID: function DBViewWrapper_getMsgHdrForMessageID(
-      aMessageId) {
+  getMsgHdrForMessageID(aMessageId) {
     if (this._syntheticView)
       return this._syntheticView.getMsgHdrForMessageID(aMessageId);
     if (!this._underlyingFolders)
       return null;
     for (let folder of this._underlyingFolders) {
       let msgHdr = folder.msgDatabase.getMsgHdrForMessageID(aMessageId);
       if (msgHdr)
         return msgHdr;
--- a/mail/base/modules/DisplayNameUtils.jsm
+++ b/mail/base/modules/DisplayNameUtils.jsm
@@ -1,13 +1,13 @@
 /* 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/. */
 
-ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
+const { fixIterator } = ChromeUtils.import("resource:///modules/iteratorUtils.jsm", null);
 ChromeUtils.import("resource:///modules/MailServices.jsm");
 ChromeUtils.import("resource:///modules/StringBundle.js");
 
 var EXPORTED_SYMBOLS = ["DisplayNameUtils"];
 
 var DisplayNameUtils = {
   formatDisplayName,
   formatDisplayNameList,
@@ -32,19 +32,18 @@ function getCardForEmail(aEmailAddress) 
   // Email address is searched for in any of the address books that support
   // the cardForEmailAddress function.
   // Future expansion could be to domain matches
   let books = MailServices.ab.directories;
   for (let book of fixIterator(books, Ci.nsIAbDirectory)) {
     try {
       let card = book.cardForEmailAddress(aEmailAddress);
       if (card)
-        return { book: book, card: card };
-    }
-    catch (ex) {}
+        return { book, card };
+    } catch (ex) {}
   }
 
   return { book: null, card: null };
 }
 
 function _getIdentityForAddress(aEmailAddress) {
   let emailAddress = aEmailAddress.toLowerCase();
   for (let identity of fixIterator(MailServices.accounts.allIdentities,
@@ -66,18 +65,17 @@ function _getIdentityForAddress(aEmailAd
  * @param aEmailAddress      The email address to format.
  * @param aHeaderDisplayName The display name from the header, if any
  *                           (unused, maintained for add-ons, previously used
  *                           as a fallback).
  * @param aContext           The field being formatted (e.g. "to", "from").
  * @param aCard              The address book card, if any.
  * @return The formatted display name, or null.
  */
-function formatDisplayName(aEmailAddress, aHeaderDisplayName, aContext, aCard)
-{
+function formatDisplayName(aEmailAddress, aHeaderDisplayName, aContext, aCard) {
   var displayName = null;
   var identity = _getIdentityForAddress(aEmailAddress);
   var card = aCard || getCardForEmail(aEmailAddress).card;
 
   // If this address is one of the user's identities...
   if (identity) {
     // ...pick a localized version of the word "Me" appropriate to this
     // specific header; fall back to the version used by the "to" header
@@ -95,17 +93,17 @@ function formatDisplayName(aEmailAddress
                                                    identity.email).toString();
   }
 
   // If we don't have a card, refuse to generate a display name. Places calling
   // this are then responsible for falling back to something else (e.g. the
   // value from the message header).
   if (card) {
     // getProperty may return a "1" or "0" string, we want a boolean
-    if (card.getProperty("PreferDisplayName", true) != false)
+    if (card.getProperty("PreferDisplayName", "1") == "1")
       displayName = card.displayName || null;
 
     // Note: aHeaderDisplayName is not used as a fallback as confusion could be
     // caused by a collected address using an e-mail address as display name.
   }
 
   return displayName;
 }
--- a/mail/base/modules/MailConsts.jsm
+++ b/mail/base/modules/MailConsts.jsm
@@ -4,18 +4,17 @@
 
 /**
  * This is a place to store constants and enumerations that are needed only by
  * JavaScript code, especially component/module code.
  */
 
 var EXPORTED_SYMBOLS = ["MailConsts"];
 
-var MailConsts =
-{
+var MailConsts = {
   /**
    * Determine how to open a message when it is double-clicked or selected and
    * Enter pressed. The preference to set this is mail.openMessageBehavior.
    */
   OpenMessageBehavior: {
     /**
      * Open the message in a new window. If multiple messages are selected, all
      * of them are opened in separate windows.
@@ -30,11 +29,11 @@ var MailConsts =
     EXISTING_WINDOW: 1,
 
     /**
      * Open the message in a new tab. If multiple messages are selected, all of
      * them are opened as tabs, with the last tab in the foreground and all the
      * rest in the background. If no 3-pane window is open, the message is
      * opened in a new standalone window.
      */
-    NEW_TAB: 2
-  }
+    NEW_TAB: 2,
+  },
 };
--- a/mail/base/modules/MailInstrumentation.jsm
+++ b/mail/base/modules/MailInstrumentation.jsm
@@ -7,96 +7,97 @@
  */
 
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
 this.EXPORTED_SYMBOLS = ["MailInstrumentation"];
 
 var nsIMFNService = Ci.nsIMsgFolderNotificationService;
 
-ChromeUtils.import("resource:///modules/errUtils.js");
+const { logException } = ChromeUtils.import("resource:///modules/errUtils.js", null);
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 Cu.importGlobalProperties(["XMLHttpRequest"]);
 
 /* :::::::: The Module ::::::::::::::: */
 
-var MailInstrumentation =
-{
+var MailInstrumentation = {
   // JS object containing the current state object
   _currentState: null,
 
   /**
    * The string containing the JSON stringified representation of the last
    * state we uploaded.
    */
   _lastStateString: null,
 
   // if true, need to remove ourselves as a folder notification listener
   _mfnListener: false,
 
   // if true, we need to remove our observers in uninit.
   _observersRegistered: false,
 
-  observe: function (aSubject, aTopic, aState) {
+  observe(aSubject, aTopic, aState) {
     if (aTopic == "mail:composeSendSucceeded")
       MailInstrumentation.addEvent("msgSent", true);
     else if (aTopic == "mail:setAsDefault")
       MailInstrumentation.addEvent("setAsDefault", true);
 
   },
-  msgAdded: function (aMsg) {
+  msgAdded(aMsg) {
     MailServices.mfn.removeListener(this);
     this._mfnListener = false;
     MailInstrumentation.addEvent("msgDownloaded", true);
   },
 
-  _accountsChanged: function() {
+  _accountsChanged() {
     // check if there are at least two accounts - one is local folders account
-    if (Services.prefs.getCharPref("mail.accountmanager.accounts").includes(',', 1)) {
+    if (Services.prefs.getCharPref("mail.accountmanager.accounts").includes(",", 1)) {
       MailInstrumentation.addEvent("accountAdded", true);
       MailInstrumentation._removeObserver(
         "mail.accountmanager.accounts",
         MailInstrumentation._accountsChanged);
 
     }
   },
-  _smtpServerAdded: function() {
+  _smtpServerAdded() {
     MailInstrumentation.addEvent("smtpServerAdded", true);
     MailInstrumentation._removeObserver("mail.smtpservers",
       MailInstrumentation._smtpServerAdded);
   },
-  _userOptedIn: function() {
+  _userOptedIn() {
     try {
       if (Services.prefs.getBoolPref("mail.instrumentation.userOptedIn"))
         MailInstrumentation._postStateObject();
-    } catch (ex) {logException(ex);}
+    } catch (ex) {
+      logException(ex);
+    }
   },
 
   /**
    * Loads the last saved state. This should only be called by
    * _init and a unit test.
    */
-  _loadState: function minst_loadState() {
+  _loadState() {
     let data = Services.prefs.getCharPref("mail.instrumentation.lastNotificationSent");
     if (data) {
       try {
         // parse the session state into JS objects
         this._currentState = JSON.parse(data);
         return;
       } catch (ex) {}
     }
     this._currentState = this._createStateObject();
   },
 
   /**
    * Writes the state object to disk.
    */
-  _postStateObject: function minst_postStateObject() {
+  _postStateObject() {
     // Getting defaultAccount will throw an exception if no account is set up.
     // This method runs for the smtp server before the account has been set up.
     if (MailServices.accounts.accounts.length == 0)
       return;
 
     let defaultAccount;
     try {
       defaultAccount = MailServices.accounts.defaultAccount;
@@ -121,82 +122,82 @@ var MailInstrumentation =
       let userOptedIn = Services.prefs.getBoolPref("mail.instrumentation.userOptedIn");
       if (userOptedIn)
         this._postData();
   },
 
   /**
    * @return an empty state object that can be populated with window states.
    */
-  _createStateObject: function minst_createStateObject() {
+  _createStateObject() {
     return {
       rev: 0,
       userEmailHash: "",
       // these will be a tuple, time stamp and answer, indexed by question key.
-      events: new Object,
+      events: {},
     };
   },
   // Convert each hashed byte into 2-hex strings, then combine them.
-  _bytesAsHex: function minst_bytesAsHex(bytes) {
+  _bytesAsHex(bytes) {
     return Array.from(bytes).
       map(byte => ("0" + byte.charCodeAt().toString(16)).slice(-2)).join("");
   },
   /**
    * Return sha-256 hash of the passed in e-mail address
    */
-  _hashEmailAddress: function minst_hashEmailAddress(address) {
+  _hashEmailAddress(address) {
     let ch = Cc["@mozilla.org/security/hash;1"]
                .createInstance(Ci.nsICryptoHash);
     ch.init(ch.SHA256);
     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                        .createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     let byteArray = converter.convertToByteArray(address, {});
     ch.update(byteArray, byteArray.length);
     let hashedData = ch.finish(false);
     return this._bytesAsHex(hashedData);
   },
 
-  _postData: function minst_postData() {
+  _postData() {
     let req = new XMLHttpRequest();
     let url = Services.prefs.getCharPref("mail.instrumentation.postUrl");
     if (!url.length)
       return;
     let dataToPost = this._lastStateString;
     req.open("POST", url, true);
     req.onerror = this._onError;
     req.onload = this._onLoad;
     req.send(dataToPost);
   },
-  _onError: function minst_onError(e) {
+  _onError(e) {
     logException(e);
   },
-  _onLoad: function minst_onLoad() {
+  _onLoad() {
     Services.prefs.setCharPref("mail.instrumentation.lastNotificationSent",
                                this._lastStateString);
   },
   // keeps track of whether or not we've removed the observer for a given
   // pref name.
-  _prefsObserved : new Map(),
-  _addObserver : function(pref, observer) {
+  _prefsObserved: new Map(),
+  _addObserver(pref, observer) {
     Services.prefs.addObserver(pref, observer);
     this._prefsObserved.set(pref, true);
   },
-  _removeObserver : function(pref, observer) {
+  _removeObserver(pref, observer) {
     if (this._prefsObserved.has(pref)) {
       Services.prefs.removeObserver(pref, observer);
       this._prefsObserved.set(pref, false);
     }
   },
 /* ........ Public API ................*/
   /**
    * This is called to initialize the instrumentation.
    */
-  init: function minst_init() {
+  init() {
     // If we're done with instrumentation, or this is not a first run,
     // we should just return immediately.
     if (!Services.prefs.getBoolPref("mail.instrumentation.askUser"))
       return;
     if (MailServices.accounts.accounts.length > 0)
       return;
 
     this._loadState();
@@ -206,35 +207,37 @@ var MailInstrumentation =
                                this._accountsChanged);
     Services.prefs.addObserver("mail.instrumentation.userOptedIn",
                                this._userOptedIn);
     Services.prefs.addObserver("mail.smtpservers", this._smtpServerAdded);
     MailServices.mfn.addListener(this, nsIMFNService.msgAdded);
     this._observersRegistered = true;
     this._mfnListener = true;
   },
-  uninit: function() {
+  uninit() {
     if (!this._observersRegistered)
       return;
     Services.obs.removeObserver(this, "mail:composeSendSucceeded");
     Services.obs.removeObserver(this, "mail:setAsDefault");
     if (this._mfnListener)
       MailServices.mfn.removeListener(this);
     Services.prefs.removeObserver("mail.accountmanager.accounts", this);
     Services.prefs.removeObserver("mail.instrumentation.userOptedIn", this);
     Services.prefs.removeObserver("mail.smtpservers", this);
   },
   /**
    * This adds an event to the current state, if it doesn't exist.
    */
-  addEvent: function minst_addEvent(aEventKey, aData) {
+  addEvent(aEventKey, aData) {
     try {
       if (!(aEventKey in this._currentState.events)) {
-        let newEvent = new Object;
+        let newEvent = {};
         newEvent.time = Date.now();
         newEvent.data = aData;
         this._currentState.events[aEventKey] = newEvent;
         this._postStateObject();
       }
-    } catch(ex) {logException(ex);}
+    } catch (ex) {
+      logException(ex);
+    }
   },
 };
 
--- a/mail/base/modules/MailMigrator.jsm
+++ b/mail/base/modules/MailMigrator.jsm
@@ -7,29 +7,24 @@
  * This module handles migrating mail-specific preferences, etc. Migration has
  * traditionally been a part of msgMail3PaneWindow.js, but separating the code
  * out into a module makes unit testing much easier.
  */
 
 var EXPORTED_SYMBOLS = ["MailMigrator"];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource:///modules/MailServices.jsm");
 ChromeUtils.import("resource:///modules/IOUtils.js");
 
-ChromeUtils.defineModuleGetter(this, "LoginHelper",
-                               "resource://gre/modules/LoginHelper.jsm");
-
 var MailMigrator = {
   /**
    * Switch the given fonts to the given encodings, but only if the current fonts
    * are defaults.
    */
-  _switchDefaultFonts: function MailMigrator__switchDefaultFonts(aFonts,
-                                                                 aEncodings) {
+  _switchDefaultFonts(aFonts, aEncodings) {
     for (let encoding of aEncodings) {
       let serifPref = "font.name.serif." + encoding;
       let sansPref = "font.name.sans-serif." + encoding;
       let variableSizePref = "font.size.variable." + encoding;
       // This is expected to be one of sans-serif or serif, and determines what
       // we'll link the variable font size to.
       let isSansDefault = Services.prefs.getCharPref("font.default." + encoding) ==
                             "sans-serif";
@@ -54,17 +49,17 @@ var MailMigrator = {
       }
     }
   },
 
   /**
    * Migrate to ClearType fonts (Cambria, Calibri and Consolas) on Windows Vista
    * and above.
    */
-  migrateToClearTypeFonts: function MailMigrator_migrateToClearTypeFonts() {
+  migrateToClearTypeFonts() {
     // Windows...
     if ("@mozilla.org/windows-registry-key;1" in Cc) {
       // Only migrate on Vista (Windows version 6.0) and above
       if (Services.sysinfo.getPropertyAsDouble("version") >= 6.0) {
         let fontPrefVersion =
           Services.prefs.getIntPref("mail.font.windows.version");
         if (fontPrefVersion < 2) {
           let fonts = {
@@ -89,28 +84,25 @@ var MailMigrator = {
       }
     }
   },
 
   /**
    * Determine if the UI has been upgraded in a way that requires us to reset
    * some user configuration.  If so, performs the resets.
    */
-  _migrateUI: function() {
+  /* eslint-disable complexity */
+  _migrateUI() {
     // The code for this was ported from
     // mozilla/browser/components/nsBrowserGlue.js
     const UI_VERSION = 17;
     const MESSENGER_DOCURL = "chrome://messenger/content/messenger.xul";
     const MESSENGERCOMPOSE_DOCURL = "chrome://messenger/content/messengercompose/messengercompose.xul";
     const UI_VERSION_PREF = "mail.ui-rdf.version";
-    let currentUIVersion = 0;
-
-    try {
-      currentUIVersion = Services.prefs.getIntPref(UI_VERSION_PREF);
-    } catch(ex) {}
+    let currentUIVersion = Services.prefs.getIntPref(UI_VERSION_PREF, 0);
 
     if (currentUIVersion >= UI_VERSION)
       return;
 
     let xulStore = Services.xulStore;
 
     let newProfile = (currentUIVersion == 0);
     if (newProfile) {
@@ -131,33 +123,32 @@ var MailMigrator = {
       // support those version here, see bug 1371898.
 
       // In UI version 6, we move the otherActionsButton button to the
       // header-view-toolbar.
       if (currentUIVersion < 6) {
         let cs = xulStore.getValue(MESSENGER_DOCURL, "header-view-toolbar", "currentset");
         if (cs && !cs.includes("otherActionsButton")) {
           // Put the otherActionsButton button at the end.
-          cs = cs + "," + "otherActionsButton";
+          cs = cs + ",otherActionsButton";
           xulStore.setValue(MESSENGER_DOCURL, "header-view-toolbar", "currentset", cs);
         }
       }
 
       // In UI version 7, the three-state doNotTrack setting was reverted back
       // to two-state. This reverts a (no longer supported) setting of "please
       // track me" to the default "don't say anything".
       if (currentUIVersion < 7) {
         try {
           if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled") &&
               Services.prefs.getIntPref("privacy.donottrackheader.value") != 1) {
             Services.prefs.clearUserPref("privacy.donottrackheader.enabled");
             Services.prefs.clearUserPref("privacy.donottrackheader.value");
           }
-        }
-        catch (ex) {}
+        } catch (ex) {}
       }
 
       // In UI version 8, we change from boolean browser.display.use_document_colors
       // to the tri-state browser.display.document_color_use.
       if (currentUIVersion < 8) {
         const kOldColorPref = "browser.display.use_document_colors";
         if (Services.prefs.prefHasUserValue(kOldColorPref) &&
             !Services.prefs.getBoolPref(kOldColorPref)) {
@@ -166,17 +157,17 @@ var MailMigrator = {
       }
 
       // Limit the charset detector pref to values (now) available from the UI.
       if (currentUIVersion < 9) {
         let detector = null;
         try {
           detector = Services.prefs.getComplexValue("intl.charset.detector",
                                                     Ci.nsIPrefLocalizedString).data;
-        } catch (ex) { }
+        } catch (ex) {}
         if (!(detector == "" ||
               detector == "ja_parallel_state_machine" ||
               detector == "ruprob" ||
               detector == "ukprob")) {
           // If the encoding detector pref value is not reachable from the UI,
           // reset to default (varies by localization).
           Services.prefs.clearUserPref("intl.charset.detector");
         }
@@ -191,18 +182,17 @@ var MailMigrator = {
         // and save it, else, just write the "All ABs" URI to the file.
         let data = IOUtils.loadFileToString(DIR_TREE_FILE);
         if (!data || data == "[]") {
           data = "";
         } else if (data.length > 0) {
           data = data.substring(1, data.length - 1);
         }
 
-        data = "[" + "\"moz-abdirectory://?\"" +
-               ((data.length > 0) ? ("," + data) : "") + "]";
+        data = "[\"moz-abdirectory://?\"" + ((data.length > 0) ? ("," + data) : "") + "]";
 
         IOUtils.saveStringToFile(DIR_TREE_FILE, data);
       }
 
       // Several Latin language groups were consolidated into x-western.
       if (currentUIVersion < 11) {
         let group = null;
         try {
@@ -223,17 +213,17 @@ var MailMigrator = {
           Services.prefs.getBoolPref("editor.CR_creates_new_p"));
         Services.prefs.clearUserPref("editor.CR_creates_new_p");
       }
 
       // Migrate remote content exceptions for email addresses which are
       // encoded as chrome URIs.
       if (currentUIVersion < 14) {
         let permissionsDB =
-          Services.dirsvc.get("ProfD",Ci.nsIFile);
+          Services.dirsvc.get("ProfD", Ci.nsIFile);
         permissionsDB.append("permissions.sqlite");
         let db = Services.storage.openDatabase(permissionsDB);
 
         try {
           let statement = db.createStatement(
             "select origin,permission from moz_perms where " +
             // Avoid 'like' here which needs to be escaped.
             "substr(origin, 1, 28)='chrome://messenger/content/?';");
@@ -336,31 +326,32 @@ var MailMigrator = {
           xulStore.setValue(MESSENGERCOMPOSE_DOCURL, "composeToolbar2",
                             "currentset", cs);
         }
       }
 
       // Update the migration version.
       Services.prefs.setIntPref(UI_VERSION_PREF, UI_VERSION);
 
-    } catch(e) {
+    } catch (e) {
       Cu.reportError("Migrating from UI version " + currentUIVersion + " to " +
                      UI_VERSION + " failed. Error message was: " + e + " -- " +
                      "Will reattempt on next start.");
     }
   },
+  /* eslint-enable complexity */
 
   /**
    * Perform any migration work that needs to occur after the Account Wizard
    * has had a chance to appear.
    */
-  migratePostAccountWizard: function MailMigrator_migratePostAccountWizard() {
+  migratePostAccountWizard() {
     this.migrateToClearTypeFonts();
   },
 
   /**
    * Perform any migration work that needs to occur once the user profile has
    * been loaded.
    */
-  migrateAtProfileStartup: function MailMigrator_migrateAtProfileStartup() {
+  migrateAtProfileStartup() {
     this._migrateUI();
   },
 };
--- a/mail/base/modules/MailUtils.jsm
+++ b/mail/base/modules/MailUtils.jsm
@@ -1,43 +1,44 @@
 /* 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/. */
 
 var EXPORTED_SYMBOLS = ["MailUtils"];
 
-ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
+const {
+  fixIterator,
+  toXPCOMArray,
+} = ChromeUtils.import("resource:///modules/iteratorUtils.jsm", null);
 ChromeUtils.import("resource:///modules/MailConsts.jsm");
 ChromeUtils.import("resource:///modules/MailServices.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/PluralForm.jsm");
 
 var MC = MailConsts;
 
 /**
  * This module has several utility functions for use by both core and
  * third-party code. Some functions are aimed at code that doesn't have a
  * window context, while others can be used anywhere.
  */
-var MailUtils =
-{
+var MailUtils = {
   /**
    * Discover all folders. This is useful during startup, when you have code
    * that deals with folders and that executes before the main 3pane window is
    * open (the folder tree wouldn't have been initialized yet).
    */
-  discoverFolders: function MailUtils_discoverFolders() {
+  discoverFolders() {
     let servers = MailServices.accounts.allServers;
     for (let server of fixIterator(servers, Ci.nsIMsgIncomingServer)) {
       // Bug 466311 Sometimes this can throw file not found, we're unsure
       // why, but catch it and log the fact.
       try {
         server.rootFolder.subFolders;
-      }
-      catch (ex) {
+      } catch (ex) {
         Services.console.logStringMessage("Discovering folders for account failed with " +
                                           "exception: " + ex);
       }
     }
   },
 
   /**
    * Get the nsIMsgFolder corresponding to this file. This just looks at all
@@ -46,18 +47,17 @@ var MailUtils =
    * One of the places this is used is desktop search integration -- to open
    * the search result corresponding to a mozeml/wdseml file, we need to figure
    * out the folder using the file's path.
    *
    * @param aFile the nsIFile to convert to a folder
    * @returns the nsIMsgFolder corresponding to aFile, or null if the folder
    *          isn't found
    */
-  getFolderForFileInProfile:
-      function MailUtils_getFolderForFileInProfile(aFile) {
+  getFolderForFileInProfile(aFile) {
     let folders = MailServices.accounts.allFolders;
 
     for (let folder of fixIterator(folders, Ci.nsIMsgFolder)) {
       if (folder.filePath.equals(aFile))
         return folder;
     }
     return null;
   },
@@ -68,28 +68,26 @@ var MailUtils =
    *
    * @param aFolderURI the URI to convert into a folder
    * @param aCheckFolderAttributes whether to check that the folder either has
    *                              a parent or isn't a server
    * @returns the nsIMsgFolder corresponding to this URI, or null if
    *          aCheckFolderAttributes is true and the folder doesn't have a
    *          parent or is a server
    */
-  getFolderForURI: function MailUtils_getFolderForURI(aFolderURI,
-                       aCheckFolderAttributes) {
+  getFolderForURI(aFolderURI, aCheckFolderAttributes) {
     let folder = null;
-    let rdfService = Cc['@mozilla.org/rdf/rdf-service;1']
+    let rdfService = Cc["@mozilla.org/rdf/rdf-service;1"]
                        .getService(Ci.nsIRDFService);
     folder = rdfService.GetResource(aFolderURI);
     // This is going to QI the folder to an nsIMsgFolder as well
     if (folder && folder instanceof Ci.nsIMsgFolder) {
       if (aCheckFolderAttributes && !(folder.parent || folder.isServer))
         return null;
-    }
-    else {
+    } else {
       return null;
     }
 
     return folder;
   },
 
   /**
    * Display this message header in a new tab, a new window or an existing
@@ -106,30 +104,29 @@ var MailUtils =
    *                              view will be used
    * @param [aTabmail] a tabmail element to use in case we need to open tabs.
    *                   If null or not given:
    *                   - if one or more 3pane windows are open, the most recent
    *                     one's tabmail is used
    *                   - if no 3pane windows are open, a standalone window is
    *                     opened instead of a tab
    */
-  displayMessage: function MailUtils_displayMessage(aMsgHdr,
-                      aViewWrapperToClone, aTabmail) {
+  displayMessage(aMsgHdr, aViewWrapperToClone, aTabmail) {
     this.displayMessages([aMsgHdr], aViewWrapperToClone, aTabmail);
   },
 
   /**
    * Display the warning if the number of messages to be displayed is greater than
    * the limit set in preferences.
    * @param aNumMessages: number of messages to be displayed
    * @param aConfirmTitle: title ID
    * @param aConfirmMsg: message ID
    * @param aLiitingPref: the name of the pref to retrieve the limit from
    */
-  confirmAction: function (aNumMessages, aConfirmTitle, aConfirmMsg, aLimitingPref) {
+  confirmAction(aNumMessages, aConfirmTitle, aConfirmMsg, aLimitingPref) {
     let openWarning = Services.prefs.getIntPref(aLimitingPref);
     if ((openWarning > 1) && (aNumMessages >= openWarning)) {
       let bundle = Services.strings.createBundle(
         "chrome://messenger/locale/messenger.properties");
       let title = bundle.GetStringFromName(aConfirmTitle);
       let message = PluralForm.get(aNumMessages,
         bundle.GetStringFromName(aConfirmMsg))
                 .replace("#1", aNumMessages);
@@ -153,91 +150,85 @@ var MailUtils =
    *                   If given, the window containing the tabmail is assumed
    *                   to be in front. If null or not given:
    *                   - if one or more 3pane windows are open, the most recent
    *                     one's tabmail is used, and the window is brought to the
    *                     front
    *                   - if no 3pane windows are open, standalone windows are
    *                     opened instead of tabs
    */
-  displayMessages: function MailUtils_displayMessages(aMsgHdrs,
-                       aViewWrapperToClone, aTabmail) {
+  displayMessages(aMsgHdrs, aViewWrapperToClone, aTabmail) {
     let openMessageBehavior = Services.prefs.getIntPref(
                                   "mail.openMessageBehavior");
 
     if (openMessageBehavior == MC.OpenMessageBehavior.NEW_WINDOW) {
       this.openMessagesInNewWindows(aMsgHdrs, aViewWrapperToClone);
-    }
-    else if (openMessageBehavior == MC.OpenMessageBehavior.EXISTING_WINDOW) {
+    } else if (openMessageBehavior == MC.OpenMessageBehavior.EXISTING_WINDOW) {
       // Try reusing an existing window. If we can't, fall back to opening new
       // windows
       if (aMsgHdrs.length > 1 || !this.openMessageInExistingWindow(aMsgHdrs[0]))
         this.openMessagesInNewWindows(aMsgHdrs, aViewWrapperToClone);
-    }
-    else if (openMessageBehavior == MC.OpenMessageBehavior.NEW_TAB) {
+    } else if (openMessageBehavior == MC.OpenMessageBehavior.NEW_TAB) {
       let mail3PaneWindow = null;
       if (!aTabmail) {
         // Try opening new tabs in a 3pane window
         mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
         if (mail3PaneWindow)
           aTabmail = mail3PaneWindow.document.getElementById("tabmail");
       }
 
       if (aTabmail) {
         if (this.confirmAction(aMsgHdrs.length, "openTabWarningTitle",
                                "openTabWarningConfirmation",
                                "mailnews.open_tab_warning"))
           return;
         for (let [i, msgHdr] of aMsgHdrs.entries())
           // Open all the tabs in the background, except for the last one
-          aTabmail.openTab("message", {msgHdr: msgHdr,
-              viewWrapperToClone: aViewWrapperToClone,
-              background: (i < (aMsgHdrs.length - 1)),
-              disregardOpener: (aMsgHdrs.length > 1),
+          aTabmail.openTab("message", {
+            msgHdr,
+            viewWrapperToClone: aViewWrapperToClone,
+            background: (i < (aMsgHdrs.length - 1)),
+            disregardOpener: (aMsgHdrs.length > 1),
           });
 
         if (mail3PaneWindow)
           mail3PaneWindow.focus();
-      }
-      else {
+      } else {
         // We still haven't found a tabmail, so we'll need to open new windows
         this.openMessagesInNewWindows(aMsgHdrs, aViewWrapperToClone);
       }
     }
   },
 
   /**
    * Show this message in an existing window.
    *
    * @param aMsgHdr the message header to display
    * @param [aViewWrapperToClone] a DB view wrapper to clone for the message
    *                              window
    * @returns true if an existing window was found and the message header was
    *          displayed, false otherwise
    */
-  openMessageInExistingWindow:
-      function MailUtils_openMessageInExistingWindow(aMsgHdr,
-                                                     aViewWrapperToClone) {
+  openMessageInExistingWindow(aMsgHdr, aViewWrapperToClone) {
     let messageWindow = Services.wm.getMostRecentWindow("mail:messageWindow");
     if (messageWindow) {
       messageWindow.displayMessage(aMsgHdr, aViewWrapperToClone);
       return true;
     }
     return false;
   },
 
   /**
    * Open a new standalone message window with this header.
    *
    * @param aMsgHdr the message header to display
    * @param [aViewWrapperToClone] a DB view wrapper to clone for the message
    *                              window
    */
-  openMessageInNewWindow:
-      function MailUtils_openMessageInNewWindow(aMsgHdr, aViewWrapperToClone) {
+  openMessageInNewWindow(aMsgHdr, aViewWrapperToClone) {
     // It sucks that we have to go through XPCOM for this
     let args = {msgHdr: aMsgHdr, viewWrapperToClone: aViewWrapperToClone};
     args.wrappedJSObject = args;
 
     Services.ww.openWindow(null,
         "chrome://messenger/content/messageWindow.xul", "",
         "all,chrome,dialog=no,status,toolbar", args);
   },
@@ -246,43 +237,39 @@ var MailUtils =
    * Open new standalone message windows for these headers. This will prompt
    * for confirmation if the number of windows to be opened is greater than the
    * value of the mailnews.open_window_warning preference.
    *
    * @param aMsgHdrs an array containing the message headers to display
    * @param [aViewWrapperToClone] a DB view wrapper to clone for each message
    *                              window
    */
-   openMessagesInNewWindows:
-       function MailUtils_openMessagesInNewWindows(aMsgHdrs,
-                                                   aViewWrapperToClone) {
+  openMessagesInNewWindows(aMsgHdrs, aViewWrapperToClone) {
     if (this.confirmAction(aMsgHdrs.length, "openWindowWarningTitle",
                            "openWindowWarningConfirmation",
                            "mailnews.open_window_warning"))
       return;
 
     for (let msgHdr of aMsgHdrs)
       this.openMessageInNewWindow(msgHdr, aViewWrapperToClone);
   },
 
   /**
    * Display this message header in a folder tab in a 3pane window. This is
    * useful when the message needs to be displayed in the context of its folder
    * or thread.
    *
    * @param aMsgHdr the message header to display
    */
-  displayMessageInFolderTab: function MailUtils_displayMessageInFolderTab(
-                                 aMsgHdr) {
+  displayMessageInFolderTab(aMsgHdr) {
     // Try opening new tabs in a 3pane window
     let mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
     if (mail3PaneWindow) {
       mail3PaneWindow.MsgDisplayMessageInFolderTab(aMsgHdr);
-    }
-    else {
+    } else {
       let args = {msgHdr: aMsgHdr};
       args.wrappedJSObject = args;
       Services.ww.openWindow(null,
           "chrome://messenger/content/", "",
           "all,chrome,dialog=no,status,toolbar", args);
     }
   },
 
@@ -332,21 +319,17 @@ var MailUtils =
    *     returns a string value.
    * @param aFolder The parent folder; we set the string property on it and all
    *     of its descendents.
    * @param [aCallback] The optional callback to invoke once we finish our work.
    *     The callback is provided a boolean success value; true means we
    *     managed to set the values on all folders, false means we encountered a
    *     problem.
    */
-  setStringPropertyOnFolderAndDescendents:
-      function MailUtils_setStringPropertyOnFolderAndDescendents(aPropertyName,
-                                                                 aPropertyValue,
-                                                                 aFolder,
-                                                                 aCallback) {
+  setStringPropertyOnFolderAndDescendents(aPropertyName, aPropertyValue, aFolder, aCallback) {
     // We need to add the base folder as it does not get added by ListDescendants.
     let allFolders = toXPCOMArray([aFolder], Ci.nsIMutableArray);
     // - get all the descendants
     aFolder.ListDescendants(allFolders);
 
     // - worker function
     function* folder_string_setter_worker() {
       for (let folder of fixIterator(allFolders, Ci.nsIMsgFolder)) {
@@ -365,18 +348,17 @@ var MailUtils =
     let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     function folder_string_setter_driver() {
       try {
         if (worker.next().done) {
           timer.cancel();
           if (aCallback)
             aCallback(true);
         }
-      }
-      catch (ex) {
+      } catch (ex) {
         // Any type of exception kills the generator.
         timer.cancel();
         if (aCallback)
           aCallback(false);
       }
     }
     // make sure there is at least 100 ms of not us between doing things.
     timer.initWithCallback(folder_string_setter_driver,
--- a/mail/base/modules/MailViewManager.jsm
+++ b/mail/base/modules/MailViewManager.jsm
@@ -1,19 +1,13 @@
 /* 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/. */
 
-this.EXPORTED_SYMBOLS = ['MailViewManager', 'MailViewConstants'];
-
-var nsMsgSearchScope  = Ci.nsMsgSearchScope;
-var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
-var nsMsgSearchOp     = Ci.nsMsgSearchOp;
-
-var nsMsgMessageFlags = Ci.nsMsgMessageFlags;
+this.EXPORTED_SYMBOLS = ["MailViewManager", "MailViewConstants"];
 
 /**
  * Put the MailViewConstants in an object so we can export them to
  *  msgViewPickerOverlay in one blob without contaminating everyone's address
  *  space who might want to import us.
  */
 var MailViewConstants = {
   // tag views have kViewTagMarker + their key as value
@@ -51,38 +45,38 @@ var MailViewManager = {
    *  functionality may want to be generalized to be usable by gloda as well.
    *
    * @param aViewDef The view definition, three attributes are required:
    * - name: A string name for the view, for debugging purposes only.  This
    *         should not be localized!
    * - index: The index to assign to the view.
    * - makeTerms: A function to invoke that returns a list of search terms.
    */
-  defineView: function MailViewManager_defineView(aViewDef) {
+  defineView(aViewDef) {
     this._views[aViewDef.index] = aViewDef;
   },
 
   /**
    * Wrap a custom view into our cute little view abstraction.  We do not cache
    *  these because views should not change often enough for it to matter from
    *  a performance perspective, but they will change enough to make stale
    *  caches a potential issue.
    */
-  _wrapCustomView: function MailViewManager_wrapCustomView(aCustomViewIndex) {
+  _wrapCustomView(aCustomViewIndex) {
     let mailView = this._customMailViews.getMailViewAt(aCustomViewIndex);
     return {
       name: mailView.prettyName, // since the user created it it's localized
       index: aCustomViewIndex,
-      makeTerms: function(aSession, aData) {
+      makeTerms(aSession, aData) {
         return mailView.searchTerms;
-      }
+      },
     };
   },
 
-  _findCustomViewByName: function MailViewManager_findCustomViewByName(aName) {
+  _findCustomViewByName(aName) {
     let count = this._customMailViews.mailViewCount;
     for (let i = 0; i < count; i++) {
       let mailView = this._customMailViews.getMailViewAt(i);
       if (mailView.mailViewName == aName)
         return this._wrapCustomView(i);
     }
     throw new Error("No custom view with name: " + aName);
   },
@@ -92,80 +86,78 @@ var MailViewManager = {
    *
    * @param aViewIndex If the value is an integer it references the built-in
    *      view with the view index from MailViewConstants, or if the index
    *      is >= MailViewConstants.kViewItemFirstCustom, it is a reference to
    *      a custom view definition.  If the value is a string, it is the name
    *      of a custom view.  The string case is mainly intended for testing
    *      purposes.
    */
-  getMailViewByIndex: function MailViewManager_getMailViewByIndex(aViewIndex) {
+  getMailViewByIndex(aViewIndex) {
     if (typeof(aViewIndex) == "string")
       return this._findCustomViewByName(aViewIndex);
     if (aViewIndex < MailViewConstants.kViewItemFirstCustom)
       return this._views[aViewIndex];
-    else
-      return this._wrapCustomView(aViewIndex -
-                                  MailViewConstants.kViewItemFirstCustom);
+    return this._wrapCustomView(aViewIndex - MailViewConstants.kViewItemFirstCustom);
   },
 };
 
 MailViewManager.defineView({
   name: "all mail", // debugging assistance only! not localized!
   index: MailViewConstants.kViewItemAll,
-  makeTerms: function(aSession, aData) {
+  makeTerms(aSession, aData) {
     return null;
-  }
+  },
 });
 
 MailViewManager.defineView({
   name: "new mail / unread", // debugging assistance only! not localized!
   index: MailViewConstants.kViewItemUnread,
-  makeTerms: function(aSession, aData) {
+  makeTerms(aSession, aData) {
     let term = aSession.createTerm();
     let value = term.value;
 
-    value.status = nsMsgMessageFlags.Read;
-    value.attrib = nsMsgSearchAttrib.MsgStatus;
+    value.status = Ci.nsMsgMessageFlags.Read;
+    value.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
     term.value = value;
-    term.attrib = nsMsgSearchAttrib.MsgStatus;
-    term.op = nsMsgSearchOp.Isnt;
+    term.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
+    term.op = Ci.nsMsgSearchOp.Isnt;
     term.booleanAnd = true;
 
     return [term];
-  }
+  },
 });
 
 MailViewManager.defineView({
   name: "tags", // debugging assistance only! not localized!
   index: MailViewConstants.kViewItemTags,
-  makeTerms: function(aSession, aKeyword) {
+  makeTerms(aSession, aKeyword) {
     let term = aSession.createTerm();
     let value = term.value;
 
     value.str = aKeyword;
-    value.attrib = nsMsgSearchAttrib.Keywords;
+    value.attrib = Ci.nsMsgSearchAttrib.Keywords;
     term.value = value;
-    term.attrib = nsMsgSearchAttrib.Keywords;
-    term.op = nsMsgSearchOp.Contains;
+    term.attrib = Ci.nsMsgSearchAttrib.Keywords;
+    term.op = Ci.nsMsgSearchOp.Contains;
     term.booleanAnd = true;
 
     return [term];
-  }
+  },
 });
 
 MailViewManager.defineView({
   name: "not deleted", // debugging assistance only! not localized!
   index: MailViewConstants.kViewItemNotDeleted,
-  makeTerms: function(aSession, aKeyword) {
+  makeTerms(aSession, aKeyword) {
     let term = aSession.createTerm();
     let value = term.value;
 
-    value.status = nsMsgMessageFlags.IMAPDeleted;
-    value.attrib = nsMsgSearchAttrib.MsgStatus;
+    value.status = Ci.nsMsgMessageFlags.IMAPDeleted;
+    value.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
     term.value = value;
-    term.attrib = nsMsgSearchAttrib.MsgStatus;
-    term.op = nsMsgSearchOp.Isnt;
+    term.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
+    term.op = Ci.nsMsgSearchOp.Isnt;
     term.booleanAnd = true;
 
     return [term];
-  }
+  },
 });
--- a/mail/base/modules/MsgHdrSyntheticView.jsm
+++ b/mail/base/modules/MsgHdrSyntheticView.jsm
@@ -24,41 +24,39 @@ function MsgHdrSyntheticView(aMsgHdr) {
 MsgHdrSyntheticView.prototype = {
   defaultSort: [[Ci.nsMsgViewSortType.byDate, Ci.nsMsgViewSortOrder.descending]],
 
   /**
    * Request the search be performed and notifications provided to
    * aSearchListener. Since we already have the result with us, this is
    * synchronous.
    */
-  search: function MsgHdrSyntheticView_search(aSearchListener,
-                                              aCompletionCallback) {
+  search(aSearchListener, aCompletionCallback) {
     this.searchListener = aSearchListener;
     this.completionCallback = aCompletionCallback;
     aSearchListener.onNewSearch();
     aSearchListener.onSearchHit(this.msgHdr, this.msgHdr.folder);
     // we're not really aborting, but it closes things out nicely
     this.abortSearch();
   },
 
   /**
    * Aborts or completes the search -- we do not make a distinction.
    */
-  abortSearch: function MsgHdrSyntheticView_abortSearch() {
+  abortSearch() {
     if (this.searchListener)
       this.searchListener.onSearchDone(Cr.NS_OK);
     if (this.completionCallback)
       this.completionCallback();
     this.searchListener = null;
     this.completionCallback = null;
   },
 
   /**
    * Helper function used by |DBViewWrapper.getMsgHdrForMessageID|.
    */
-  getMsgHdrForMessageID: function MsgHdrSyntheticView_getMsgHdrForMessageID(
-      aMessageId) {
+  getMsgHdrForMessageID(aMessageId) {
     if (this.msgHdr.messageId == aMessageId)
       return this.msgHdr;
 
     return null;
-  }
+  },
 };
--- a/mail/base/modules/QuickFilterManager.jsm
+++ b/mail/base/modules/QuickFilterManager.jsm
@@ -4,30 +4,27 @@
 
 this.EXPORTED_SYMBOLS = ["QuickFilterState", "QuickFilterManager",
                           "MessageTextFilter", "QuickFilterSearchListener"];
 
 ChromeUtils.import("resource://gre/modules/PluralForm.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
-ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
-ChromeUtils.import("resource:///modules/errUtils.js");
+const {
+  logException,
+  logObject,
+} = ChromeUtils.import("resource:///modules/errUtils.js", null);
 ChromeUtils.import("resource:///modules/MailServices.jsm");
-ChromeUtils.import("resource:///modules/SearchSpec.jsm");
-
-var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
-var nsMsgMessageFlags = Ci.nsMsgMessageFlags;
-var nsMsgSearchOp = Ci.nsMsgSearchOp;
 
 // XXX we need to know whether the gloda indexer is enabled for upsell reasons,
 // but this should really just be exposed on the main Gloda public interface.
-ChromeUtils.import("resource:///modules/gloda/indexer.js");
+const { GlodaIndexer } = ChromeUtils.import("resource:///modules/gloda/indexer.js", null);
 // we need to be able to create gloda message searcher instances for upsells:
-ChromeUtils.import("resource:///modules/gloda/msg_search.js");
+const { GlodaMsgSearcher } = ChromeUtils.import("resource:///modules/gloda/msg_search.js", null);
 
 
 /**
  * Shallow object copy.
  */
 function shallowObjCopy(obj) {
   let newObj = {};
   for (let key in obj) {
@@ -49,23 +46,21 @@ var FILTER_VISIBILITY_DEFAULT = true;
  * Represents the state of a quick filter bar.  This mainly decorates the
  *  manipulation of the filter states with support of tracking the filter most
  *  recently manipulated so we can maintain a very limited undo stack of sorts.
  */
 function QuickFilterState(aTemplateState, aJsonedState) {
   if (aJsonedState) {
     this.filterValues = aJsonedState.filterValues;
     this.visible = aJsonedState.visible;
-  }
-  else if (aTemplateState) {
+  } else if (aTemplateState) {
     this.filterValues = QuickFilterManager.propagateValues(
                           aTemplateState.filterValues);
     this.visible = aTemplateState.visible;
-  }
-  else {
+  } else {
     this.filterValues = QuickFilterManager.getDefaultValues();
     this.visible = FILTER_VISIBILITY_DEFAULT;
   }
   this._lastFilterAttr = null;
 }
 QuickFilterState.prototype = {
   /**
    * Maps filter names to their current states.  We rely on QuickFilterManager
@@ -82,31 +77,31 @@ QuickFilterState.prototype = {
    * Get a filter state and update lastFilterAttr appropriately.  This is
    *  intended for use when the filter state is a rich object whose state
    *  cannot be updated just by clobbering as provided by |setFilterValue|.
    *
    * @param aName The name of the filter we are retrieving.
    * @param [aNoChange=false] Is this actually a change for the purposes of
    *     lastFilterAttr purposes?
    */
-  getFilterValue: function MFS_getFilterValue(aName, aNoChange) {
+  getFilterValue(aName, aNoChange) {
     if (!aNoChange)
       this._lastFilterAttr = aName;
     return this.filterValues[aName];
   },
 
   /**
    * Set a filter state and update lastFilterAttr appropriately.
    *
    * @param aName The name of the filter we are setting.
    * @param aValue The value to set; null/undefined implies deletion.
    * @param [aNoChange=false] Is this actually a change for the purposes of
    *     lastFilterAttr purposes?
    */
-  setFilterValue: function MFS_setFilterValue(aName, aValue, aNoChange) {
+  setFilterValue(aName, aValue, aNoChange) {
     if (aValue == null) {
       delete this.filterValues[aName];
       return;
     }
 
     this.filterValues[aName] = aValue;
     if (!aNoChange)
       this._lastFilterAttr = aName;
@@ -122,17 +117,17 @@ QuickFilterState.prototype = {
   /**
    * The user hit escape; based on _lastFilterAttr and whether there are any
    *  applied filters, change our constraints.  First press clears the last
    *  added constraint (if any), second press (or if no last constraint) clears
    *  the state entirely.
    *
    * @return true if we relaxed the state, false if there was nothing to relax.
    */
-  userHitEscape: function MFS_userHitEscape() {
+  userHitEscape() {
     if (this._lastFilterAttr) {
       // it's possible the UI state the last attribute has already been cleared,
       //  in which case we want to fall through...
       if (QuickFilterManager.clearFilterValue(this._lastFilterAttr,
                                               this.filterValues)) {
         this._lastFilterAttr = null;
         return true;
       }
@@ -140,29 +135,29 @@ QuickFilterState.prototype = {
 
     return QuickFilterManager.clearAllFilterValues(this.filterValues);
   },
 
   /**
    * Clear the state without going through any undo-ish steps like
    *  |userHitEscape| tries to do.
    */
-  clear: function MFS_clear() {
+  clear() {
     QuickFilterManager.clearAllFilterValues(this.filterValues);
   },
 
   /**
    * Create the search terms appropriate to the current filter states.
    */
-  createSearchTerms: function MFS_createSearchTerms(aTermCreator) {
+  createSearchTerms(aTermCreator) {
     return QuickFilterManager.createSearchTerms(this.filterValues,
                                                 aTermCreator);
   },
 
-  persistToObj: function MFS_persistToObj() {
+  persistToObj() {
     return {
       filterValues: this.filterValues,
       visible: this.visible,
     };
   },
 };
 
 /**
@@ -219,45 +214,43 @@ function QuickFilterSearchListener(aFold
   this.scratch = null;
   this.count = 0;
   this.started = false;
 
   this.session.registerListener(this,
                                 Ci.nsIMsgSearchSession.allNotifications);
 }
 QuickFilterSearchListener.prototype = {
-  onNewSearch: function QuickFilterSearchListener_onNewSearch() {
+  onNewSearch() {
     this.started = true;
     let curState = (this.filterDef.name in this.filterer.filterValues) ?
                      this.filterer.filterValues[this.filterDef.name] : null;
     this.scratch = this.listener.onSearchStart(curState);
   },
 
-  onSearchHit: function QuickFilterSearchListener_onSearchHit(aMsgHdr,
-                                                              aFolder) {
+  onSearchHit(aMsgHdr, aFolder) {
     // GC sanity demands that we trigger a GC if we have seen a large number
     //  of headers.  Because we are driven by the search mechanism which likes
     //  to time-slice when it has a lot of messages on its plate, it is
     //  conceivable something else may trigger a GC for us.  Unfortunately,
     //  we can't guarantee it, as XPConnect does not inform memory pressure,
     //  so it's us to stop-gap it.
     this.count++;
     if (!(this.count % 4096))
       Cu.forceGC();
 
     try {
       this.listener.onSearchMessage(this.scratch, aMsgHdr, aFolder);
-    }
-    catch (ex) {
+    } catch (ex) {
       logException(ex);
       logObject(this.scratch, "scratch object");
     }
   },
 
-  onSearchDone: function QuickFilterSearchListener_onSearchDone(aStatus) {
+  onSearchDone(aStatus) {
     // it's possible we will see the tail end of an existing search. ignore.
     if (!this.started)
       return;
 
     this.session.unregisterListener(this);
 
     let curState = (this.filterDef.name in this.filterer.filterValues) ?
                      this.filterer.filterValues[this.filterDef.name] : null;
@@ -383,68 +376,67 @@ var QuickFilterManager = {
    *     aFiltering; true means we have applied some terms, false means not.
    *     It's vitally important that you do not just facet things willy nilly
    *     unless there is expected user payoff and they opted in.  Our tagging UI
    *     only facets when the user clicked the tag facet.  If you write an
    *     extension that provides really sweet visualizations or something like
    *     that and the user installs you knowing what's what, that is also cool,
    *     we just can't do it in core for now.
    */
-  defineFilter: function MFM_defineFilter(aFilterDef) {
+  defineFilter(aFilterDef) {
     this.filterDefs.push(aFilterDef);
     this.filterDefsByName[aFilterDef.name] = aFilterDef;
   },
 
   /**
    * Remove a filter from existence by name.  This is for extensions to disable
    *  existing filters and not a dynamic jetpack-like lifecycle.  It falls to
    *  the code calling killFilter to deal with the DOM nodes themselves for now.
    *
    * @param aName The name of the filter to kill.
    */
-  killFilter: function MFM_killFilter(aName) {
+  killFilter(aName) {
     let filterDef = this.filterDefsByName[aName];
     this.filterDefs.splice(this.filterDefs.indexOf(filterDef), 1);
     delete this.filterDefsByName[aName];
   },
 
   /**
    * Propagate values from an existing state into a new state based on
    *  propagation rules.  For use by QuickFilterState.
    *
    * @param aTemplValues A set of existing filterValues.
    * @return The new filterValues state.
    */
-  propagateValues: function MFM_propagateValues(aTemplValues) {
+  propagateValues(aTemplValues) {
     let values = {};
     let sticky = ("sticky" in aTemplValues) ? aTemplValues.sticky : false;
 
     for (let filterDef of this.filterDefs) {
       if ("propagateState" in filterDef) {
         let curValue = (filterDef.name in aTemplValues) ?
                          aTemplValues[filterDef.name] : undefined;
         let newValue = filterDef.propagateState(curValue, sticky);
         if (newValue != null)
           values[filterDef.name] = newValue;
-      }
-      // always propagate the value if sticky and there was no handler
-      else if (sticky) {
+      } else if (sticky) {
+        // Always propagate the value if sticky and there was no handler.
         if (filterDef.name in aTemplValues)
           values[filterDef.name] = aTemplValues[filterDef.name];
       }
     }
 
     return values;
   },
   /**
    * Get the set of default filterValues for the current set of defined filters.
    *
    * @return Thew new filterValues state.
    */
-  getDefaultValues: function MFM_getDefaultValues() {
+  getDefaultValues() {
     let values = {};
     for (let filterDef of this.filterDefs) {
       if ("getDefaults" in filterDef) {
         let newValue = filterDef.getDefaults();
         if (newValue != null)
           values[filterDef.name] = newValue;
       }
     }
@@ -452,17 +444,17 @@ var QuickFilterManager = {
   },
 
   /**
    * Reset the state of a single filter given the provided values.
    *
    * @return true if we actually cleared some state, false if there was nothing
    *     to clear.
    */
-  clearFilterValue: function MFM_clearFilterValue(aFilterName, aValues) {
+  clearFilterValue(aFilterName, aValues) {
     let filterDef = this.filterDefsByName[aFilterName];
     if (!("clearState" in filterDef)) {
       if (aFilterName in aValues) {
         delete aValues[aFilterName];
         return true;
       }
       return false;
     }
@@ -479,142 +471,140 @@ var QuickFilterManager = {
   },
 
   /**
    * Reset the state of all filters given the provided values.
    *
    * @return true if we actually cleared something, false if there was nothing
    *     to clear.
    */
-  clearAllFilterValues: function MFM_clearFilterValues(aFilterValues) {
+  clearAllFilterValues(aFilterValues) {
     let didClearSomething = false;
     for (let filterDef of this.filterDefs) {
       if (this.clearFilterValue(filterDef.name, aFilterValues))
         didClearSomething = true;
     }
     return didClearSomething;
   },
 
   /**
    * Populate and return a list of search terms given the provided state.
    *
    * We only invoke appendTerms on filters that have state in aFilterValues,
    * as per the contract.
    */
-  createSearchTerms: function MFM_createSearchTerms(aFilterValues,
-                                                    aTermCreator) {
+  createSearchTerms(aFilterValues, aTermCreator) {
     let searchTerms = [], listeners = [];
     for (let filterName in aFilterValues) {
       let filterValue = aFilterValues[filterName];
       let filterDef = this.filterDefsByName[filterName];
       try {
         let listener =
           filterDef.appendTerms(aTermCreator, searchTerms, filterValue);
         if (listener)
           listeners.push([listener, filterDef]);
-      }
-      catch(ex) {
+      } catch (ex) {
         logException(ex);
       }
     }
     return searchTerms.length ? [searchTerms, listeners] : [null, listeners];
-  }
+  },
 };
 
 /**
  * Meta-filter, just handles whether or not things are sticky.
  */
 QuickFilterManager.defineFilter({
   name: "sticky",
   domId: "qfb-sticky",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
   },
   /**
    * This should not cause an update, otherwise default logic.
    */
-  onCommand: function(aState, aNode, aEvent, aDocument) {
+  onCommand(aState, aNode, aEvent, aDocument) {
     let checked = aNode.checked ? true : null;
     return [checked, false];
   },
 });
 
 /**
  * true: must be unread, false: must be read.
  */
 QuickFilterManager.defineFilter({
   name: "unread",
   domId: "qfb-unread",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     let term, value;
     term = aTermCreator.createTerm();
-    term.attrib = nsMsgSearchAttrib.MsgStatus;
+    term.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
     value = term.value;
     value.attrib = term.attrib;
-    value.status = nsMsgMessageFlags.Read;
+    value.status = Ci.nsMsgMessageFlags.Read;
     term.value = value;
-    term.op = aFilterValue ? nsMsgSearchOp.Isnt : nsMsgSearchOp.Is;
+    term.op = aFilterValue ? Ci.nsMsgSearchOp.Isnt : Ci.nsMsgSearchOp.Is;
     term.booleanAnd = true;
     aTerms.push(term);
-  }
+  },
 });
 
 /**
  * true: must be starred, false: must not be starred.
  */
 QuickFilterManager.defineFilter({
   name: "starred",
   domId: "qfb-starred",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     let term, value;
     term = aTermCreator.createTerm();
-    term.attrib = nsMsgSearchAttrib.MsgStatus;
+    term.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
     value = term.value;
     value.attrib = term.attrib;
-    value.status = nsMsgMessageFlags.Marked;
+    value.status = Ci.nsMsgMessageFlags.Marked;
     term.value = value;
-    term.op = aFilterValue ? nsMsgSearchOp.Is : nsMsgSearchOp.Isnt;
+    term.op = aFilterValue ? Ci.nsMsgSearchOp.Is : Ci.nsMsgSearchOp.Isnt;
     term.booleanAnd = true;
     aTerms.push(term);
-  }
+  },
 });
 
 /**
  * true: sender must be in a local address book, false: sender must not be.
  */
 QuickFilterManager.defineFilter({
   name: "addrBook",
   domId: "qfb-inaddrbook",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     let term, value;
     let enumerator = MailServices.ab.directories;
     let firstBook = true;
     term = null;
     while (enumerator.hasMoreElements()) {
       let addrbook = enumerator.getNext();
       if (addrbook instanceof Ci.nsIAbDirectory &&
           !addrbook.isRemote) {
         term = aTermCreator.createTerm();
         term.attrib = Ci.nsMsgSearchAttrib.Sender;
         value = term.value;
         value.attrib = term.attrib;
         value.str = addrbook.URI;
         term.value = value;
-        term.op = aFilterValue ? nsMsgSearchOp.IsInAB : nsMsgSearchOp.IsntInAB;
+        term.op = aFilterValue ? Ci.nsMsgSearchOp.IsInAB : Ci.nsMsgSearchOp.IsntInAB;
         // It's an AND if we're the first book (so the boolean affects the
         //  group as a whole.)
         // It's the negation of whether we're filtering otherwise; demorgans.
         term.booleanAnd = firstBook || !aFilterValue;
         term.beginsGrouping = firstBook;
         aTerms.push(term);
         firstBook = false;
       }
     }
     if (term)
       term.endsGrouping = true;
-  }
+  },
 });
 
 /**
  * It's a tag filter that sorta facets! Stealing gloda's thunder! Woo!
  *
  * Filter on message tags?  Meanings:
  * - true: Yes, must have at least one tag on it.
  * - false: No, no tags on it!
@@ -625,17 +615,17 @@ QuickFilterManager.defineFilter({
 var TagFacetingFilter = {
   name: "tags",
   domId: "qfb-tags",
 
   /**
    * @return true if the constaint is only on has tags/does not have tags,
    *     false if there are specific tag constraints in play.
    */
-  isSimple: function(aFilterValue) {
+  isSimple(aFilterValue) {
     // it's the simple case if the value is just a boolean
     if (typeof(aFilterValue) != "object")
       return true;
     // but also if the object contains no non-null values
     let simpleCase = true;
     for (let key in aFilterValue.tags) {
       let value = aFilterValue.tags[key];
       if (value !== null) {
@@ -648,17 +638,17 @@ var TagFacetingFilter = {
 
   /**
    * Because we support both inclusion and exclusion we can produce up to two
    *  groups.  One group for inclusion, one group for exclusion.  To get listed
    *  the message must have any/all of the tags marked for inclusion,
    *  (depending on mode), but it cannot have any of the tags marked for
    *  exclusion.
    */
-  appendTerms: function TFF_appendTerms(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     if (aFilterValue == null)
       return null;
 
     let term, value;
 
     // just the true/false case
     if (this.isSimple(aFilterValue)) {
       term = aTermCreator.createTerm();
@@ -670,18 +660,17 @@ var TagFacetingFilter = {
                   Ci.nsMsgSearchOp.IsntEmpty :
                   Ci.nsMsgSearchOp.IsEmpty;
       term.booleanAnd = true;
       aTerms.push(term);
 
       // we need to perform faceting if the value is literally true.
       if (aFilterValue === true)
         return this;
-    }
-    else {
+    } else {
       let firstIncludeClause = true, firstExcludeClause = true;
       let lastIncludeTerm = null;
       term = null;
 
       let excludeTerms = [];
 
       let mode = aFilterValue.mode;
       for (let key in aFilterValue.tags) {
@@ -689,27 +678,26 @@ var TagFacetingFilter = {
         if (shouldFilter !== null) {
           term = aTermCreator.createTerm();
           term.attrib = Ci.nsMsgSearchAttrib.Keywords;
           value = term.value;
           value.attrib = term.attrib;
           value.str = key;
           term.value = value;
           if (shouldFilter) {
-            term.op = nsMsgSearchOp.Contains;
+            term.op = Ci.nsMsgSearchOp.Contains;
             // AND for the group. Inside the group we also want AND if the
             // mode is set to "All of".
             term.booleanAnd = firstIncludeClause || (mode === "AND");
             term.beginsGrouping = firstIncludeClause;
             aTerms.push(term);
             firstIncludeClause = false;
             lastIncludeTerm = term;
-          }
-          else {
-            term.op = nsMsgSearchOp.DoesntContain;
+          } else {
+            term.op = Ci.nsMsgSearchOp.DoesntContain;
             // you need to not include all of the tags marked excluded.
             term.booleanAnd = true;
             term.beginsGrouping = firstExcludeClause;
             excludeTerms.push(term);
             firstExcludeClause = false;
           }
         }
       }
@@ -729,36 +717,36 @@ var TagFacetingFilter = {
           value.str = "";
           term.value = value;
           term.op = Ci.nsMsgSearchOp.IsntEmpty;
           term.booleanAnd = true;
           aTerms.push(term);
         }
 
         // (extend in the exclusions)
-        excludeTerms[excludeTerms.length-1].endsGrouping = true;
+        excludeTerms[excludeTerms.length - 1].endsGrouping = true;
         aTerms.push.apply(aTerms, excludeTerms);
       }
     }
     return null;
   },
 
-  onSearchStart: function(aCurState) {
+  onSearchStart(aCurState) {
     // this becomes aKeywordMap; we want to start with an empty one
     return {};
   },
-  onSearchMessage: function(aKeywordMap, aMsgHdr, aFolder) {
+  onSearchMessage(aKeywordMap, aMsgHdr, aFolder) {
     let keywords = aMsgHdr.getStringProperty("keywords");
-    let keywordList = keywords.split(' ');
+    let keywordList = keywords.split(" ");
     for (let iKeyword = 0; iKeyword < keywordList.length; iKeyword++) {
       let keyword = keywordList[iKeyword];
       aKeywordMap[keyword] = null;
     }
   },
-  onSearchDone: function(aCurState, aKeywordMap, aStatus) {
+  onSearchDone(aCurState, aKeywordMap, aStatus) {
     // we are an async operation; if the user turned off the tag facet already,
     //  then leave that state intact...
     if (aCurState == null)
       return [null, false, false];
 
     // only propagate things that are actually tags though!
     let outKeyMap = {tags: {}};
     let tags = MailServices.tags.getAllTags({});
@@ -770,62 +758,61 @@ var TagFacetingFilter = {
         outKeyMap.tags[tag.key] = aKeywordMap[tag.key];
     }
     return [outKeyMap, true, false];
   },
 
   /**
    * We need to clone our state if it's an object to avoid bad sharing.
    */
-  propagateState: function(aOld, aSticky) {
+  propagateState(aOld, aSticky) {
     // stay disabled when disabled, get disabled when not sticky
     if (aOld == null || !aSticky)
       return null;
     if (this.isSimple(aOld))
-      return aOld ? true : false; // could be an object, need to convert.
+      return !!aOld; // could be an object, need to convert.
     return shallowObjCopy(aOld);
   },
 
   /**
    * Default behaviour but:
    * - We collapse our expando if we get unchecked.
    * - We want to initiate a faceting pass if we just got checked.
    */
-  onCommand: function(aState, aNode, aEvent, aDocument) {
+  onCommand(aState, aNode, aEvent, aDocument) {
     let checked = aNode.checked ? true : null;
     if (!checked)
       aDocument.getElementById("quick-filter-bar-tab-bar").collapsed = true;
 
     // return ourselves if we just got checked to have
     //  onSearchStart/onSearchMessage/onSearchDone get to do their thing.
     return [checked, true];
   },
 
-  domBindExtra: function(aDocument, aMuxer, aNode) {
+  domBindExtra(aDocument, aMuxer, aNode) {
     // Tag filtering mode menu (All of/Any of)
     function commandHandler(aEvent) {
       let filterValue = aMuxer.getFilterValueForMutation(TagFacetingFilter.name);
       filterValue.mode = aEvent.target.value;
       aMuxer.updateSearch();
     }
     aDocument.getElementById("qfb-boolean-mode").addEventListener(
       "ValueChange", commandHandler);
   },
 
-  reflectInDOM: function TFF_reflectInDOM(aNode, aFilterValue,
-                                          aDocument, aMuxer) {
-    aNode.checked = aFilterValue ? true : false;
+  reflectInDOM(aNode, aFilterValue, aDocument, aMuxer) {
+    aNode.checked = !!aFilterValue;
     if ((aFilterValue != null) &&
         (typeof(aFilterValue) == "object"))
       this._populateTagBar(aFilterValue, aDocument, aMuxer);
     else
       aDocument.getElementById("quick-filter-bar-tab-bar").collapsed = true;
   },
 
-  _populateTagBar: function TFF__populateTagMenu(aState, aDocument, aMuxer) {
+  _populateTagBar(aState, aDocument, aMuxer) {
     let tagbar = aDocument.getElementById("quick-filter-bar-tab-bar");
     let keywordMap = aState.tags;
 
     // If we have a mode stored use that. If we don't have a mode, then update
     // our state to agree with what the UI is currently displaying;
     // this will happen for fresh profiles.
     let qbm = aDocument.getElementById("qfb-boolean-mode");
     if (aState.mode)
@@ -834,17 +821,17 @@ var TagFacetingFilter = {
       aState.mode = qbm.value;
 
     function commandHandler(aEvent) {
       let tagKey = aEvent.target.getAttribute("value");
       let state = aMuxer.getFilterValueForMutation(TagFacetingFilter.name);
       state.tags[tagKey] = aEvent.target.checked ? true : null;
       aEvent.target.removeAttribute("inverted");
       aMuxer.updateSearch();
-    };
+    }
 
     function rightClickHandler(aEvent) {
       // Only do something if this is a right-click, otherwise commandHandler
       //  will pick up on it.
       if (aEvent.button == 2) {
         // we need to toggle the checked state ourselves
         aEvent.target.checked = !aEvent.target.checked;
 
@@ -908,28 +895,28 @@ var TagFacetingFilter = {
 QuickFilterManager.defineFilter(TagFacetingFilter);
 
 /**
  * true: must have attachment, false: must not have attachment.
  */
 QuickFilterManager.defineFilter({
   name: "attachment",
   domId: "qfb-attachment",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     let term, value;
     term = aTermCreator.createTerm();
     term.attrib = Ci.nsMsgSearchAttrib.MsgStatus;
     value = term.value;
     value.attrib = term.attrib;
     value.status = Ci.nsMsgMessageFlags.Attachment;
     term.value = value;
-    term.op = aFilterValue ? nsMsgSearchOp.Is : nsMsgSearchOp.Isnt;
+    term.op = aFilterValue ? Ci.nsMsgSearchOp.Is : Ci.nsMsgSearchOp.Isnt;
     term.booleanAnd = true;
     aTerms.push(term);
-  }
+  },
 });
 
 /**
  * The traditional quick-search text filter now with added gloda upsell!  We
  * are mildly extensible in case someone wants to add more specific text filter
  * criteria to toggle, but otherwise are intended to be taken out of the
  * picture entirely by extensions implementing more featureful text searches.
  *
@@ -946,17 +933,17 @@ var MessageTextFilter = {
    * update using a timer and this results in stable behavior.)
    *
    * This code is cloned from gloda's msg_search.js and known good (enough :).
    * I did change the friendless quote situation, though.
    *
    * @param aSearchString The phrase to parse up.
    * @return A list of terms.
    */
-  _parseSearchString: function MTF__parseSearchString(aSearchString) {
+  _parseSearchString(aSearchString) {
     aSearchString = aSearchString.trim();
     let terms = [];
 
     /*
      * Add the term as long as the trim on the way in didn't obliterate it.
      *
      * In the future this might have other helper logic; it did once before.
      */
@@ -992,17 +979,17 @@ var MessageTextFilter = {
   },
 
   /**
    * For each search phrase, build a group that contains all our active text
    *  filters OR'ed together.  So if the user queries for 'foo bar' with
    *  sender and recipient enabled, we build:
    * ("foo" sender OR "foo" recipient) AND ("bar" sender OR "bar" recipient)
    */
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
     let term, value;
 
     if (aFilterValue.text) {
       let phrases = this._parseSearchString(aFilterValue.text);
       for (let groupedPhrases of phrases) {
         let firstClause = true;
         term = null;
         let splitPhrases = groupedPhrases.split("|");
@@ -1013,57 +1000,57 @@ var MessageTextFilter = {
             let tfDef = this.textFilterDefs[tfName];
 
             term = aTermCreator.createTerm();
             term.attrib = tfDef.attrib;
             value = term.value;
             value.attrib = tfDef.attrib;
             value.str = phrase;
             term.value = value;
-            term.op = nsMsgSearchOp.Contains;
+            term.op = Ci.nsMsgSearchOp.Contains;
             // AND for the group, but OR inside the group
             term.booleanAnd = firstClause;
             term.beginsGrouping = firstClause;
             aTerms.push(term);
             firstClause = false;
           }
         }
         if (term)
           term.endsGrouping = true;
       }
     }
   },
-  getDefaults: function() {
+  getDefaults() {
     let states = {};
     for (let name in this._defaultStates) {
       states[name] = this._defaultStates[name];
     }
     return {
       text: null,
-      states: states,
+      states,
     };
   },
-  propagateState: function(aOld, aSticky) {
+  propagateState(aOld, aSticky) {
     return {
       text: aSticky ? aOld.text : null,
       states: shallowObjCopy(aOld.states),
     };
   },
-  clearState: function(aState) {
+  clearState(aState) {
     let hadState = Boolean(aState.text);
     aState.text = null;
     return [aState, hadState];
   },
 
   /**
    * We need to create and bind our expando-bar toggle buttons.  We also need to
    *  add a special down keypress handler that escapes the textbox into the
    *  thread pane.
    */
-  domBindExtra: function MessageTextFilter_domBind(aDocument, aMuxer, aNode) {
+  domBindExtra(aDocument, aMuxer, aNode) {
     // -- platform-dependent placeholder setup
     aNode.setAttribute(
       "placeholder",
       aNode.getAttribute("emptytextbase")
            .replace("#1", aNode.getAttribute((AppConstants.platform == "macosx") ?
                                              "keyLabelMac" : "keyLabelNonMac")));
     // force an update of the emptytext now that we've updated it.
     aNode.value = "";
@@ -1074,19 +1061,16 @@ var MessageTextFilter = {
       if (aEvent.keyCode == aEvent.DOM_VK_DOWN) {
         let threadPane = aDocument.getElementById("threadTree");
         // focusing does not actually select the row...
         threadPane.focus();
         // ...so explicitly select the current index.
         threadPane.view.selection.select(threadPane.currentIndex);
         return false;
       }
-      // - Enter when upsell is actively proposed...
-      else if (aEvent.keyCode == aEvent.DOM_VK_RETURN) {
-      }
       return true;
     });
 
     // -- Blurring kills upsell.
     aNode.addEventListener("blur", function(aEvent) {
       let panel = aDocument.getElementById("qfb-text-search-upsell");
       if ((Services.focus.activeWindow != aDocument.defaultView ||
            aDocument.commandDispatcher.focusedElement != aNode.inputField) &&
@@ -1105,56 +1089,54 @@ var MessageTextFilter = {
 
     for (let name in this.textFilterDefs) {
       let textFilter  = this.textFilterDefs[name];
       aDocument.getElementById(textFilter.domId).addEventListener(
         "command", commandHandler);
     }
   },
 
-  onCommand: function(aState, aNode, aEvent, aDocument) {
+  onCommand(aState, aNode, aEvent, aDocument) {
     let text = aNode.value.length ? aNode.value : null;
     if (text == aState.text) {
       let upsell = aDocument.getElementById("qfb-text-search-upsell");
       if (upsell.state == "open") {
         upsell.hidePopup();
         let tabmail = aDocument.getElementById("tabmail");
         tabmail.openTab("glodaFacet", {
-                          searcher: new GlodaMsgSearcher(null, aState.text)
+                          searcher: new GlodaMsgSearcher(null, aState.text),
                         });
       }
       return [aState, false];
     }
 
     aState.text = text;
     aDocument.getElementById("quick-filter-bar-filter-text-bar").collapsed =
       (text == null);
     return [aState, true];
   },
 
-  reflectInDOM: function MessageTextFilter_reflectInDOM(aNode, aFilterValue,
-                                                        aDocument, aMuxer,
-                                                        aFromPFP) {
+  reflectInDOM(aNode, aFilterValue, aDocument, aMuxer, aFromPFP) {
     if (aFromPFP == "nosale") {
       let panel = aDocument.getElementById("qfb-text-search-upsell");
       if (panel.state != "closed")
         panel.hidePopup();
       return;
     }
     if (aFromPFP == "upsell") {
       let panel = aDocument.getElementById("qfb-text-search-upsell");
       let line1 = aDocument.getElementById("qfb-upsell-line-one");
       let line2 = aDocument.getElementById("qfb-upsell-line-two");
       line1.value = line1.getAttribute("fmt").replace("#1", aFilterValue.text);
       line2.value = line2.getAttribute("fmt").replace("#1", aFilterValue.text);
 
       if (panel.state == "closed" &&
           aDocument.commandDispatcher.focusedElement == aNode.inputField) {
         let filterBar = aDocument.getElementById("quick-filter-bar");
-        //panel.sizeTo(filterBar.clientWidth - 20, filterBar.clientHeight - 20);
+        // panel.sizeTo(filterBar.clientWidth - 20, filterBar.clientHeight - 20);
         panel.openPopup(filterBar, "after_end", -7, 7, false, true);
       }
       return;
     }
 
     // Make sure we have no visible upsell on state change while our textbox
     //  retains focus.
     let panel = aDocument.getElementById("qfb-text-search-upsell");
@@ -1179,19 +1161,17 @@ var MessageTextFilter = {
     aDocument.getElementById("quick-filter-bar-filter-text-bar").collapsed =
       (aFilterValue.text == null);
   },
 
   /**
    * In order to do our upsell we need to know when we are not getting any
    *  results.
    */
-  postFilterProcess: function MessageTextFilter_postFilterProcess(aState,
-                                                                  aViewWrapper,
-                                                                  aFiltering) {
+  postFilterProcess(aState, aViewWrapper, aFiltering) {
     // If we're not filtering, not filtering on text, there are results, or
     //  gloda is not enabled so upselling makes no sense, then bail.
     // (Currently we always return "nosale" to make sure our panel is closed;
     //  this might be overkill but unless it becomes a performance problem, it
     //  keeps us safe from weird stuff.)
     if (!aFiltering || !aState.text || aViewWrapper.dbView.numMsgsInView ||
         !GlodaIndexer.enabled)
       return [aState, "nosale", false];
@@ -1202,149 +1182,145 @@ var MessageTextFilter = {
   },
 
   /** maps text filter names to whether they are enabled by default (bool)  */
   _defaultStates: {},
   /** maps text filter name to text filter def */
   textFilterDefs: {},
   /** maps dom id to text filter def */
   textFilterDefsByDomId: {},
-  defineTextFilter: function MessageTextFilter_defineTextFilter(aTextDef) {
+  defineTextFilter(aTextDef) {
     this.textFilterDefs[aTextDef.name] = aTextDef;
     this.textFilterDefsByDomId[aTextDef.domId] = aTextDef;
     if (aTextDef.defaultState)
       this._defaultStates[aTextDef.name] = true;
   },
 };
 // Note that we definitely want this filter defined AFTER the cheap message
 // status filters, so don't reorder this invocation willy nilly.
 QuickFilterManager.defineFilter(MessageTextFilter);
 QuickFilterManager.textBoxDomId = "qfb-qs-textbox";
 
 MessageTextFilter.defineTextFilter({
   name: "sender",
   domId: "qfb-qs-sender",
-  attrib: nsMsgSearchAttrib.Sender,
+  attrib: Ci.nsMsgSearchAttrib.Sender,
   defaultState: true,
 });
 MessageTextFilter.defineTextFilter({
   name: "recipients",
   domId: "qfb-qs-recipients",
-  attrib: nsMsgSearchAttrib.ToOrCC,
+  attrib: Ci.nsMsgSearchAttrib.ToOrCC,
   defaultState: true,
 });
 MessageTextFilter.defineTextFilter({
   name: "subject",
   domId: "qfb-qs-subject",
-  attrib: nsMsgSearchAttrib.Subject,
+  attrib: Ci.nsMsgSearchAttrib.Subject,
   defaultState: true,
 });
 MessageTextFilter.defineTextFilter({
   name: "body",
   domId: "qfb-qs-body",
-  attrib: nsMsgSearchAttrib.Body,
+  attrib: Ci.nsMsgSearchAttrib.Body,
   defaultState: false,
 });
 
 /**
  * We need to be parameterized by folder/muxer to provide update notifications
  * and this is the cleanest way given the current FolderDisplayWidget assumption
  * that everyone knows the window they are in already.
  */
 function ResultsLabelFolderDisplayListener(aMuxer) {
   this.muxer = aMuxer;
 }
 ResultsLabelFolderDisplayListener.prototype = {
-  _update: function ResultsLabelFolderDisplayListener__update(aFolderDisplay) {
+  _update(aFolderDisplay) {
     let filterer = aFolderDisplay._tabInfo._ext.quickFilter;
     if (!filterer)
       return;
     let oldCount = ("results" in filterer.filterValues) ?
                      filterer.filterValues.results : null;
     // (we only display the tally when the filter is active; don't change that)
     if (oldCount == null)
       return;
     let newCount = aFolderDisplay.view.dbView.numMsgsInView;
     if (oldCount == newCount)
       return;
     filterer.setFilterValue("results", newCount, true);
     if (aFolderDisplay.active)
       this.muxer.reflectFiltererState(filterer, aFolderDisplay, "results");
   },
 
-  //////////////////////////////////////////////////////////////////////////////
-  //// FolderDisplayListener
+  // ---------------------
+  // FolderDisplayListener
 
   // We want to make sure that anything that would change the count of displayed
   //  messages causes us to update our displayed value.
 
-  onMessageCountsChanged: function(aFolderDisplay) {
+  onMessageCountsChanged(aFolderDisplay) {
     this._update(aFolderDisplay);
   },
 
-  onMessagesRemoved: function(aFolderDisplay) {
+  onMessagesRemoved(aFolderDisplay) {
     this._update(aFolderDisplay);
   },
 };
 
 /**
  * The results label says whether there were any matches and, if so, how many.
  */
 QuickFilterManager.defineFilter({
   name: "results",
   domId: "qfb-results-label",
-  appendTerms: function(aTermCreator, aTerms, aFilterValue) {
+  appendTerms(aTermCreator, aTerms, aFilterValue) {
   },
 
   /**
    * Our state is meaningless; we implement this to avoid clearState ever
    *  thinking we were a facet.
    */
-  clearState: function(aState) {
+  clearState(aState) {
     return [null, false];
   },
 
   /**
    * We never have any state to propagate!
    */
-  propagateState: function(aOld, aSticky) {
+  propagateState(aOld, aSticky) {
     return null;
   },
 
   /**
    * Hook us up as a folder display listener so we can get information on when
    * the counts change.
    */
-  domBindExtra: function MessageTextFilter_domBind(aDocument, aMuxer, aNode) {
+  domBindExtra(aDocument, aMuxer, aNode) {
     aDocument.defaultView.FolderDisplayListenerManager.registerListener(
       new ResultsLabelFolderDisplayListener(aMuxer));
   },
-  reflectInDOM: function MessageTextFilter_reflectInDOM(aNode, aFilterValue,
-                                                        aDocument) {
+  reflectInDOM(aNode, aFilterValue, aDocument) {
     if (aFilterValue == null) {
       aNode.value = "";
       aNode.style.visibility = "hidden";
-    }
-    else if (aFilterValue == 0) {
+    } else if (aFilterValue == 0) {
       aNode.value = aNode.getAttribute("noresultsstring");
       aNode.style.visibility = "visible";
-    }
-    else {
+    } else {
       let fmtstring = aNode.getAttribute("somefmtstring");
 
       aNode.value = PluralForm.get(aFilterValue, fmtstring)
                               .replace("#1", aFilterValue.toString());
       aNode.style.visibility = "visible";
     }
   },
   /**
    * We slightly abuse the filtering hook to figure out how many messages there
    *  are and whether a filter is active.  What makes this reasonable is that
    *  a more complicated widget that visualized the results as a timeline would
    *  definitely want to be hooked up like this.  (Although they would want
    *  to implement propagateState since the state they store would be pretty
    *  expensive.)
    */
-  postFilterProcess: function TFF_postFilterProcess(aState, aViewWrapper,
-                                                    aFiltering) {
+  postFilterProcess(aState, aViewWrapper, aFiltering) {
     return [aFiltering ? aViewWrapper.dbView.numMsgsInView : null, true, false];
   },
 });
--- a/mail/base/modules/SearchSpec.jsm
+++ b/mail/base/modules/SearchSpec.jsm
@@ -1,26 +1,18 @@
 /* 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/. */
 
-this.EXPORTED_SYMBOLS = ['SearchSpec'];
+this.EXPORTED_SYMBOLS = ["SearchSpec"];
 
-ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
+const { fixIterator } = ChromeUtils.import("resource:///modules/iteratorUtils.jsm", null);
 ChromeUtils.import("resource:///modules/MailServices.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-var nsMsgSearchScope = Ci.nsMsgSearchScope;
-var nsIMsgSearchTerm = Ci.nsIMsgSearchTerm;
-var nsIMsgLocalMailFolder = Ci.nsIMsgLocalMailFolder;
-var nsMsgFolderFlags = Ci.nsMsgFolderFlags;
-var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
-
-var NS_MSG_SEARCH_INTERRUPTED = 0x00550002;
-
 /**
  * Wrapper abstraction around a view's search session.  This is basically a
  *  friend class of FolderDisplayWidget and is privy to some of its internals.
  */
 function SearchSpec(aViewWrapper) {
   this.owner = aViewWrapper;
 
   this._viewTerms = null;
@@ -32,17 +24,17 @@ function SearchSpec(aViewWrapper) {
   this._listenersRegistered = false;
 
   this._onlineSearch = false;
 }
 SearchSpec.prototype = {
   /**
    * Clone this SearchSpec; intended to be used by DBViewWrapper.clone().
    */
-  clone: function SearchSpec_clone(aViewWrapper) {
+  clone(aViewWrapper) {
     let doppel = new SearchSpec(aViewWrapper);
 
     // we can just copy the terms since we never mutate them
     doppel._viewTerms = this._viewTerms;
     doppel._virtualFolderTerms = this._virtualFolderTerms;
     doppel._userTerms = this._userTerms;
 
     // _session can stay null
@@ -83,54 +75,52 @@ SearchSpec.prototype = {
    * (Potentially) add the db view as a search listener and kick off the search.
    *  We only do that if we have search terms.  The intent is to allow you to
    *  call this all the time, even if you don't need to.
    * DBViewWrapper._applyViewChanges used to handle a lot more of this, but our
    *  need to make sure that the session listener gets added after the DBView
    *  caused us to introduce this method.  (We want the DB View's OnDone method
    *  to run before our listener, as it may do important work.)
    */
-  associateView: function SearchSpec_associateView(aDBView) {
+  associateView(aDBView) {
     if (this.hasSearchTerms) {
       this.updateSession();
 
       if (this.owner.isSynthetic) {
         this.owner._syntheticView.search(new FilteringSyntheticListener(this));
-      }
-      else {
+      } else {
         if (!this._sessionListener)
           this._sessionListener = new SearchSpecListener(this);
 
         this.session.registerListener(aDBView,
                                       Ci.nsIMsgSearchSession.allNotifications);
         aDBView.searchSession = this._session;
         this._session.registerListener(this._sessionListener,
                                        Ci.nsIMsgSearchSession.onNewSearch |
                                        Ci.nsIMsgSearchSession.onSearchDone);
         this._listenersRegistered = true;
 
         this.owner.searching = true;
         this.session.search(this.owner.listener.msgWindow);
       }
-    }
-    // if it's synthetic but we have no search terms, hook the output of the
-    //  synthetic view directly up to the search nsIMsgDBView
-    else if (this.owner.isSynthetic) {
+    } else if (this.owner.isSynthetic) {
+      // If it's synthetic but we have no search terms, hook the output of the
+      // synthetic view directly up to the search nsIMsgDBView.
       let owner = this.owner;
       owner.searching = true;
       this.owner._syntheticView.search(
         aDBView.QueryInterface(Ci.nsIMsgSearchNotify),
         function() { owner.searching = false; });
     }
   },
   /**
    * Stop any active search and stop the db view being a search listener (if it
    *  is one).
    */
-  dissociateView: function SearchSpec_dissociateView(aDBView) {
+  dissociateView(aDBView) {
     // If we are currently searching, interrupt the search.  This will
     //  immediately notify the listeners that the search is done with and
     //  clear the searching flag for us.
     if (this.owner.searching) {
       if (this.owner.isSynthetic)
         this.owner._syntheticView.abortSearch();
       else
         this.session.interruptSearch();
@@ -146,18 +136,17 @@ SearchSpec.prototype = {
 
   /**
    * Given a list of terms, mutate them so that they form a single boolean
    *  group.
    *
    * @param aTerms The search terms
    * @param aCloneTerms Do we need to clone the terms?
    */
-  _flattenGroupifyTerms: function SearchSpec__flattenGroupifyTerms(aTerms,
-                                                                   aCloneTerms){
+  _flattenGroupifyTerms(aTerms, aCloneTerms) {
     let iTerm = 0, term;
     let outTerms = aCloneTerms ? [] : aTerms;
     for (term of fixIterator(aTerms, Ci.nsIMsgSearchTerm)) {
       if (aCloneTerms) {
         let cloneTerm = this.session.createTerm();
         cloneTerm.value = term.value;
         cloneTerm.attrib = term.attrib;
         cloneTerm.arbitraryHeader = term.arbitraryHeader;
@@ -168,18 +157,17 @@ SearchSpec.prototype = {
         cloneTerm.matchAll = term.matchAll;
         term = cloneTerm;
         outTerms.push(term);
       }
       if (iTerm == 0) {
         term.beginsGrouping = true;
         term.endsGrouping = false;
         term.booleanAnd = true;
-      }
-      else {
+      } else {
         term.beginsGrouping = false;
         term.endsGrouping = false;
       }
       iTerm++;
     }
     if (term)
       term.endsGrouping = true;
 
@@ -193,32 +181,31 @@ SearchSpec.prototype = {
    *  a single group, maintaining the booleanAnd state of terms.
    *
    * This particular logic is desired because it allows the quick filter bar to
    *  produce interesting and useful filters.
    *
    * @param aTerms The search terms
    * @param aCloneTerms Do we need to clone the terms?
    */
-  _groupifyTerms: function SearchSpec__groupifyTerms(aTerms, aCloneTerms) {
+  _groupifyTerms(aTerms, aCloneTerms) {
     let term;
     let outTerms = aCloneTerms ? [] : aTerms;
     let inGroup = false;
     for (term of fixIterator(aTerms, Ci.nsIMsgSearchTerm)) {
       // If we're in a group, all that is forbidden is the creation of new
       // groups.
       if (inGroup) {
         if (term.beginsGrouping) // forbidden!
           return this._flattenGroupifyTerms(aTerms, aCloneTerms);
         else if (term.endsGrouping)
           inGroup = false;
-      }
-      // If we're not in a group, the boolean must be AND.  It's okay for a group
-      // to start.
-      else {
+      } else {
+        // If we're not in a group, the boolean must be AND.  It's okay for a group
+        // to start.
         // If it's not an AND then it needs to be in a group and we use the other
         //  function to take care of it.  (This function can't back up...)
         if (!term.booleanAnd)
           return this._flattenGroupifyTerms(aTerms, aCloneTerms);
 
         inGroup = term.beginsGrouping;
       }
 
@@ -312,17 +299,17 @@ SearchSpec.prototype = {
   /**
    * @return the user terms currently in effect as set via the |userTerms|
    *     attribute or via the |quickSearch| method.  Do not mutate this.
    */
   get userTerms() {
     return this._userTerms;
   },
 
-  clear: function SearchSpec_clear() {
+  clear() {
     if (this.hasSearchTerms) {
       this._viewTerms = null;
       this._virtualFolderTerms = null;
       this._userTerms = null;
       this.owner._applyViewChanges();
     }
   },
 
@@ -347,107 +334,94 @@ SearchSpec.prototype = {
   },
 
   /**
    * Populate the search session using viewTerms, virtualFolderTerms, and
    *  userTerms.  The way this works is that each of the 'context' sets of
    *  terms gets wrapped into a group which is boolean anded together with
    *  everything else.
    */
-  updateSession: function SearchSpec_applySearch() {
+  updateSession() {
     let session = this.session;
 
     // clear out our current terms and scope
     session.searchTerms.clear();
     session.clearScopes();
 
-    // the scope logic needs to know if any terms look at the body attribute.
-    let haveBodyTerm = false;
-
     // -- apply terms
     if (this._virtualFolderTerms) {
-      for (let term of fixIterator(this._virtualFolderTerms,
-                                   nsIMsgSearchTerm)) {
-        if (term.attrib == nsMsgSearchAttrib.Body)
-          haveBodyTerm = true;
+      for (let term of fixIterator(this._virtualFolderTerms, Ci.nsIMsgSearchTerm)) {
         session.appendTerm(term);
       }
     }
 
     if (this._viewTerms) {
-      for (let term of fixIterator(this._viewTerms,
-                                   nsIMsgSearchTerm)) {
-        if (term.attrib == nsMsgSearchAttrib.Body)
-          haveBodyTerm = true;
+      for (let term of fixIterator(this._viewTerms, Ci.nsIMsgSearchTerm)) {
         session.appendTerm(term);
       }
     }
 
     if (this._userTerms) {
-      for (let term of fixIterator(this._userTerms,
-                                   nsIMsgSearchTerm)) {
-        if (term.attrib == nsMsgSearchAttrib.Body)
-          haveBodyTerm = true;
+      for (let term of fixIterator(this._userTerms, Ci.nsIMsgSearchTerm)) {
         session.appendTerm(term);
       }
     }
 
     // -- apply scopes
     // If it is a synthetic view, create a single bogus scope so that we can use
     //  MatchHdr.
     if (this.owner.isSynthetic) {
       // We don't want to pass in a folder, and we don't want to use the
       //  allSearchableGroups scope, so we cheat and use AddDirectoryScopeTerm.
-      session.addDirectoryScopeTerm(nsMsgSearchScope.offlineMail);
+      session.addDirectoryScopeTerm(Ci.nsMsgSearchScope.offlineMail);
       return;
     }
 
     let filtering = this._userTerms != null || this._viewTerms != null;
-    let validityManager = Cc['@mozilla.org/mail/search/validityManager;1']
+    let validityManager = Cc["@mozilla.org/mail/search/validityManager;1"]
                             .getService(Ci.nsIMsgSearchValidityManager);
     for (let folder of this.owner._underlyingFolders) {
       // we do not need to check isServer here because _underlyingFolders
       //  filtered it out when it was initialized.
 
       let scope;
       let serverScope = folder.server.searchScope;
       // If we're offline, or this is a local folder, or there's no separate
       //  online scope, use server scope.
-      if (Services.io.offline || (serverScope == nsMsgSearchScope.offlineMail) ||
-                                 (folder instanceof nsIMsgLocalMailFolder))
+      if (Services.io.offline || (serverScope == Ci.nsMsgSearchScope.offlineMail) ||
+                                 (folder instanceof Ci.nsIMsgLocalMailFolder)) {
         scope = serverScope;
-      else {
+      } else {
         // we need to test the validity in online and offline tables
         let onlineValidityTable = validityManager.getTable(serverScope);
 
         let offlineScope;
-        if (folder.flags & nsMsgFolderFlags.Offline)
-          offlineScope = nsMsgSearchScope.offlineMail;
+        if (folder.flags & Ci.nsMsgFolderFlags.Offline)
+          offlineScope = Ci.nsMsgSearchScope.offlineMail;
         else
           // The onlineManual table is used for local search when there is no
           //  body available.
-          offlineScope = nsMsgSearchScope.onlineManual;
+          offlineScope = Ci.nsMsgSearchScope.onlineManual;
 
         let offlineValidityTable = validityManager.getTable(offlineScope);
         let offlineAvailable = true;
         let onlineAvailable = true;
         for (let term of fixIterator(session.searchTerms,
-                                     nsIMsgSearchTerm)) {
+                                     Ci.nsIMsgSearchTerm)) {
           if (!term.matchAll) {
             // for custom terms, we need to getAvailable from the custom term
             if (term.attrib == Ci.nsMsgSearchAttrib.Custom) {
               let customTerm = MailServices.filters.getCustomTerm(term.customId);
               if (customTerm) {
                 offlineAvailable = customTerm.getAvailable(offlineScope, term.op);
                 onlineAvailable = customTerm.getAvailable(serverScope, term.op);
-              }
-              else // maybe an extension with a custom term was unloaded?
+              } else { // maybe an extension with a custom term was unloaded?
                 Cu.reportError("Custom search term " + term.customId + " missing");
-            }
-            else {
+              }
+            } else {
               if (!offlineValidityTable.getAvailable(term.attrib, term.op))
                 offlineAvailable = false;
               if (!onlineValidityTable.getAvailable(term.attrib, term.op))
                 onlineAvailable = false;
             }
           }
         }
         // If both scopes work, honor the onlineSearch request, unless we're
@@ -459,67 +433,67 @@ SearchSpec.prototype = {
           scope = serverScope;
         else
           scope = offlineScope;
       }
       session.addScopeTerm(scope, folder);
     }
   },
 
-  prettyStringOfSearchTerms: function(aSearchTerms) {
+  prettyStringOfSearchTerms(aSearchTerms) {
     if (aSearchTerms == null)
-      return '      (none)\n';
+      return "      (none)\n";
 
-    let s = '';
+    let s = "";
 
-    for (let term of fixIterator(aSearchTerms, nsIMsgSearchTerm)) {
-      s += '      ' + term.termAsString + '\n';
+    for (let term of fixIterator(aSearchTerms, Ci.nsIMsgSearchTerm)) {
+      s += "      " + term.termAsString + "\n";
     }
 
     return s;
   },
 
-  prettyString: function() {
-    let s = '  Search Terms:\n';
-    s += '    Virtual Folder Terms:\n';
+  prettyString() {
+    let s = "  Search Terms:\n";
+    s += "    Virtual Folder Terms:\n";
     s += this.prettyStringOfSearchTerms(this._virtualFolderTerms);
-    s += '    View Terms:\n';
+    s += "    View Terms:\n";
     s += this.prettyStringOfSearchTerms(this._viewTerms);
-    s += '    User Terms:\n';
+    s += "    User Terms:\n";
     s += this.prettyStringOfSearchTerms(this._userTerms);
-    s += '    Scope (Folders):\n';
+    s += "    Scope (Folders):\n";
     for (let folder of this.owner._underlyingFolders) {
-      s += '      ' + folder.prettyName + '\n';
+      s += "      " + folder.prettyName + "\n";
     }
     return s;
   },
 };
 
 /**
  * A simple nsIMsgSearchNotify listener that only listens for search start/stop
  *  so that it can tell the DBViewWrapper when the search has completed.
  */
 function SearchSpecListener(aSearchSpec) {
   this.searchSpec = aSearchSpec;
 }
 SearchSpecListener.prototype = {
-  onNewSearch: function SearchSpecListener_onNewSearch() {
+  onNewSearch() {
     // searching should already be true by the time this happens.  if it's not,
     //  it means some code is poking at the search session.  bad!
     if (!this.searchSpec.owner.searching) {
       Cu.reportErrror("Search originated from unknown initiator! Confusion!");
       this.searchSpec.owner.searching = true;
     }
   },
 
-  onSearchHit: function SearchSpecListener_onSearchHit(aMsgHdr, aFolder) {
+  onSearchHit(aMsgHdr, aFolder) {
     // this method is never invoked!
   },
 
-  onSearchDone: function SearchSpecListener_onSearchDone(aStatus) {
+  onSearchDone(aStatus) {
     this.searchSpec.owner.searching = false;
   },
 };
 
 /**
  * Pretend to implement the nsIMsgSearchNotify interface, checking all matches
  *  we are given against the search session on the search spec.  If they pass,
  *  relay them to the underlying db view, otherwise quietly eat them.
@@ -528,25 +502,24 @@ SearchSpecListener.prototype = {
  */
 function FilteringSyntheticListener(aSearchSpec) {
   this.searchSpec = aSearchSpec;
   this.session = this.searchSpec.session;
   this.dbView =
     this.searchSpec.owner.dbView.QueryInterface(Ci.nsIMsgSearchNotify);
 }
 FilteringSyntheticListener.prototype = {
-  onNewSearch: function FilteringSyntheticListener_onNewSearch() {
+  onNewSearch() {
     this.searchSpec.owner.searching = true;
     this.dbView.onNewSearch();
   },
-  onSearchHit:
-      function FilteringSyntheticListener_onSearchHit(aMsgHdr, aFolder) {
+  onSearchHit(aMsgHdr, aFolder) {
     // We don't need to worry about msgDatabase opening the database.
     // It is (obviously) already open, and presumably gloda is already on the
     //  hook to perform the cleanup (assuming gloda is backing this search).
     if (this.session.MatchHdr(aMsgHdr, aFolder.msgDatabase))
       this.dbView.onSearchHit(aMsgHdr, aFolder);
   },
-  onSearchDone: function FilteringSyntheticListener_OnSearchDone(aStatus) {
+  onSearchDone(aStatus) {
     this.searchSpec.owner.searching = false;
     this.dbView.onSearchDone(aStatus);
-  }
+  },
 };
--- a/mail/base/modules/SessionStoreManager.jsm
+++ b/mail/base/modules/SessionStoreManager.jsm
@@ -1,34 +1,25 @@
 /* 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/. */
 
-/**
- * Session Storage and Restoration
- */
-
-/* :::::::: Constants and Helpers ::::::::::::::: */
-
 this.EXPORTED_SYMBOLS = ["SessionStoreManager"];
 
 ChromeUtils.import("resource://gre/modules/JSONFile.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 /**
  * asuth arbitrarily chose this value to trade-off powersaving,
  * processor usage, and recency of state in the face of the impossibility of
  * our crashing; he also worded this.
  */
 var SESSION_AUTO_SAVE_DEFAULT_MS = 300000; // 5 minutes
 
-/* :::::::: The Module ::::::::::::::: */
-
-var SessionStoreManager =
-{
+var SessionStoreManager = {
   _initialized: false,
 
   /**
    * Session restored successfully on startup; use this to test for an early
    * failed startup which does not restore user tab state to ensure a session
    * save on close will not overwrite the last good session state.
    */
   _restored: false,
@@ -49,94 +40,88 @@ var SessionStoreManager =
    * session has been persisted to disk. See |observe| and |unloadingWindow|
    * for justification on why we need this.
    */
   _shutdownStateSaved: false,
 
   /**
    * The JSONFile store object.
    */
-  get store()
-  {
+  get store() {
     if (this._store)
       return this._store;
 
     return this._store = new JSONFile({path: this.sessionFile.path});
   },
 
   /**
    * Gets the nsIFile used for session storage.
    */
-  get sessionFile()
-  {
+  get sessionFile() {
     let sessionFile = Services.dirsvc.get("ProfD", Ci.nsIFile);
     sessionFile.append("session.json");
     return sessionFile;
   },
 
   /**
    * This is called on startup, and when a new 3 pane window is opened after
    * the last 3 pane window was closed (e.g., on the mac, closing the last
    * window doesn't shut down the app).
    */
-  async _init()
-  {
+  async _init() {
     await this._loadSessionFile();
 
     // we listen for "quit-application-granted" instead of
     // "quit-application-requested" because other observers of the
     // latter can cancel the shutdown.
     Services.obs.addObserver(this, "quit-application-granted");
 
     this.startPeriodicSave();
 
     this._initialized = true;
   },
 
   /**
    * Loads the session file into _initialState. This should only be called by
    * _init and a unit test.
    */
-  async _loadSessionFile()
-  {
+  async _loadSessionFile() {
     if (!this.sessionFile.exists())
       return;
 
     // Read the session state data from file, asynchronously.
     // An error on the json file returns an empty object which corresponds
     // to a null |_initialState|.
     await this.store.load();
     this._initialState = this.store.data.toSource() == {}.toSource() ?
                            null : this.store.data;
 
   },
 
   /**
    * Opens the windows that were open in the previous session.
    */
-  _openOtherRequiredWindows: function ssm_openOtherRequiredWindows(aWindow)
-  {
+  _openOtherRequiredWindows(aWindow) {
     // XXX we might want to display a restore page and let the user decide
     // whether to restore the other windows, just like Firefox does.
 
     if (!this._initialState || !this._initialState.windows || !aWindow)
       return;
 
     for (var i = 0; i < this._initialState.windows.length; ++i)
       aWindow.open(
              "chrome://messenger/content/messenger.xul",
              "_blank",
              "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
   },
 
   /**
    * Writes the state object to disk.
    */
-  _saveStateObject: function ssm_saveStateObject(aStateObj)
-  {
+  _saveStateObject(aStateObj) {
     if (!this.store) {
       Cu.reportError("SessionStoreManager: could not create data store from file");
       return;
     }
 
     let currentStateString = JSON.stringify(aStateObj);
     let storedStateString = this.store.dataReady && this.store.data ?
                               JSON.stringify(this.store.data) : null;
@@ -148,54 +133,49 @@ var SessionStoreManager =
 
     this.store.data = aStateObj;
     this.store.saveSoon();
   },
 
   /**
    * @return an empty state object that can be populated with window states.
    */
-  _createStateObject: function ssm_createStateObject()
-  {
+  _createStateObject() {
     return {
       rev: 0,
-      windows: []
+      windows: [],
     };
   },
 
   /**
    * Writes the state of all currently open 3pane windows to disk.
    */
-  _saveState: function ssm_saveState()
-  {
+  _saveState() {
     let state = this._createStateObject();
 
     // XXX we'd like to support other window types in future, but for now
     // only get the 3pane windows.
     let enumerator = Services.wm.getEnumerator("mail:3pane");
     while (enumerator.hasMoreElements()) {
       let win = enumerator.getNext();
       if (win && "complete" == win.document.readyState &&
           win.getWindowStateForSessionPersistence)
         state.windows.push(win.getWindowStateForSessionPersistence());
     }
 
     this._saveStateObject(state);
   },
 
-/* ........ Timer Callback ................*/
-
-  _sessionAutoSaveTimerCallback: function ssm_sessionAutoSaveTimerCallback()
-  {
+  // Timer Callback
+  _sessionAutoSaveTimerCallback() {
     SessionStoreManager._saveState();
   },
 
-/* ........ Observer Notification Handler ................*/
-
-  observe: function ssm_observe(aSubject, aTopic, aData) {
+  // Observer Notification Handler
+  observe(aSubject, aTopic, aData) {
     switch (aTopic) {
     // This is observed before any windows start unloading if something other
     // than the last 3pane window closing requested the application be
     // shutdown. For example, when the user quits via the file menu.
     case "quit-application-granted":
       if (!this._shutdownStateSaved) {
         this.stopPeriodicSave();
         this._saveState();
@@ -203,26 +183,25 @@ var SessionStoreManager =
         // this is to ensure we don't clobber the saved state when the
         // 3pane windows unload.
         this._shutdownStateSaved = true;
       }
       break;
     }
   },
 
-/* ........ Public API ................*/
+  // Public API
 
   /**
    * Called by each 3pane window instance when it loads.
    *
    * @return a window state object if aWindow was opened as a result of a
    *         session restoration, null otherwise.
    */
-  async loadingWindow(aWindow)
-  {
+  async loadingWindow(aWindow) {
     let firstWindow = !this._initialized || this._shutdownStateSaved;
     if (firstWindow)
       await this._init();
 
     // If we are seeing a new 3-pane, we are obviously not in a shutdown
     // state anymore.  (This would happen if all the 3panes got closed but
     // we did not quit because another window was open and then a 3pane showed
     // up again.  This can happen in both unit tests and real life.)
@@ -242,18 +221,17 @@ var SessionStoreManager =
     return windowState;
   },
 
   /**
    * Called by each 3pane window instance when it unloads. If aWindow is the
    * last 3pane window, its state is persisted. The last 3pane window unloads
    * first before the "quit-application-granted" event is generated.
    */
-  unloadingWindow: function ssm_unloadingWindow(aWindow)
-  {
+  unloadingWindow(aWindow) {
     if (!this._shutdownStateSaved) {
       // determine whether aWindow is the last open window
       let lastWindow = true;
       let enumerator = Services.wm.getEnumerator("mail:3pane");
       while (enumerator.hasMoreElements()) {
         if (enumerator.getNext() != aWindow)
           lastWindow = false;
       }
@@ -273,34 +251,32 @@ var SessionStoreManager =
         this._shutdownStateSaved = true;
       }
     }
   },
 
   /**
    * Stops periodic session persistence.
    */
-  stopPeriodicSave: function ssm_stopPeriodicSave()
-  {
+  stopPeriodicSave() {
     if (this._sessionAutoSaveTimer) {
       this._sessionAutoSaveTimer.cancel();
 
       delete this._sessionAutoSaveTimer;
       this._sessionAutoSaveTimer = null;
     }
   },
 
   /**
    * Starts periodic session persistence.
    */
-  startPeriodicSave: function ssm_startPeriodicSave()
-  {
+  startPeriodicSave() {
     if (!this._sessionAutoSaveTimer) {
       this._sessionAutoSaveTimer = Cc["@mozilla.org/timer;1"]
                                    .createInstance(Ci.nsITimer);
 
       this._sessionAutoSaveTimer.initWithCallback(
                                    this._sessionAutoSaveTimerCallback,
                                    this._sessionAutoSaveTimerIntervalMS,
                                    Ci.nsITimer.TYPE_REPEATING_SLACK);
     }
-  }
+  },
 };
--- a/mail/base/modules/SummaryFrameManager.jsm
+++ b/mail/base/modules/SummaryFrameManager.jsm
@@ -25,71 +25,66 @@ function SummaryFrameManager(aFrame) {
   this.callback = null;
   this.url = "";
 }
 
 SummaryFrameManager.prototype = {
   /**
    * Clear the summary frame.
    */
-  clear: function() {
+  clear() {
     this.loadAndCallback("about:blank");
   },
 
   /**
    * Load the specified URL if necessary, and cause the specified callback to be
    * called either when the document is loaded, or immediately if the document
    * is already loaded.
    *
    * @param aUrl the URL to load
    * @param aCallback the callback to run when the URL has loaded; this function
    *        is passed a single boolean indicating if the URL was changed
    */
-  loadAndCallback: function(aUrl, aCallback) {
+  loadAndCallback(aUrl, aCallback) {
     this.url = aUrl;
     if (this.pendingOrLoadedUrl != aUrl) {
       // We're changing the document. Stash the callback that we want to call
       // when it's done loading
       this.pendingCallback = aCallback;
       this.callback = null; // clear it
       this.iframe.contentDocument.location.href = aUrl;
       this.pendingOrLoadedUrl = aUrl;
-    }
-    else {
+    } else if (!this.pendingCallback) {
       // We're being called, but the document has been set already -- either
       // we've already received the DOMContentLoaded event, in which case we can
       // just call the callback directly, or we're still loading in which case
       // we should just wait for the dom event handler, but update the callback.
 
-      if (!this.pendingCallback) {
-        this.callback = aCallback;
-        if (this.callback) {
-          this.callback(false);
-        }
+      this.callback = aCallback;
+      if (this.callback) {
+        this.callback(false);
       }
-      else {
-        this.pendingCallback = aCallback;
-      }
+    } else {
+      this.pendingCallback = aCallback;
     }
   },
 
-  _onLoad: function(event) {
+  _onLoad(event) {
     try {
       // Make sure we're responding to the summary frame being loaded, and not
       // some subnode.
       if (event.originalTarget != this.iframe.contentDocument ||
           this.pendingOrLoadedUrl == "about:blank")
         return;
 
       this.callback = this.pendingCallback;
       this.pendingCallback = null;
       if (this.pendingOrLoadedUrl != this.iframe.contentDocument.location.href)
         Cu.reportError(
-          "Please do not load stuff in the multimessage browser directly, "+
+          "Please do not load stuff in the multimessage browser directly, " +
           "use the SummaryFrameManager instead.");
       else if (this.callback)
         this.callback(true);
-    }
-    catch (e) {
+    } catch (e) {
       Cu.reportError(e);
     }
-  }
+  },
 };
--- a/mail/base/modules/TBDistCustomizer.jsm
+++ b/mail/base/modules/TBDistCustomizer.jsm
@@ -1,38 +1,38 @@
 /* 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/. */
 
+// This file uses eval, but really shouldn't. See bug 1498497.
+/* eslint-disable no-eval */
+
 this.EXPORTED_SYMBOLS = ["TBDistCustomizer"];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-var DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
-  "distribution-customization-complete";
-
 var TBDistCustomizer = {
-  applyPrefDefaults: function TBDistCustomizer_applyPrefDefaults() {
+  applyPrefDefaults() {
     this._prefDefaultsApplied = true;
     if (!this._ini) {
       return;
     }
     // Grab the sections of the ini file
     let sections = enumToObject(this._ini.getSections());
 
     // The global section, and several of its fields, is required
     // Function exits if this section and its fields are not present
-    if (!sections["Global"]) {
+    if (!sections.Global) {
       return;
     }
 
     // Get the keys in the "Global" section  of the ini file
     let globalPrefs = enumToObject(this._ini.getKeys("Global"));
-    if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"])) {
+    if (!(globalPrefs.id && globalPrefs.version && globalPrefs.about)) {
       return;
     }
 
     // Get the entire preferences tree (defaults is an instance of nsIPrefBranch)
     let defaults = Services.prefs.getDefaultBranch(null);
 
     // Set the following user prefs
     defaults.setCharPref("distribution.id", this._ini.getString("Global", "id"));
@@ -41,17 +41,17 @@ var TBDistCustomizer = {
     let partnerAbout;
     if (globalPrefs["about." + this._locale]) {
       partnerAbout = this._ini.getString("Global", "about." + this._locale);
     } else {
       partnerAbout = this._ini.getString("Global", "about");
     }
     defaults.setStringPref("distribution.about", partnerAbout);
 
-    if (sections["Preferences"]) {
+    if (sections.Preferences) {
       let keys = this._ini.getKeys("Preferences");
       while (keys.hasMore()) {
         let key = keys.getNext();
         try {
           // Get the string value of the key
           let value = eval(this._ini.getString("Preferences", key));
           // After determining what type it is, set the pref
           switch (typeof value) {
@@ -79,17 +79,17 @@ var TBDistCustomizer = {
 
     // We eval() the localizable prefs as well (even though they'll
     // always get set as a string) to keep the INI format consistent:
     // string prefs always need to be in quotes
 
     let localizedStr = Cc["@mozilla.org/pref-localizedstring;1"]
                          .createInstance(Ci.nsIPrefLocalizedString);
 
-    if (sections["LocalizablePreferences"]) {
+    if (sections.LocalizablePreferences) {
       let keys = this._ini.getKeys("LocalizablePreferences");
       while (keys.hasMore()) {
         let key = keys.getNext();
         try {
           let value = eval(this._ini.getString("LocalizablePreferences", key));
           value = value.replace(/%LOCALE%/g, this._locale);
           localizedStr.data = "data:text/plain," + key + "=" + value;
           defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
@@ -107,38 +107,35 @@ var TBDistCustomizer = {
           let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
           localizedStr.data = "data:text/plain," + key + "=" + value;
           defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
         } catch (e) {
           Cu.reportError(e);
         }
       }
     }
-    return true;
-  }
+  },
 };
 
-XPCOMUtils.defineLazyGetter(TBDistCustomizer, "_ini",
-  function TBDistCustomizer_get__ini() {
-    let ini = null;
-    let iniFile = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
-    iniFile.append("distribution");
-    iniFile.append("distribution.ini");
-    if (iniFile.exists()) {
-      ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]
-              .getService(Ci.nsIINIParserFactory)
-              .createINIParser(iniFile);
-    }
-    return ini;
+XPCOMUtils.defineLazyGetter(TBDistCustomizer, "_ini", function() {
+  let ini = null;
+  let iniFile = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
+  iniFile.append("distribution");
+  iniFile.append("distribution.ini");
+  if (iniFile.exists()) {
+    ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]
+            .getService(Ci.nsIINIParserFactory)
+            .createINIParser(iniFile);
+  }
+  return ini;
 });
 
-XPCOMUtils.defineLazyGetter(TBDistCustomizer, "_locale",
-  function TBDistCustomizer_get__locale() {
-    return Services.locale.requestedLocale;
+XPCOMUtils.defineLazyGetter(TBDistCustomizer, "_locale", function() {
+  return Services.locale.requestedLocale;
 });
 
 function enumToObject(UTF8Enumerator) {
   let ret = {};
   while (UTF8Enumerator.hasMore()) {
-    ret[UTF8Enumerator.getNext()] = 1
+    ret[UTF8Enumerator.getNext()] = 1;
   }
   return ret;
 }
--- a/mail/base/modules/ThemeVariableMap.jsm
+++ b/mail/base/modules/ThemeVariableMap.jsm
@@ -5,85 +5,85 @@
 var EXPORTED_SYMBOLS = ["ThemeVariableMap", "ThemeContentPropertyList"];
 
 function _isTextColorDark(r, g, b) {
   return (0.2125 * r + 0.7154 * g + 0.0721 * b) <= 110;
 }
 
 const ThemeVariableMap = [
   ["--lwt-accent-color-inactive", {
-    lwtProperty: "accentcolorInactive"
+    lwtProperty: "accentcolorInactive",
   }],
   ["--lwt-background-alignment", {
     isColor: false,
-    lwtProperty: "backgroundsAlignment"
+    lwtProperty: "backgroundsAlignment",
   }],
   ["--lwt-background-tiling", {
     isColor: false,
-    lwtProperty: "backgroundsTiling"
+    lwtProperty: "backgroundsTiling",
   }],
   ["--tab-loading-fill", {
     lwtProperty: "tab_loading",
   }],
   ["--lwt-tab-text", {
-    lwtProperty: "tab_text"
+    lwtProperty: "tab_text",
   }],
   ["--tab-line-color", {
     lwtProperty: "tab_line",
   }],
   ["--lwt-background-tab-separator-color", {
     lwtProperty: "tab_background_separator",
   }],
   ["--toolbar-bgcolor", {
-    lwtProperty: "toolbarColor"
+    lwtProperty: "toolbarColor",
   }],
   ["--toolbar-color", {
-    lwtProperty: "toolbar_text"
+    lwtProperty: "toolbar_text",
   }],
   ["--urlbar-separator-color", {
-    lwtProperty: "toolbar_field_separator"
+    lwtProperty: "toolbar_field_separator",
   }],
   ["--tabs-border-color", {
     lwtProperty: "toolbar_top_separator",
   }],
   ["--lwt-toolbar-vertical-separator", {
-    lwtProperty: "toolbar_vertical_separator"
+    lwtProperty: "toolbar_vertical_separator",
   }],
   ["--toolbox-border-bottom-color", {
-    lwtProperty: "toolbar_bottom_separator"
+    lwtProperty: "toolbar_bottom_separator",
   }],
   ["--lwt-toolbarbutton-icon-fill", {
-    lwtProperty: "icon_color"
+    lwtProperty: "icon_color",
   }],
   ["--lwt-toolbarbutton-icon-fill-attention", {
-    lwtProperty: "icon_attention_color"
+    lwtProperty: "icon_attention_color",
   }],
   ["--lwt-toolbarbutton-hover-background", {
-    lwtProperty: "button_background_hover"
+    lwtProperty: "button_background_hover",
   }],
   ["--lwt-toolbarbutton-active-background", {
-    lwtProperty: "button_background_active"
+    lwtProperty: "button_background_active",
   }],
   ["--lwt-selected-tab-background-color", {
-    lwtProperty: "tab_selected"
+    lwtProperty: "tab_selected",
   }],
   ["--autocomplete-popup-background", {
-    lwtProperty: "popup"
+    lwtProperty: "popup",
   }],
   ["--autocomplete-popup-color", {
-    lwtProperty: "popup_text"
+    lwtProperty: "popup_text",
   }],
   ["--autocomplete-popup-border-color", {
-    lwtProperty: "popup_border"
+    lwtProperty: "popup_border",
   }],
   ["--autocomplete-popup-highlight-background", {
-    lwtProperty: "popup_highlight"
+    lwtProperty: "popup_highlight",
   }],
   ["--autocomplete-popup-highlight-color", {
-    lwtProperty: "popup_highlight_text"
+    lwtProperty: "popup_highlight_text",
   }],
   ["--sidebar-background-color", {
     lwtProperty: "sidebar",
   }],
   ["--sidebar-text-color", {
     lwtProperty: "sidebar_text",
     processColor(rgbaChannels, element) {
       if (!rgbaChannels) {
--- a/mail/base/modules/Windows8WindowFrameColor.jsm
+++ b/mail/base/modules/Windows8WindowFrameColor.jsm
@@ -1,24 +1,22 @@
 /* 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";
 
 this.EXPORTED_SYMBOLS = ["Windows8WindowFrameColor"];
 
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-const { WindowsRegistry } = ChromeUtils.import("resource://gre/modules/WindowsRegistry.jsm", null);
+ChromeUtils.import("resource://gre/modules/WindowsRegistry.jsm");
 
 var Windows8WindowFrameColor = {
   _windowFrameColor: null,
 
-  get: function() {
+  get() {
     if (this._windowFrameColor)
       return this._windowFrameColor;
 
     const HKCU = Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER;
     const dwmKey = "Software\\Microsoft\\Windows\\DWM";
     let customizationColor = WindowsRegistry.readRegKey(HKCU, dwmKey,
                                                         "ColorizationColor");
     if (customizationColor == undefined) {
@@ -27,17 +25,17 @@ var Windows8WindowFrameColor = {
     }
 
     // The color returned from the Registry is in decimal form.
     let customizationColorHex = customizationColor.toString(16);
 
     // Zero-pad the number just to make sure that it is 8 digits.
     customizationColorHex = ("00000000" + customizationColorHex).substr(-8);
     let customizationColorArray = customizationColorHex.match(/../g);
-    let [unused, fgR, fgG, fgB] = customizationColorArray.map(val => parseInt(val, 16));
+    let [, fgR, fgG, fgB] = customizationColorArray.map(val => parseInt(val, 16));
     let colorizationColorBalance = WindowsRegistry.readRegKey(HKCU, dwmKey,
                                                               "ColorizationColorBalance");
     if (colorizationColorBalance == undefined) {
       colorizationColorBalance = 78;
     }
 
     // Window frame base color when Color Intensity is at 0, see bug 1004576.
     let frameBaseColor = 217;