Bug 1515877 - Turn on ESLint in mailnews/mime; r=aceman
authorGeoff Lankow <geoff@darktrojan.net>
Mon, 13 May 2019 19:54:17 +1200
changeset 73614 b2447f459283d075a942a40adcdb726471e543ba
parent 73613 b39e405810ed7a8a2b13d96d8f49f3eead66fed6
child 73615 937e7c60b40043bbdd456e18aaef5df8c0af91a1
push id8446
push usermozilla@jorgk.com
push dateMon, 13 May 2019 12:48:50 +0000
treeherdertry-comm-central@44a039417a1c [default view] [failures only]
reviewersaceman
bugs1515877
Bug 1515877 - Turn on ESLint in mailnews/mime; r=aceman
.eslintignore
mailnews/mime/jsmime/jsmime.js
mailnews/mime/jsmime/test/.eslintrc.js
mailnews/mime/jsmime/test/head_xpcshell_glue.js
mailnews/mime/jsmime/test/mock_date.js
mailnews/mime/jsmime/test/test_custom_headers.js
mailnews/mime/jsmime/test/test_header.js
mailnews/mime/jsmime/test/test_header_emitter.js
mailnews/mime/jsmime/test/test_mime_tree.js
mailnews/mime/jsmime/test/test_structured_header_emitters.js
mailnews/mime/jsmime/test/test_structured_headers.js
mailnews/mime/src/extraMimeParsers.jsm
mailnews/mime/src/jsmime.jsm
mailnews/mime/src/mimeJSComponents.js
mailnews/mime/src/mimeParser.jsm
mailnews/mime/src/mimemcms.cpp
mailnews/mime/test/unit/.eslintrc.js
mailnews/mime/test/unit/custom_header.js
mailnews/mime/test/unit/head_mime.js
mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
mailnews/mime/test/unit/test_alternate_p7m_handling.js
mailnews/mime/test/unit/test_attachment_size.js
mailnews/mime/test/unit/test_badContentType.js
mailnews/mime/test/unit/test_bug493544.js
mailnews/mime/test/unit/test_hidden_attachments.js
mailnews/mime/test/unit/test_jsmime_charset.js
mailnews/mime/test/unit/test_message_attachment.js
mailnews/mime/test/unit/test_mimeContentType.js
mailnews/mime/test/unit/test_mimeStreaming.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser1.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser2.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser3.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser5.js
mailnews/mime/test/unit/test_parser.js
mailnews/mime/test/unit/test_rfc822_body.js
mailnews/mime/test/unit/test_smime_decrypt.js
mailnews/mime/test/unit/test_structured_headers.js
mailnews/mime/test/unit/test_text_attachment.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -59,17 +59,16 @@ editor/ui/dialogs/content/EdSnapToGrid.j
 editor/ui/dialogs/content/EdSnapToGrid.xul
 editor/ui/texzilla/**
 
 # mailnews exclusions
 mailnews/mailnews.js
 mailnews/extensions/dsn/content/dsn.js
 mailnews/extensions/mdn/content/mdn.js
 mailnews/extensions/smime/content/smime.js
-mailnews/mime/*
 
 # mail exclusions
 mail/app/profile/all-thunderbird.js
 mail/app/profile/channel-prefs.js
 mail/app/profile/prefs.js
 mail/base/content/protovis-r2.6-modded.js
 mail/branding/nightly/thunderbird-branding.js
 mail/branding/thunderbird/thunderbird-branding.js
--- a/mailnews/mime/jsmime/jsmime.js
+++ b/mailnews/mime/jsmime/jsmime.js
@@ -1,26 +1,29 @@
-(function (root, fn) {
-  if (typeof define === 'function' && define.amd) {
+/* import-globals-from ../src/jsmime.jsm */
+/* globals define, module */
+
+(function(root, fn) {
+  if (typeof define === "function" && define.amd) {
     define(fn);
-  } else if (typeof module !== 'undefined' && module.exports) {
+  } else if (typeof module !== "undefined" && module.exports) {
     module.exports = fn();
   } else {
     root.jsmime = fn();
   }
 }(this, function() {
   var mods = {};
   function req(id) {
-    return mods[id.replace(/^\.\//, '')];
+    return mods[id.replace(/^\.\//, "")];
   }
 
   function def(id, fn) {
     mods[id] = fn(req);
   }
-def('mimeutils', function() {
+def("mimeutils", function() {
 "use strict";
 
 /**
  * Decode a quoted-printable buffer into a binary string.
  *
  * @param buffer {BinaryString} The string to decode.
  * @param more   {Boolean}      This argument is ignored.
  * @returns {Array(BinaryString, BinaryString)} The first element of the array
@@ -28,53 +31,53 @@ def('mimeutils', function() {
  *          string.
  */
 function decode_qp(buffer, more) {
   // Unlike base64, quoted-printable isn't stateful across multiple lines, so
   // there is no need to buffer input, so we can always ignore more.
   let decoded = buffer.replace(
     // Replace either =<hex><hex> or =<wsp>CRLF
     /=([0-9A-F][0-9A-F]|[ \t]*(\r\n|[\r\n]|$))/gi,
-    function replace_chars(match, param) {
+    function(match, param) {
       // If trailing text matches [ \t]*CRLF, drop everything, since it's a
       // soft line break.
       if (param.trim().length == 0)
-        return '';
+        return "";
       return String.fromCharCode(parseInt(param, 16));
     });
-  return [decoded, ''];
+  return [decoded, ""];
 }
 
 /**
  * Decode a base64 buffer into a binary string. Unlike window.atob, the buffer
  * may contain non-base64 characters that will be ignored.
  *
  * @param buffer {BinaryString} The string to decode.
  * @param more   {Boolean}      If true, we expect that this function could be
  *                              called again and should retain extra data. If
  *                              false, we should flush all pending output.
  * @returns {Array(BinaryString, BinaryString)} The first element of the array
  *          is the decoded string. The second element contains the data that
  *          could not be decoded and needs to be retained for the next call.
  */
 function decode_base64(buffer, more) {
   // Drop all non-base64 characters
-  let sanitize = buffer.replace(/[^A-Za-z0-9+\/=]/g,'');
+  let sanitize = buffer.replace(/[^A-Za-z0-9+\/=]/g, "");
   // Remove harmful `=' chars in the middle.
-  sanitize = sanitize.replace(/=+([A-Za-z0-9+\/])/g, '$1');
+  sanitize = sanitize.replace(/=+([A-Za-z0-9+\/])/g, "$1");
   // We need to encode in groups of 4 chars. If we don't have enough, leave the
   // excess for later. If there aren't any more, drop enough to make it 4.
   let excess = sanitize.length % 4;
   if (excess != 0 && more)
     buffer = sanitize.slice(-excess);
   else
-    buffer = '';
+    buffer = "";
   sanitize = sanitize.substring(0, sanitize.length - excess);
   // Delete all unnecessary '====' in padding.
-  sanitize = sanitize.replace(/(====)+$/g, '');
+  sanitize = sanitize.replace(/(====)+$/g, "");
   // Use the atob function we (ought to) have in global scope.
   return [atob(sanitize), buffer];
 }
 
 /**
  * Converts a binary string into a Uint8Array buffer.
  *
  * @param buffer {BinaryString} The string to convert.
@@ -89,40 +92,40 @@ function stringToTypedArray(buffer) {
 
 /**
  * Converts a Uint8Array buffer to a binary string.
  *
  * @param buffer {BinaryString} The string to convert.
  * @returns {Uint8Array} The converted data.
  */
 function typedArrayToString(buffer) {
-  var string = '';
-  for (var i = 0; i < buffer.length; i+= 100)
+  var string = "";
+  for (let i = 0; i < buffer.length; i += 100)
     string += String.fromCharCode.apply(undefined, buffer.subarray(i, i + 100));
   return string;
 }
 
 /** A list of month names for Date parsing. */
 var kMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
   "Sep", "Oct", "Nov", "Dec"];
 
 return {
-  decode_base64: decode_base64,
-  decode_qp: decode_qp,
-  kMonthNames: kMonthNames,
-  stringToTypedArray: stringToTypedArray,
-  typedArrayToString: typedArrayToString,
+  decode_base64,
+  decode_qp,
+  kMonthNames,
+  stringToTypedArray,
+  typedArrayToString,
 };
 });
 /**
  * This file implements knowledge of how to encode or decode structured headers
  * for several key headers. It is not meant to be used externally to jsmime.
  */
 
-def('structuredHeaders', function (require) {
+def("structuredHeaders", function(require) {
 "use strict";
 
 var structuredDecoders = new Map();
 var structuredEncoders = new Map();
 var preferredSpellings = new Map();
 
 function addHeader(name, decoder, encoder) {
   var lowerName = name.toLowerCase();
@@ -132,19 +135,18 @@ function addHeader(name, decoder, encode
 }
 
 
 // Addressing headers: We assume that they can be specified in 1* form (this is
 // false for From, but it's close enough to the truth that it shouldn't matter).
 // There is no need to specialize the results for the header, so just pun it
 // back to parseAddressingHeader.
 function parseAddress(value) {
-  let results = [];
   let headerparser = this;
-  return value.reduce(function (results, header) {
+  return value.reduce(function(results, header) {
     return results.concat(headerparser.parseAddressingHeader(header, true));
   }, []);
 }
 function writeAddress(value) {
   // Make sure the input is an array (accept a single entry)
   if (!Array.isArray(value))
     value = [value];
   this.addAddresses(value);
@@ -181,30 +183,30 @@ function parseParameterHeader(value, do2
   // Only use the first header for parameters; ignore subsequent redefinitions.
   return this.parseParameterHeader(value[0], do2231, do2047);
 }
 
 // RFC 2045
 function parseContentType(value) {
   let params = parseParameterHeader.call(this, value, false, false);
   let origtype = params.preSemi;
-  let parts = origtype.split('/');
+  let parts = origtype.split("/");
   if (parts.length != 2) {
     // Malformed. Return to text/plain. Evil, ain't it?
     params = new Map();
     parts = ["text", "plain"];
   }
   let mediatype = parts[0].toLowerCase();
   let subtype = parts[1].toLowerCase();
-  let type = mediatype + '/' + subtype;
+  let type = mediatype + "/" + subtype;
   let structure = new Map();
   structure.mediatype = mediatype;
   structure.subtype = subtype;
   structure.type = type;
-  params.forEach(function (value, name) {
+  params.forEach(function(value, name) {
     structure.set(name.toLowerCase(), value);
   });
   return structure;
 }
 structuredDecoders.set("Content-Type", parseContentType);
 
 // Unstructured headers (just decode RFC 2047 for the first header value)
 function parseUnstructured(values) {
@@ -250,53 +252,52 @@ addHeader("NNTP-Posting-Date", parseDate
 
 // RFC 5322
 addHeader("Message-ID", parseMessageID, writeMessageID);
 addHeader("Resent-Message-ID", parseMessageID, writeMessageID);
 
 // Miscellaneous headers (those that don't fall under the above schemes):
 
 // RFC 2047
-structuredDecoders.set("Content-Transfer-Encoding", function (values) {
+structuredDecoders.set("Content-Transfer-Encoding", function(values) {
   return values[0].toLowerCase();
 });
 structuredEncoders.set("Content-Transfer-Encoding", writeUnstructured);
 
 // Some clients like outlook.com send non-compliant References headers that
 // separate values using commas. Also, some clients don't separate References
 // with spaces, since these are optional according to RFC2822. So here we
 // preprocess these headers (see bug 1154521 and bug 1197686).
 function preprocessMessageIDs(values) {
   let msgId = /<[^>]*>/g;
   let match, ids = [];
   while ((match = msgId.exec(values)) !== null) {
     ids.push(match[0]);
   }
-  return ids.join(' ');
+  return ids.join(" ");
 }
 structuredDecoders.set("References", preprocessMessageIDs);
 structuredDecoders.set("In-Reply-To", preprocessMessageIDs);
 
 return Object.freeze({
   decoders: structuredDecoders,
   encoders: structuredEncoders,
   spellings: preferredSpellings,
 });
-
 });
-def('headerparser', function(require) {
+def("headerparser", function(require) {
 /**
  * This file implements the structured decoding of message header fields. It is
  * part of the same system as found in mimemimeutils.js, and occasionally makes
  * references to globals defined in that file or other dependencies thereof. See
  * documentation in that file for more information about external dependencies.
  */
 
 "use strict";
-var mimeutils = require('./mimeutils');
+var mimeutils = require("./mimeutils");
 
 /**
  * This is the API that we ultimately return.
  *
  * We define it as a global here, because we need to pass it as a |this|
  * argument to a few functions.
  */
 var headerparser = {};
@@ -370,28 +371,29 @@ var headerparser = {};
  * @param {Boolean} [opts.dliteral] If true, recognize domain literals.
  * @param {Boolean} [opts.comments] If true, recognize comments.
  * @param {Boolean} [opts.rfc2047]  If true, parse and decode RFC 2047
  *                                  encoded-words.
  * @returns {(Token|String)[]} An array of Token objects (which have a toString
  *                             method returning their value) or String objects
  *                             (representing delimiters).
  */
+/* eslint-disable complexity */
 function getHeaderTokens(value, delimiters, opts) {
   // The array of parsed tokens. This method used to be a generator, but it
   // appears that generators are poorly optimized in current engines, so it was
   // converted to not be one.
   let tokenList = [];
 
-  /// Represents a non-delimiter token
+  // Represents a non-delimiter token
   function Token(token) {
     // Unescape all quoted pairs. Any trailing \ is deleted.
     this.token = token.replace(/\\(.?)/g, "$1");
   }
-  Token.prototype.toString = function () { return this.token; };
+  Token.prototype.toString = function() { return this.token; };
 
   // The start of the current token (e.g., atoms, strings)
   let tokenStart = undefined;
   // The set of whitespace characters, as defined by RFC 5322
   let wsp = " \t\r\n";
   // If we are a domain literal ([]) or a quoted string ("), this is set to the
   // character to look for at the end.
   let endQuote = undefined;
@@ -400,17 +402,17 @@ function getHeaderTokens(value, delimite
   let commentDepth = 0;
 
   // Iterate over every character one character at a time.
   let length = value.length;
   for (let i = 0; i < length; i++) {
     let ch = value[i];
     // If we see a \, no matter what context we are in, ignore the next
     // character.
-    if (ch == '\\') {
+    if (ch == "\\") {
       i++;
       continue;
     }
 
     // If we are in a qstring or a dliteral, process the character only if it is
     // what we are looking for to end the quote.
     if (endQuote !== undefined) {
       if (ch == endQuote && ch == '"') {
@@ -419,29 +421,29 @@ function getHeaderTokens(value, delimite
 
         // If RFC 2047 is enabled, always decode the qstring.
         if (opts.rfc2047)
           text = decodeRFC2047Words(text);
 
         tokenList.push(new Token(text));
         endQuote = undefined;
         tokenStart = undefined;
-      } else if (ch == endQuote && ch == ']') {
+      } else if (ch == endQuote && ch == "]") {
         // Domain literals include their delimiters.
         tokenList.push(new Token(value.slice(tokenStart, i + 1)));
         endQuote = undefined;
         tokenStart = undefined;
       }
       // Avoid any further processing.
       continue;
     }
 
     // If we can match the RFC 2047 encoded-word pattern, we need to decode the
     // entire word or set of words.
-    if (opts.rfc2047 && ch == '=' && i + 1 < value.length && value[i + 1] == '?') {
+    if (opts.rfc2047 && ch == "=" && i + 1 < value.length && value[i + 1] == "?") {
       // RFC 2047 tokens separated only by whitespace are conceptually part of
       // the same output token, so we need to decode them all at once.
       let encodedWordsRE = /([ \t\r\n]*=\?[^?]*\?[BbQq]\?[^?]*\?=)+/;
       let result = encodedWordsRE.exec(value.slice(i));
       if (result !== null) {
         // If we were in the middle of a prior token (i.e., something like
         // foobar=?UTF-8?Q?blah?=), yield the previous segment as a token.
         if (tokenStart !== undefined) {
@@ -450,17 +452,17 @@ function getHeaderTokens(value, delimite
         }
 
         // Find out how much we need to decode...
         let encWordsLen = result[0].length;
         let string = decodeRFC2047Words(value.slice(i, i + encWordsLen),
           "UTF-8");
         // Don't make a new Token variable, since we do not want to unescape the
         // decoded string.
-        tokenList.push({ toString: function() { return string; }});
+        tokenList.push({ toString() { return string; }});
 
         // Skip everything we decoded. The -1 is because we don't want to
         // include the starting character.
         i += encWordsLen - 1;
         continue;
       }
 
       // If we are here, then we failed to match the simple 2047 encoded-word
@@ -491,33 +493,33 @@ function getHeaderTokens(value, delimite
       // apply within comments.
       tokenIsEnding = true;
       isSpecial = true;
     } else if (opts.qstring && ch == '"') {
       // Quoted strings end the last token and start a new one.
       tokenIsEnding = true;
       tokenIsStarting = true;
       endQuote = ch;
-    } else if (opts.dliteral && ch == '[') {
+    } else if (opts.dliteral && ch == "[") {
       // Domain literals end the last token and start a new one.
       tokenIsEnding = true;
       tokenIsStarting = true;
-      endQuote = ']';
-    } else if (opts.comments && ch == '(') {
+      endQuote = "]";
+    } else if (opts.comments && ch == "(") {
       // Comments are nested (oh joy). We only really care for the outer
       // delimiter, though, which also ends the prior token and needs to be
       // output if the consumer requests it.
       commentDepth++;
       if (commentDepth == 1) {
         tokenIsEnding = true;
         isSpecial = true;
       } else {
         tokenIsStarting = true;
       }
-    } else if (opts.comments && ch == ')') {
+    } else if (opts.comments && ch == ")") {
       // Comments are nested (oh joy). We only really care for the outer
       // delimiter, though, which also ends the prior token and needs to be
       // output if the consumer requests it.
       if (commentDepth > 0)
         commentDepth--;
       if (commentDepth == 0) {
         tokenIsEnding = true;
         isSpecial = true;
@@ -554,16 +556,17 @@ function getHeaderTokens(value, delimite
     if (endQuote == '"')
       tokenList.push(new Token(value.slice(tokenStart + 1)));
     else
       tokenList.push(new Token(value.slice(tokenStart)));
   }
 
   return tokenList;
 }
+/* eslint-enable complexity */
 
 /**
  * Convert a header value into UTF-16 strings by attempting to decode as UTF-8
  * or another legacy charset. If the header is valid UTF-8, it will be decoded
  * as UTF-8; if it is not, the fallbackCharset will be attempted instead.
  *
  * @param {String} headerValue       The header (as a binary string) to attempt
  *                                   to convert to UTF-16.
@@ -607,66 +610,66 @@ function convert8BitHeader(headerValue, 
  */
 function decodeRFC2047Words(headerValue) {
   // Unfortunately, many implementations of RFC 2047 encoding are actually wrong
   // in that they split over-long encoded words without regard for whether or
   // not the split point is in the middle of a multibyte character. Therefore,
   // we need to be able to handle these situations gracefully. This is done by
   // using the decoder in streaming mode so long as the next token is another
   // 2047 token with the same charset.
-  let lastCharset = '', currentDecoder = undefined;
+  let lastCharset = "", currentDecoder = undefined;
 
   /**
    * Decode a single RFC 2047 token. This function is inline so that we can
    * easily close over the lastCharset/currentDecoder variables, needed for
    * handling bad RFC 2047 productions properly.
    */
   function decode2047Token(token, isLastToken) {
     let tokenParts = token.split("?");
 
     // If it's obviously not a valid token, return false immediately.
-    if (tokenParts.length != 5 || tokenParts[4] != '=')
+    if (tokenParts.length != 5 || tokenParts[4] != "=")
       return false;
 
     // The charset parameter is defined in RFC 2231 to be charset or
     // charset*language. We only care about the charset here, so ignore any
     // language parameter that gets passed in.
-    let charset = tokenParts[1].split('*', 1)[0];
+    let charset = tokenParts[1].split("*", 1)[0];
     let encoding = tokenParts[2], text = tokenParts[3];
 
     let buffer;
-    if (encoding == 'B' || encoding == 'b') {
+    if (encoding == "B" || encoding == "b") {
       // Decode base64. If there's any non-base64 data, treat the string as
       // an illegal token.
       if (/[^ A-Za-z0-9+\/=]/.exec(text))
         return false;
 
       // Decode the string
       buffer = mimeutils.decode_base64(text, false)[0];
-    } else if (encoding == 'Q' || encoding == 'q') {
+    } else if (encoding == "Q" || encoding == "q") {
       // Q encoding here looks a lot like quoted-printable text. The differences
       // between quoted-printable and this are that quoted-printable allows you
       // to quote newlines (this doesn't), while this replaces spaces with _.
       // We can reuse the decode_qp code here, since newlines are already
       // stripped from the header. There is one edge case that could trigger a
       // false positive, namely when you have a single = or an = followed by
       // whitespace at the end of the string. Such an input string is already
       // malformed to begin with, so stripping the = and following input in that
       // case should not be an important loss.
-      buffer = mimeutils.decode_qp(text.replace(/_/g, ' '), false)[0];
+      buffer = mimeutils.decode_qp(text.replace(/_/g, " "), false)[0];
     } else {
       return false;
     }
 
     // Make the buffer be a typed array for what follows
     let stringBuffer = buffer;
     buffer = mimeutils.stringToTypedArray(buffer);
 
     // If we cannot reuse the last decoder, flush out whatever remains.
-    var output = '';
+    var output = "";
     if (charset != lastCharset && currentDecoder) {
       output += currentDecoder.decode();
       currentDecoder = null;
     }
 
     // Initialize the decoder for this token.
     lastCharset = charset;
     if (!currentDecoder) {
@@ -717,37 +720,36 @@ function decodeRFC2047Words(headerValue)
         components[i] = decoded;
 
         // We're done processing, so continue to the next link.
         continue;
       }
     } else if (/^[ \t\r\n]*$/.exec(components[i])) {
       // Whitespace-only tokens get squashed into nothing, so 2047 tokens will
       // be concatenated together.
-      components[i] = '';
+      components[i] = "";
       continue;
     }
 
     // If there was stuff left over from decoding the last 2047 token, flush it
     // out.
-    lastCharset = '';
+    lastCharset = "";
     if (currentDecoder) {
       components[i] = currentDecoder.decode() + components[i];
       currentDecoder = null;
     }
   }
 
   // After the for loop, we'll have a set of decoded strings. Concatenate them
   // together to make the return value.
-  return components.join('');
+  return components.join("");
 }
 
-///////////////////////////////
-// Structured field decoders //
-///////////////////////////////
+// Structured field decoders
+// -------------------------
 
 /**
  * Extract a list of addresses from a header which matches the RFC 5322
  * address-list production, possibly doing RFC 2047 decoding along the way.
  *
  * The output of this method is an array of elements corresponding to the
  * addresses and the groups in the input header. An address is represented by
  * an object of the form:
@@ -774,17 +776,17 @@ function parseAddressingHeader(header, d
     doRFC2047 = true;
 
   // The final (top-level) results list to append to.
   let results = [];
   // Temporary results
   let addrlist = [];
 
   // Build up all of the values
-  let name = '', groupName = '', localPart = '', address = '', comment = '';
+  let name = "", groupName = "", localPart = "", address = "", comment = "";
   // Indicators of current state
   let inAngle = false, inComment = false, needsSpace = false;
   let preserveSpace = false;
   let commentClosed = false;
 
   // RFC 5322 §3.4 notes that legacy implementations exist which use a simple
   // recipient form where the addr-spec appears without the angle brackets,
   // but includes the name of the recipient in parentheses as a comment
@@ -799,17 +801,17 @@ function parseAddressingHeader(header, d
   // If the display-name is empty while the last comment is not, we assume it's
   // the legacy form above and take the comment content as the display-name.
   //
   // When parsing the address field, we at first do not know whether any
   // strings belong to the display-name (which may include comments) or to the
   // local-part of an addr-spec (where we ignore comments) until we find an
   // '@' or an '<' token. Thus, we collect both variants until the fog lifts,
   // plus the last comment seen.
-  let lastComment = '';
+  let lastComment = "";
 
   /**
    * Add the parsed mailbox object to the address list.
    * If it's in the legacy form above, correct the display-name.
    * Also reset any faked flags.
    * @param {String} displayName   display-name as per RFC 5322
    * @param {String} addrSpec      addr-spec as per RFC 5322
    */
@@ -819,121 +821,121 @@ function parseAddressingHeader(header, d
     if (/[ !()<>\[\]:;@\\,"]/.exec(lp) !== null) {
       addrSpec = '"' + lp.replace(/([\\"])/g, "\\$1") + '"' +
                  addrSpec.substring(addrSpec.lastIndexOf("@"));
     }
 
     // Replace consecutive whitespace in the name with a single whitespace.
     displayName = displayName.replace(/\s\s+/g, " ");
 
-    if (displayName === '' && lastComment !== '') {
+    if (displayName === "" && lastComment !== "") {
       // Take last comment content as the display-name.
-      let offset = lastComment[0] === ' ' ? 2 : 1;
+      let offset = lastComment[0] === " " ? 2 : 1;
       displayName = lastComment.substr(offset, lastComment.length - offset - 1);
     }
-    if (displayName !== '' || addrSpec !== '') {
+    if (displayName !== "" || addrSpec !== "") {
       addrlist.push({name: displayName, email: addrSpec});
     }
     // Clear pending flags and variables.
-    name = localPart = address = lastComment = '';
+    name = localPart = address = lastComment = "";
     inAngle = inComment = needsSpace = false;
   }
 
   // Main parsing loop
   for (let token of getHeaderTokens(header, ":,;<>@",
         {qstring: true, comments: true, dliteral: true, rfc2047: doRFC2047})) {
-    if (token === ':') {
+    if (token === ":") {
       groupName = name;
-      name = '';
-      localPart = '';
+      name = "";
+      localPart = "";
       // If we had prior email address results, commit them to the top-level.
       if (addrlist.length > 0)
         results = results.concat(addrlist);
       addrlist = [];
-    } else if (token === '<') {
+    } else if (token === "<") {
       if (inAngle) {
         // Interpret the address we were parsing as a name.
         if (address.length > 0) {
           name = address;
         }
-        localPart = address = '';
+        localPart = address = "";
       } else {
         inAngle = true;
       }
-    } else if (token === '>') {
+    } else if (token === ">") {
       inAngle = false;
       // Forget addr-spec comments.
-      lastComment = '';
-    } else if (token === '(') {
+      lastComment = "";
+    } else if (token === "(") {
       inComment = true;
       // The needsSpace flag may not always be set even if it should be,
       // e.g. for a comment behind an angle-addr.
       // Also, we need to restore the needsSpace flag if we ignore the comment.
       preserveSpace = needsSpace;
       if (!needsSpace)
-        needsSpace = name !== '' && name.substr(-1) !== ' ';
-      comment = needsSpace ? ' (' : '(';
+        needsSpace = name !== "" && name.substr(-1) !== " ";
+      comment = needsSpace ? " (" : "(";
       commentClosed = false;
-    } else if (token === ')') {
+    } else if (token === ")") {
       inComment = false;
-      comment += ')';
+      comment += ")";
       lastComment = comment;
       // The comment may be part of the name, but not of the local-part.
       // Enforce a space behind the comment only when not ignoring it.
       if (inAngle) {
         needsSpace = preserveSpace;
       } else {
         name += comment;
         needsSpace = true;
       }
       commentClosed = true;
       continue;
-    } else if (token === '@') {
+    } else if (token === "@") {
       // An @ means we see an email address. If we're not within <> brackets,
       // then we just parsed an email address instead of a display name. Empty
       // out the display name for the current production.
       if (!inAngle) {
         address = localPart;
-        name = '';
-        localPart = '';
+        name = "";
+        localPart = "";
         // The remainder of this mailbox is part of an addr-spec.
         inAngle = true;
       }
-      address += '@';
-    } else if (token === ',') {
+      address += "@";
+    } else if (token === ",") {
       // A comma ends the current name. If we have something that's kind of a
       // name, add it to the result list. If we don't, then our input looks like
       // To: , , -> don't bother adding an empty entry.
       addToAddrList(name, address);
-    } else if (token === ';') {
+    } else if (token === ";") {
       // Add pending name to the list
       addToAddrList(name, address);
 
       // If no group name was found, treat the ';' as a ','. In any case, we
       // need to copy the results of addrlist into either a new group object or
       // the main list.
-      if (groupName === '') {
+      if (groupName === "") {
         results = results.concat(addrlist);
       } else {
         results.push({
           name: groupName,
-          group: addrlist
+          group: addrlist,
         });
       }
       // ... and reset every other variable.
       addrlist = [];
-      groupName = '';
+      groupName = "";
     } else {
       // This is either comment content, a quoted-string, or some span of
       // dots and atoms.
 
       // Ignore the needs space if we're a "close" delimiter token.
       let spacedToken = token;
-      if (needsSpace && token.toString()[0] != '.')
-        spacedToken = ' ' + spacedToken;
+      if (needsSpace && token.toString()[0] != ".")
+        spacedToken = " " + spacedToken;
 
       // Which field do we add this data to?
       if (inComment) {
         comment += spacedToken;
       } else if (inAngle) {
         address += spacedToken;
       } else {
         name += spacedToken;
@@ -943,31 +945,31 @@ function parseAddressingHeader(header, d
           commentClosed = false;
         } else {
           localPart += spacedToken;
         }
       }
 
       // We need space for the next token if we aren't some kind of comment or
       // . delimiter.
-      needsSpace = (token.toString().length > 0) && (token.toString()[0] != '.');
+      needsSpace = (token.toString().length > 0) && (token.toString()[0] != ".");
       // The fall-through case after this resets needsSpace to false, and we
       // don't want that!
       continue;
     }
 
     // If we just parsed a delimiter, we don't need any space for the next
     // token.
     needsSpace = false;
   }
 
   // If we're missing the final ';' of a group, assume it was present. Also, add
   // in the details of any email/address that we previously saw.
   addToAddrList(name, address);
-  if (groupName !== '') {
+  if (groupName !== "") {
     results.push({name: groupName, group: addrlist});
     addrlist = [];
   }
 
   // Add the current address list build-up to the list of addresses, and return
   // the whole array to the caller.
   return results.concat(addrlist);
 }
@@ -978,74 +980,75 @@ function parseAddressingHeader(header, d
  *
  * @param {String} headerValue The MIME header value to parse.
  * @param {Boolean} doRFC2047  If true, decode RFC 2047 encoded-words.
  * @param {Boolean} doRFC2231  If true, decode RFC 2231 encoded parameters.
  * @return {Map(String -> String)} A map of parameter names to parameter values.
  *                                 The property preSemi is set to the token that
  *                                 precedes the first semicolon.
  */
+/* eslint-disable complexity */
 function parseParameterHeader(headerValue, doRFC2047, doRFC2231) {
   // The basic syntax of headerValue is token [; token = token-or-qstring]*
   // Copying more or less liberally from nsMIMEHeaderParamImpl:
   // The first token is the text to the first whitespace or semicolon.
   var semi = headerValue.indexOf(";");
+  let start, rest;
   if (semi < 0) {
-    var start = headerValue;
-    var rest = '';
+    start = headerValue;
+    rest = "";
   } else {
-    var start = headerValue.substring(0, semi);
-    var rest = headerValue.substring(semi); // Include the semicolon
+    start = headerValue.substring(0, semi);
+    rest = headerValue.substring(semi); // Include the semicolon
   }
   // Strip start to be <WSP><nowsp><WSP>.
   start = start.trim().split(/[ \t\r\n]/)[0];
 
   // Decode the the parameter tokens.
   let opts = {qstring: true, rfc2047: doRFC2047};
   // Name is the name of the parameter, inName is true iff we don't have a name
   // yet.
-  let name = '', inName = true;
+  let name = "", inName = true;
   // Matches is a list of [name, value] pairs, where we found something that
   // looks like name=value in the input string.
   let matches = [];
   for (let token of getHeaderTokens(rest, ";=", opts)) {
-    if (token === ';') {
+    if (token === ";") {
       // If we didn't find a name yet (we have ... tokenA; tokenB), push the
       // name with an empty token instead.
-      if (name != '' && inName == false)
-        matches.push([name, '']);
-      name = '';
+      if (name != "" && !inName)
+        matches.push([name, ""]);
+      name = "";
       inName = true;
-    } else if (token === '=') {
+    } else if (token === "=") {
       inName = false;
-    } else if (inName && name == '') {
+    } else if (inName && name == "") {
       name = token.toString();
-    } else if (!inName && name != '') {
+    } else if (!inName && name != "") {
       token = token.toString();
       // RFC 2231 doesn't make it clear if %-encoding is supposed to happen
       // within a quoted string, but this is very much required in practice. If
       // it ends with a '*', then the string is an extended-value, which means
       // that its value may be %-encoded.
-      if (doRFC2231 && name.endsWith('*')) {
-        token = token.replace(/%([0-9A-Fa-f]{2})/g,
-          function percent_deencode(match, hexchars) {
-            return String.fromCharCode(parseInt(hexchars, 16));
+      if (doRFC2231 && name.endsWith("*")) {
+        token = token.replace(/%([0-9A-Fa-f]{2})/g, function(match, hexchars) {
+          return String.fromCharCode(parseInt(hexchars, 16));
         });
       }
       matches.push([name, token]);
       // Clear the name, so we ignore anything afterwards.
-      name = '';
+      name = "";
     } else if (inName) {
       // We have ...; tokenA tokenB ... -> ignore both tokens
-      name = ''; // Error recovery, ignore this one
+      name = ""; // Error recovery, ignore this one
     }
   }
   // If we have a leftover ...; tokenA, push the tokenA
-  if (name != '' && inName == false)
-    matches.push([name, '']);
+  if (name != "" && !inName)
+    matches.push([name, ""]);
 
   // Now matches holds the parameters, so clean up for RFC 2231. There are three
   // cases: param=val, param*=us-ascii'en-US'blah, and param*n= variants. The
   // order of preference is to pick the middle, then the last, then the first.
   // Note that we already unpacked %-encoded values.
 
   // simpleValues is just a straight parameter -> value map.
   // charsetValues is the parameter -> value map, although values are stored
@@ -1054,17 +1057,17 @@ function parseParameterHeader(headerValu
   // valid (if we decided we couldn't do anything anymore) and hasCharset (which
   // records if we need to decode the charset parameter or not).
   var simpleValues = new Map(), charsetValues = new Map(),
       continuationValues = new Map();
   for (let pair of matches) {
     let name = pair[0];
     let value = pair[1];
     // Get first index, not last index, so we match param*0*= like param*0=.
-    let star = name.indexOf('*');
+    let star = name.indexOf("*");
     if (star == -1) {
       // This is the case of param=val. Select the first value here, if there
       // are multiple ones.
       if (!simpleValues.has(name))
         simpleValues.set(name, value);
     } else if (star == name.length - 1) {
       // This is the case of param*=us-ascii'en-US'blah.
       name = name.substring(0, star);
@@ -1077,32 +1080,30 @@ function parseParameterHeader(headerValu
       let entry = continuationValues.get(param);
       // Did we previously find this one to be bungled? Then ignore it.
       if (continuationValues.has(param) && !entry.valid)
         continue;
 
       // If we haven't seen it yet, set up entry already. Note that entries are
       // not straight string values but rather [valid, hasCharset, param0, ... ]
       if (!continuationValues.has(param)) {
-        entry = new Array();
+        entry = [];
         entry.valid = true;
         entry.hasCharset = undefined;
         continuationValues.set(param, entry);
       }
 
       // When the string ends in *, we need to charset decoding.
       // Note that the star is only meaningful for the *0*= case.
-      let lastStar = name[name.length - 1] == '*';
+      let lastStar = name[name.length - 1] == "*";
       let number = name.substring(star + 1, name.length - (lastStar ? 1 : 0));
-      if (number == '0')
+      if (number == "0") {
         entry.hasCharset = lastStar;
-
-      // Is the continuation number illegal?
-      else if (number.length == 0 || (number[0] == '0' && number != '0') ||
-          !(/^[0-9]+$/.test(number))) {
+      } else if (number.length == 0 || (number[0] == "0" && number != "0") ||
+          !(/^[0-9]+$/.test(number))) { // Is the continuation number illegal?
         entry.valid = false;
         continue;
       }
       // Normalize to an integer
       number = parseInt(number, 10);
 
       // Is this a repeat? If so, bail.
       if (entry[number] !== undefined) {
@@ -1137,17 +1138,17 @@ function parseParameterHeader(headerValu
       // entry, stop there.
       let valid = true;
       for (var i = 0; valid && i < entry.length; i++)
         if (entry[i] === undefined)
           valid = false;
 
       // Concatenate as many parameters as are valid. If we need to decode thec
       // charset, do so now.
-      let value = entry.slice(0, i).join('');
+      let value = entry.slice(0, i).join("");
       if (entry.hasCharset) {
         try {
           value = decode2231Value(value);
         } catch (e) {
           // Bad charset, don't add anything.
           continue;
         }
       }
@@ -1164,32 +1165,33 @@ function parseParameterHeader(headerValu
       }
     }
   }
 
   // Finally, return the values computed above.
   values.preSemi = start;
   return values;
 }
+/* eslint-enable complexity */
 
 /**
  * Convert a RFC 2231-encoded string parameter into a Unicode version of the
  * string. This assumes that percent-decoding has already been applied.
  *
  * @param {String} value The RFC 2231-encoded string to decode.
  * @return The Unicode version of the string.
  */
 function decode2231Value(value) {
   let quote1 = value.indexOf("'");
   let quote2 = quote1 >= 0 ? value.indexOf("'", quote1 + 1) : -1;
 
   let charset = (quote1 >= 0 ? value.substring(0, quote1) : "");
   // It turns out that the language isn't useful anywhere in our codebase for
   // the present time, so we will safely ignore it.
-  //var language = (quote2 >= 0 ? value.substring(quote1 + 2, quote2) : "");
+  // var language = (quote2 >= 0 ? value.substring(quote1 + 2, quote2) : "");
   value = value.substring(Math.max(quote1, quote2) + 1);
 
   // Convert the value into a typed array for decoding
   let typedarray = mimeutils.stringToTypedArray(value);
 
   // Decode the charset. If the charset isn't found, we throw an error. Try to
   // fallback in that case.
   return new MimeTextDecoder(charset, {fatal: true})
@@ -1206,17 +1208,17 @@ var kKnownTZs = {
   "MST": "-0700", "MDT": "-0600",
   "PST": "-0800", "PDT": "-0700",
   // The following are time zones copied from NSPR's prtime.c
   "AST": "-0400", // Atlantic Standard Time
   "NST": "-0330", // Newfoundland Standard Time
   "BST": "+0100", // British Summer Time
   "MET": "+0100", // Middle Europe Time
   "EET": "+0200", // Eastern Europe Time
-  "JST": "+0900"  // Japan Standard Time
+  "JST": "+0900", // Japan Standard Time
 };
 
 /**
  * Parse a header that contains a date-time definition according to RFC 5322.
  * The result is a JS date object with the same timestamp as the header.
  *
  * The dates returned by this parser cannot be reliably converted back into the
  * original header for two reasons. First, JS date objects cannot retain the
@@ -1240,17 +1242,17 @@ var kKnownTZs = {
 function parseDateHeader(header) {
   let tokens = getHeaderTokens(header, ",:", {}).map(x => x.toString());
   // What does a Date header look like? In practice, most date headers devolve
   // into Date: [dow ,] dom mon year hh:mm:ss tzoff [(abbrev)], with the day of
   // week mostly present and the timezone abbreviation mostly absent.
 
   // First, ignore the day-of-the-week if present. This would be the first two
   // tokens.
-  if (tokens.length > 1 && tokens[1] === ',')
+  if (tokens.length > 1 && tokens[1] === ",")
     tokens = tokens.slice(2);
 
   // If there are too few tokens, the date is obviously invalid.
   if (tokens.length < 8)
     return new Date(NaN);
 
   // Save off the numeric tokens
   let day = parseInt(tokens[0]);
@@ -1278,19 +1280,19 @@ function parseDateHeader(header) {
   // Compute the timezone offset. If it's not in the form ±hhmm, convert it to
   // that form.
   let tzoffset = tokens[8];
   if (tzoffset in kKnownTZs)
     tzoffset = kKnownTZs[tzoffset];
   let decompose = /^([+-])(\d\d)(\d\d)$/.exec(tzoffset);
   // Unknown? Make it +0000
   if (decompose === null)
-    decompose = ['+0000', '+', '00', '00'];
+    decompose = ["+0000", "+", "00", "00"];
   let tzOffsetInMin = parseInt(decompose[2]) * 60 + parseInt(decompose[3]);
-  if (decompose[1] == '-')
+  if (decompose[1] == "-")
     tzOffsetInMin = -tzOffsetInMin;
 
   // How do we make the date at this point? Well, the JS date's constructor
   // builds the time in terms of the local timezone. To account for the offset
   // properly, we need to build in UTC.
   let finalDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds)
     - tzOffsetInMin * 60 * 1000);
 
@@ -1298,23 +1300,22 @@ function parseDateHeader(header) {
   // became undefined. In that case, the date would become invalid, and the
   // indication that it is so is that the underlying number is a NaN. In that
   // scenario, we could build attempt to use JS Date parsing as a last-ditch
   // attempt. But it's not clear that such messages really exist in practice,
   // and the valid formats for Date in ES6 are unspecified.
   return finalDate;
 }
 
-////////////////////////////////////////
-// Structured header decoding support //
-////////////////////////////////////////
+// Structured header decoding support
+// ----------------------------------
 
 // Load the default structured decoders
 var structuredDecoders = new Map();
-var structuredHeaders = require('./structuredHeaders');
+var structuredHeaders = require("./structuredHeaders");
 var preferredSpellings = structuredHeaders.spellings;
 var forbiddenHeaders = new Set();
 for (let pair of structuredHeaders.decoders) {
   addStructuredDecoder(pair[0], pair[1]);
   forbiddenHeaders.add(pair[0].toLowerCase());
 }
 
 /**
@@ -1448,22 +1449,20 @@ headerparser.addStructuredDecoder = addS
 headerparser.convert8BitHeader = convert8BitHeader;
 headerparser.decodeRFC2047Words = decodeRFC2047Words;
 headerparser.getHeaderTokens = getHeaderTokens;
 headerparser.parseAddressingHeader = parseAddressingHeader;
 headerparser.parseDateHeader = parseDateHeader;
 headerparser.parseParameterHeader = parseParameterHeader;
 headerparser.parseStructuredHeader = parseStructuredHeader;
 return Object.freeze(headerparser);
-
 });
 
-////////////////////////////////////////////////////////////////////////////////
-//                        JavaScript Raw MIME Parser                          //
-////////////////////////////////////////////////////////////////////////////////
+// JavaScript Raw MIME Parser
+// --------------------------
 
 /**
  * The parser implemented in this file produces a MIME part tree for a given
  * input message via a streaming callback interface. It does not, by itself,
  * understand concepts like attachments (hence the term 'Raw'); the consumer
  * must translate output into such a format.
  *
  * Charsets:
@@ -1505,22 +1504,22 @@ return Object.freeze(headerparser);
  * - The numbers of multipart/* parts are separated by `.' characters.
  * - The outermost message is referred to by use of the empty string.
  * --> The following segments are not accounted for by IMAP part numbering. <--
  * - The body of any message/rfc822 or similar part is distinguished from the
  *   message part as a whole by appending a `$' character. This does not apply
  *   to the outermost message/rfc822 envelope.
  */
 
-def('mimeparser', function(require) {
+def("mimeparser", function(require) {
 "use strict";
 
-var mimeutils = require('./mimeutils');
-var headerparser = require('./headerparser');
-var spellings = require('./structuredHeaders').spellings;
+var mimeutils = require("./mimeutils");
+var headerparser = require("./headerparser");
+var spellings = require("./structuredHeaders").spellings;
 
 /**
  * An object that represents the structured MIME headers for a message.
  *
  * This class is primarily used as the 'headers' parameter in the startPart
  * callback on handlers for MimeParser. As such, it is designed to do the right
  * thing in common cases as much as possible, with some advanced customization
  * possible for clients that need such flexibility.
@@ -1587,40 +1586,41 @@ function StructuredHeaders(rawHeaderText
   // and don't capture the strings or else split results get nasty.
   let values = rawHeaderText.split(/(?:\r\n|\n)(?![ \t])|\r(?![ \t\n])/);
 
   // Ignore the first "header" if it begins with an mbox delimiter
   if (values.length > 0 && values[0].substring(0, 5) == "From ") {
     values.shift();
     // Elide the mbox delimiter from this._headerData
     if (values.length == 0)
-      rawHeaderText = '';
+      rawHeaderText = "";
     else
       rawHeaderText = rawHeaderText.substring(rawHeaderText.indexOf(values[0]));
   }
 
   let headers = new Map();
   for (let i = 0; i < values.length; i++) {
     // Look for a colon. If it's not present, this header line is malformed,
     // perhaps by premature EOF or similar.
     let colon = values[i].indexOf(":");
+    let header, val;
     if (colon >= 0) {
-      var header = values[i].substring(0, colon);
-      var val = values[i].substring(colon + 1).trim();
+      header = values[i].substring(0, colon);
+      val = values[i].substring(colon + 1).trim();
       if (options.stripcontinuations)
-        val = val.replace(/[\r\n]/g, '');
+        val = val.replace(/[\r\n]/g, "");
     } else {
-      var header = values[i];
-      var val = '';
+      header = values[i];
+      val = "";
     }
 
     // Canonicalize the header in lower-case form.
     header = header.trim().toLowerCase();
     // Omit "empty" headers
-    if (header == '')
+    if (header == "")
       continue;
 
     // We keep an array of values for each header, since a given header may be
     // repeated multiple times.
     if (headers.has(header)) {
       headers.get(header).push(val);
     } else {
       headers.set(header, [val]);
@@ -1632,41 +1632,43 @@ function StructuredHeaders(rawHeaderText
    * @private
    */
   this._rawHeaders = headers;
   /**
    * Cached results of structured header parsing.
    * @private
    */
   this._cachedHeaders = new Map();
-  Object.defineProperty(this, "rawHeaderText",
-    {get: function () { return rawHeaderText; }});
-  Object.defineProperty(this, "size",
-    {get: function () { return this._rawHeaders.size; }});
+  Object.defineProperty(this, "rawHeaderText", {
+    get() { return rawHeaderText; },
+  });
+  Object.defineProperty(this, "size", {
+    get() { return this._rawHeaders.size; },
+  });
   Object.defineProperty(this, "charset", {
-    get: function () { return this._charset; },
-    set: function (value) {
+    get() { return this._charset; },
+    set(value) {
       this._charset = value;
       // Clear the cached headers, since this could change their values
       this._cachedHeaders.clear();
-    }
+    },
   });
 
   // Default to the charset, until the message parser overrides us.
-  if ('charset' in options)
+  if ("charset" in options)
     this._charset = options.charset;
   else
     this._charset = null;
 
   // If we have a Content-Type header, set contentType to return the structured
   // representation. We don't set the value off the bat, since we want to let
   // someone who changes the charset affect the values of 8-bit parameters.
   Object.defineProperty(this, "contentType", {
     configurable: true,
-    get: function () { return this.get('Content-Type'); }
+    get() { return this.get("Content-Type"); },
   });
 }
 
 /**
  * Get a raw header.
  *
  * Raw headers are an array of the header values, listed in order that they were
  * specified in the header block, and without any attempt to convert charsets or
@@ -1680,17 +1682,17 @@ function StructuredHeaders(rawHeaderText
  * the result of calling getRawHeader('X-Header') or getRawHeader('x-header')
  * would be ['Value A', 'V\xC3\xA5lue B'] and the result of
  * getRawHeader('Header2') would be ['Q'].
  *
  * @param headerName {String} The header name for which to get header values.
  * @returns {BinaryString[]} The raw header values (with no charset conversion
  *                           applied).
  */
-StructuredHeaders.prototype.getRawHeader = function (headerName) {
+StructuredHeaders.prototype.getRawHeader = function(headerName) {
   return this._rawHeaders.get(headerName.toLowerCase());
 };
 
 /**
  * Retrieve a structured version of the header.
  *
  * If there is a registered structured decoder (registration happens via
  * headerparser.addStructuredDecoder), then the result of calling that decoder
@@ -1700,113 +1702,113 @@ StructuredHeaders.prototype.getRawHeader
  *
  * A substantial set of headers have pre-registed structured decoders, which, in
  * some cases, are unable to be overridden due to their importance in the
  * functioning of the parser code itself.
  *
  * @param headerName {String} The header name for which to get the header value.
  * @returns The structured header value of the output.
  */
-StructuredHeaders.prototype.get = function (headerName) {
+StructuredHeaders.prototype.get = function(headerName) {
   // Normalize the header name to lower case
   headerName = headerName.toLowerCase();
 
   // First, check the cache for the header value
   if (this._cachedHeaders.has(headerName))
     return this._cachedHeaders.get(headerName);
 
   // Not cached? Grab it [propagating lack of header to caller]
   let headerValue = this._rawHeaders.get(headerName);
   if (headerValue === undefined)
     return headerValue;
 
   // Convert the header to Unicode
   let charset = this.charset;
-  headerValue = headerValue.map(function (value) {
+  headerValue = headerValue.map(function(value) {
     return headerparser.convert8BitHeader(value, charset);
   });
 
   // If there is a structured decoder, use that; otherwise, assume that the
   // header is unstructured and only do RFC 2047 conversion
   let structured;
   try {
     structured = headerparser.parseStructuredHeader(headerName, headerValue);
   } catch (e) {
-    structured = headerValue.map(function (value) {
+    structured = headerValue.map(function(value) {
       return headerparser.decodeRFC2047Words(value);
     });
   }
 
   // Cache the result and return it
   this._cachedHeaders.set(headerName, structured);
   return structured;
 };
 
 /**
  * Check if the message has the given header.
  *
  * @param headerName {String} The header name for which to get the header value.
  * @returns {Boolean} True if the header is present in this header block.
  */
-StructuredHeaders.prototype.has = function (headerName) {
+StructuredHeaders.prototype.has = function(headerName) {
   // Check for presence in the raw headers instead of cached headers.
   return this._rawHeaders.has(headerName.toLowerCase());
 };
 
 // Make a custom iterator. Presently, support for Symbol isn't yet present in
 // SpiderMonkey (or V8 for that matter), so type-pun the name for now.
 var JS_HAS_SYMBOLS = typeof Symbol === "function";
 var ITERATOR_SYMBOL = JS_HAS_SYMBOLS ? Symbol.iterator : "@@iterator";
 
 /**
  * An equivalent of Map.@@iterator, applied to the structured header
  * representations. This is the function that makes
  * for (let [header, value] of headers) work properly.
  */
-StructuredHeaders.prototype[ITERATOR_SYMBOL] = function*() {
+StructuredHeaders.prototype[ITERATOR_SYMBOL] = function* () {
   // Iterate over all the raw headers, and use the cached headers to retrieve
   // them.
   for (let headerName of this.keys()) {
     yield [headerName, this.get(headerName)];
   }
 };
 
 /**
  * An equivalent of Map.forEach, applied to the structured header
  * representations.
  *
  * @param callback {Function(value, name, headers)} The callback to call for
  *                                                  each header/value combo.
  * @param thisarg  {Object}                         The parameter that will be
  *                                                  the |this| of the callback.
  */
-StructuredHeaders.prototype.forEach = function (callback, thisarg) {
+StructuredHeaders.prototype.forEach = function(callback, thisarg) {
   for (let [header, value] of this) {
     callback.call(thisarg, value, header, this);
   }
 };
 
 /**
  * An equivalent of Map.entries, applied to the structured header
  * representations.
  */
 StructuredHeaders.prototype.entries =
   StructuredHeaders.prototype[Symbol.iterator];
 
-/// This function maps lower case names to a pseudo-preferred spelling.
+// This function maps lower case names to a pseudo-preferred spelling.
 function capitalize(headerName) {
-  return headerName.replace(/\b[a-z]/g, function (match) {
+  return headerName.replace(/\b[a-z]/g, function(match) {
     return match.toUpperCase();
   });
 }
 
 /**
  * An equivalent of Map.keys, applied to the structured header representations.
  */
-StructuredHeaders.prototype.keys = function*() {
+StructuredHeaders.prototype.keys = function* () {
   for (let name of this._rawHeaders.keys()) {
     yield spellings.get(name) || capitalize(name);
   }
 };
 
 /**
  * An equivalent of Map.values, applied to the structured header
  * representations.
@@ -1876,74 +1878,74 @@ StructuredHeaders.prototype.values = fun
  *      If true, then the newlines in headers are removed in the returned
  *      header objects.
  *    onerror: <function(thrown error)> [default = nop-function]
  *      An error function that is called if an emitter callback throws an error.
  *      By default, such errors are swallowed by the parser. If you want the
  *      parser itself to throw an error, rethrow it via the onerror function.
  */
 function MimeParser(emitter, options) {
-  /// The actual emitter
+  // The actual emitter
   this._emitter = emitter;
-  /// Options for the parser (those listed here are defaults)
+  // Options for the parser (those listed here are defaults)
   this._options = {
     pruneat: "",
     bodyformat: "nodecode",
     strformat: "binarystring",
     stripcontinuations: true,
     charset: "",
     "force-charset": false,
-    onerror: function swallow(error) {}
+    onerror(error) {},
   };
   // Load the options as a copy here (prevents people from changing on the fly).
   if (options)
     for (var opt in options) {
       this._options[opt] = options[opt];
     }
 
   // Ensure that the error function is in fact a function
   if (typeof this._options.onerror != "function")
-    throw new Exception("onerror callback must be a function");
+    throw new Error("onerror callback must be a function");
 
   // Reset the parser
   this.resetParser();
 }
 
 /**
  * Resets the parser to read a new message. This method need not be called
  * immediately after construction.
  */
-MimeParser.prototype.resetParser = function () {
-  /// Current parser state
+MimeParser.prototype.resetParser = function() {
+  // Current parser state
   this._state = PARSING_HEADERS;
-  /// Input data that needs to be held for buffer conditioning
-  this._holdData = '';
-  /// Complete collection of headers (also used to accumulate _headerData)
-  this._headerData = '';
-  /// Whether or not emitter.startMessage has been called
+  // Input data that needs to be held for buffer conditioning
+  this._holdData = "";
+  // Complete collection of headers (also used to accumulate _headerData)
+  this._headerData = "";
+  // Whether or not emitter.startMessage has been called
   this._triggeredCall = false;
 
-  /// Splitting input
+  // Splitting input
   this._splitRegex = this._handleSplit = undefined;
-  /// Subparsing
+  // Subparsing
   this._subparser = this._subPartNum = undefined;
-  /// Data that has yet to be consumed by _convertData
-  this._savedBuffer = '';
-  /// Convert data
+  // Data that has yet to be consumed by _convertData
+  this._savedBuffer = "";
+  // Convert data
   this._convertData = undefined;
-  /// String decoder
+  // String decoder
   this._decoder = undefined;
 };
 
 /**
  * Deliver a buffer of data to the parser.
  *
  * @param buffer {BinaryString} The raw data to add to the message.
  */
-MimeParser.prototype.deliverData = function (buffer) {
+MimeParser.prototype.deliverData = function(buffer) {
   // In ideal circumstances, we'd like to parse the message all at once. In
   // reality, though, data will be coming to us in packets. To keep the amount
   // of saved state low, we want to make basic guarantees about how packets get
   // delivered. Our basic model is a twist on line-buffering, as the format of
   // MIME and messages make it hard to not do so: we can handle multiple lines
   // at once. To ensure this, we start by conditioning the packet by
   // withholding data to make sure that the internal deliveries have the
   // guarantees. This implies that we need to do the following steps:
@@ -1955,17 +1957,17 @@ MimeParser.prototype.deliverData = funct
   // is being passed to us via a line-buffered input is going to have most of
   // its data being withhold until the next buffer. Since \r is so uncommon of
   // a line ending in modern times, this is acceptable lossage.]
   // 3. Eliminate empty packets.
 
   // Add in previously saved data
   if (this._holdData) {
     buffer = this._holdData + buffer;
-    this._holdData = '';
+    this._holdData = "";
   }
 
   // Condition the input, so that we get the multiline-buffering mentioned in
   // the above comment.
   if (buffer.length > 0) {
     [buffer, this._holdData] = conditionToEndOnCRLF(buffer);
   }
 
@@ -1976,43 +1978,43 @@ MimeParser.prototype.deliverData = funct
   // Signal the beginning, if we haven't done so.
   if (!this._triggeredCall) {
     this._callEmitter("startMessage");
     this._triggeredCall = true;
   }
 
   // Finally, send it the internal parser.
   this._dispatchData("", buffer, true);
-}
+};
 
 /**
  * Ensure that a set of data always ends in an end-of-line character.
  *
  * @param buffer {BinaryString} The data with no guarantees about where it ends.
  * @returns {BinaryString[]} An array of 2 binary strings where the first string
  *                           ends in a newline and the last string contains the
  *                           text in buffer following the first string.
  */
 function conditionToEndOnCRLF(buffer) {
   // Find the last occurrence of '\r' or '\n' to split the string. However, we
   // don't want to consider '\r' if it is the very last character, as we need
   // the next packet to tell if the '\r' is the beginning of a CRLF or a line
   // ending by itself.
-  let lastCR = buffer.lastIndexOf('\r', buffer.length - 2);
-  let lastLF = buffer.lastIndexOf('\n');
+  let lastCR = buffer.lastIndexOf("\r", buffer.length - 2);
+  let lastLF = buffer.lastIndexOf("\n");
   let end = lastLF > lastCR ? lastLF : lastCR;
   return [buffer.substring(0, end + 1), buffer.substring(end + 1)];
-};
+}
 
 /**
  * Tell the parser that all of the data has been delivered.
  *
  * This will flush all of the internal state of the parser.
  */
-MimeParser.prototype.deliverEOF = function () {
+MimeParser.prototype.deliverEOF = function() {
   // Start of input buffered too long? Call start message now.
   if (!this._triggeredCall) {
     this._triggeredCall = true;
     this._callEmitter("startMessage");
   }
   // Force a flush of all of the data.
   if (this._holdData)
     this._dispatchData("", this._holdData, true);
@@ -2025,17 +2027,17 @@ MimeParser.prototype.deliverEOF = functi
  * Calls a method on the emitter safely.
  *
  * This method ensures that errors in the emitter call won't cause the parser
  * to exit with an error, unless the user wants it to.
  *
  * @param funcname {String} The function name to call on the emitter.
  * @param args...           Extra arguments to pass into the emitter callback.
  */
-MimeParser.prototype._callEmitter = function (funcname, ...args) {
+MimeParser.prototype._callEmitter = function(funcname, ...args) {
   if (this._emitter && funcname in this._emitter) {
     if (args.length > 0 && this._willIgnorePart(args[0])) {
       // partNum is always the first argument, so check to make sure that it
       // satisfies our emitter's pruneat requirement.
       return;
     }
     try {
       this._emitter[funcname].apply(this._emitter, args);
@@ -2048,32 +2050,31 @@ MimeParser.prototype._callEmitter = func
 };
 
 /**
  * Helper function to decide if a part's output will never be seen.
  *
  * @param part {String} The number of the part.
  * @returns {Boolean} True if the emitter is not interested in this part.
  */
-MimeParser.prototype._willIgnorePart = function (part) {
-  if (this._options["pruneat"]) {
-    let match = this._options["pruneat"];
+MimeParser.prototype._willIgnorePart = function(part) {
+  if (this._options.pruneat) {
+    let match = this._options.pruneat;
     let start = part.substr(0, match.length);
     // It needs to start with and follow with a new part indicator
     // (i.e., don't let 10 match with 1, but let 1.1 or 1$ do so)
     if (start != match || (match.length < part.length &&
-          "$.".indexOf(part[match.length]) == -1))
+          !("$.".includes(part[match.length]))))
       return true;
   }
   return false;
 };
 
-//////////////////////
-// MIME parser core //
-//////////////////////
+// MIME parser core
+// ----------------
 
 // This MIME parser is a stateful parser; handling of the MIME tree is mostly
 // done by creating new parsers and feeding data to them manually. In parallel
 // to the externally-visible deliverData and deliverEOF, the two methods
 // _dispatchData and _dispatchEOF are the internal counterparts that do the
 // main work of moving data to where it needs to go; helper functions are used
 // to handle translation.
 //
@@ -2130,17 +2131,17 @@ var SEND_TO_SUBPARSER = 4;
  *
  * @param partNum    {String}       The part number being currently parsed.
  * @param buffer     {BinaryString} The text (conditioned as mentioned above) to
  *                                  pass to the parser.
  * @param checkSplit {Boolean}      If true, split the text using _splitRegex.
  *                                  This is set to false internally to handle
  *                                  low-level splitting details.
  */
-MimeParser.prototype._dispatchData = function (partNum, buffer, checkSplit) {
+MimeParser.prototype._dispatchData = function(partNum, buffer, checkSplit) {
   // Are we parsing headers?
   if (this._state == PARSING_HEADERS) {
     this._headerData += buffer;
     // Find the end of the headers--either it's a CRLF at the beginning (in
     // which case we have no headers), or it's a pair of CRLFs.
     let result = /(?:^(?:\r\n|[\r\n]))|(\r\n|[\r\n])\1/.exec(this._headerData);
     if (result != null) {
       // If we found the end of headers, split the data at this point and send
@@ -2177,23 +2178,22 @@ MimeParser.prototype._dispatchData = fun
         this._dispatchData(partNum, buffer, true);
       return;
     }
   }
 
   // Where does the data go?
   if (this._state == SEND_TO_BLACK_HOLE) {
     // Don't send any data when going to the black hole.
-    return;
   } else if (this._state == SEND_TO_EMITTER) {
     // Don't pass body data if the format is to be none
-    let passData = this._options["bodyformat"] != "none";
+    let passData = this._options.bodyformat != "none";
     if (!passData || this._willIgnorePart(partNum))
       return;
-    buffer = this._applyDataConversion(buffer, this._options["strformat"]);
+    buffer = this._applyDataConversion(buffer, this._options.strformat);
     if (buffer.length > 0)
       this._callEmitter("deliverPartData", partNum, buffer);
   } else if (this._state == SEND_TO_SUBPARSER) {
     buffer = this._applyDataConversion(buffer, "binarystring");
     if (buffer.length > 0)
       this._subparser._dispatchData(this._subPartNum, buffer, true);
   }
 };
@@ -2203,17 +2203,17 @@ MimeParser.prototype._dispatchData = fun
  * needs extra data to be saved.
  *
  * @param buf  {BinaryString} The data to be sent to the output.
  * @param type {String}       The type of the data to output. Valid values are
  *                            the same as the strformat option.
  * @returns Coerced and converted data that can be sent to the emitter or
  *          subparser.
  */
-MimeParser.prototype._applyDataConversion = function (buf, type) {
+MimeParser.prototype._applyDataConversion = function(buf, type) {
   // If we need to convert data, do so.
   if (this._convertData) {
     // Prepend leftover data from the last conversion.
     buf = this._savedBuffer + buf;
     [buf, this._savedBuffer] = this._convertData(buf, true);
   }
   return this._coerceData(buf, type, false);
 };
@@ -2222,18 +2222,18 @@ MimeParser.prototype._applyDataConversio
  * Coerce the input buffer into the given output type.
  *
  * @param buffer {BinaryString|Uint8Array} The data to be converted.
  * @param type   {String}                  The type to convert the data to.
  * @param more   {boolean}                 If true, this function will never be
  *                                         called again.
  * @returns {BinaryString|String|Uint8Array} The desired output format.
  */
-/// Coerces the buffer (a string or typedarray) into a given type
-MimeParser.prototype._coerceData = function (buffer, type, more) {
+// Coerces the buffer (a string or typedarray) into a given type
+MimeParser.prototype._coerceData = function(buffer, type, more) {
   if (typeof buffer == "string") {
     // string -> binarystring is a nop
     if (type == "binarystring")
       return buffer;
     // Either we're going to array or unicode. Both people need the array
     var typedarray = mimeutils.stringToTypedArray(buffer);
     // If it's unicode, do the coercion from the array
     // If its typedarray, just return the synthesized one
@@ -2252,123 +2252,123 @@ MimeParser.prototype._coerceData = funct
   throw new Error("Invalid type: " + type);
 };
 
 /**
  * Signal that no more data will be dispatched to this parser.
  *
  * @param partNum {String} The part number being currently parsed.
  */
-MimeParser.prototype._dispatchEOF = function (partNum) {
+MimeParser.prototype._dispatchEOF = function(partNum) {
   if (this._state == PARSING_HEADERS) {
     // Unexpected EOF in headers. Parse them now and call startPart/endPart
     this._headers = this._parseHeaders();
     this._callEmitter("startPart", partNum, this._headers);
   } else if (this._state == SEND_TO_SUBPARSER) {
     // Pass in any lingering data
     if (this._convertData && this._savedBuffer)
       this._subparser._dispatchData(this._subPartNum,
         this._convertData(this._savedBuffer, false)[0], true);
     this._subparser._dispatchEOF(this._subPartNum);
     // Clean up after ourselves
     this._subparser = null;
   } else if (this._convertData && this._savedBuffer) {
     // Convert lingering data
-    let [buffer, ] = this._convertData(this._savedBuffer, false);
-    buffer = this._coerceData(buffer, this._options["strformat"], false);
+    let [buffer] = this._convertData(this._savedBuffer, false);
+    buffer = this._coerceData(buffer, this._options.strformat, false);
     if (buffer.length > 0)
       this._callEmitter("deliverPartData", partNum, buffer);
   }
 
   // We've reached EOF for this part; tell the emitter
   this._callEmitter("endPart", partNum);
 };
 
 /**
  * Produce a dictionary of all headers as if they were unstructured fields.
  *
  * @returns {StructuredHeaders} The structured header objects for the header
  *                              block.
  */
-MimeParser.prototype._parseHeaders = function () {
+MimeParser.prototype._parseHeaders = function() {
   let headers = new StructuredHeaders(this._headerData, this._options);
 
   // Fill the headers.contentType parameter of headers.
-  let contentType = headers.get('Content-Type');
+  let contentType = headers.get("Content-Type");
   if (typeof contentType === "undefined") {
-    contentType = headerparser.parseStructuredHeader('Content-Type',
-      this._defaultContentType || 'text/plain');
+    contentType = headerparser.parseStructuredHeader("Content-Type",
+      this._defaultContentType || "text/plain");
     Object.defineProperty(headers, "contentType", {
-      get: function () { return contentType; }
+      get() { return contentType; },
     });
   } else {
     Object.defineProperty(headers, "contentType", { configurable: false });
   }
 
   // Find the charset for the current part. If the user requested a forced
   // conversion, use that first. Otherwise, check the content-type for one and
   // fallback to a default if it is not present.
-  let charset = '';
+  let charset = "";
   if (this._options["force-charset"])
-    charset = this._options["charset"];
+    charset = this._options.charset;
   else if (contentType.has("charset"))
     charset = contentType.get("charset");
   else
-    charset = this._options["charset"];
+    charset = this._options.charset;
   headers.charset = charset;
 
   // Retain a copy of the charset so that users don't override our decision for
   // decoding body parts.
   this._charset = charset;
   return headers;
 };
 
 /**
  * Initialize the parser state for the body of this message.
  *
  * @param partNum {String} The part number being currently parsed.
  */
-MimeParser.prototype._startBody = function Parser_startBody(partNum) {
+MimeParser.prototype._startBody = function(partNum) {
   let contentType = this._headers.contentType;
 
   // Should the bodyformat be raw, we just want to pass through all data without
   // trying to interpret it.
-  if (this._options["bodyformat"] == "raw" &&
-      partNum == this._options["pruneat"]) {
+  if (this._options.bodyformat == "raw" &&
+      partNum == this._options.pruneat) {
     this._state = SEND_TO_EMITTER;
     return;
   }
 
   // The output depents on the content-type. Basic rule of thumb:
   // 1. Discrete media types (text, video, audio, image, application) are passed
   //    through with no alterations beyond Content-Transfer-Encoding unpacking.
   // 2. Everything with a media type of multipart is treated the same.
   // 3. Any message/* type that acts like a mail message (rfc822, news, global)
   //    is parsed as a header/body pair again. Most of the other message/* types
   //    have similar structures, but they don't have cascading child subparts,
   //    so it's better to pass their entire contents to the emitter and let the
   //    consumer deal with them.
   // 4. For untyped data, there needs to be no Content-Type header. This helps
   //    avoid false positives.
-  if (contentType.mediatype == 'multipart') {
+  if (contentType.mediatype == "multipart") {
     // If there's no boundary type, everything will be part of the prologue of
     // the multipart message, so just feed everything into a black hole.
-    if (!contentType.has('boundary')) {
+    if (!contentType.has("boundary")) {
       this._state = SEND_TO_BLACK_HOLE;
       return;
     }
     // The boundary of a multipart message needs to start with -- and be at the
     // beginning of the line. If -- is after the boundary, it represents the
     // terminator of the multipart. After the line, there may be only whitespace
     // and then the CRLF at the end. Since the CRLFs in here are necessary for
     // distinguishing the parts, they are not included in the subparts, so we
     // need to capture them in the regex as well to prevent them leaking out.
-    this._splitRegex = new RegExp('(\r\n|[\r\n]|^)--' +
-      contentType.get('boundary').replace(/[\\^$*+?.()|{}[\]]/g, '\\$&') +
-      '(--)?[ \t]*(?:\r\n|[\r\n]|$)');
+    this._splitRegex = new RegExp("(\r\n|[\r\n]|^)--" +
+      contentType.get("boundary").replace(/[\\^$*+?.()|{}[\]]/g, "\\$&") +
+      "(--)?[ \t]*(?:\r\n|[\r\n]|$)");
     this._handleSplit = this._whenMultipart;
     this._subparser = new MimeParser(this._emitter, this._options);
     // multipart/digest defaults to message/rfc822 instead of text/plain
     if (contentType.subtype == "digest")
       this._subparser._defaultContentType = "message/rfc822";
 
     // All text before the first boundary and after the closing boundary are
     // supposed to be ignored ("must be ignored", according to RFC 2046 §5.1.1);
@@ -2376,114 +2376,114 @@ MimeParser.prototype._startBody = functi
     // deliverPartData.
     this._state = SEND_TO_BLACK_HOLE;
 
     // Multipart MIME messages stipulate that the final CRLF before the boundary
     // delimiter is not matched. When the packet ends on a CRLF, we don't know
     // if the next text could be the boundary. Therefore, we need to withhold
     // the last line of text to be sure of what's going on. The _convertData is
     // how we do this, even though we're not really converting any data.
-    this._convertData = function mpart_no_leak_crlf(buffer, more) {
+    this._convertData = function(buffer, more) {
       let splitPoint = buffer.length;
       if (more) {
-        if (buffer.charAt(splitPoint - 1) == '\n')
+        if (buffer.charAt(splitPoint - 1) == "\n")
           splitPoint--;
-        if (splitPoint >= 0 && buffer.charAt(splitPoint - 1) == '\r')
+        if (splitPoint >= 0 && buffer.charAt(splitPoint - 1) == "\r")
           splitPoint--;
       }
       let res = conditionToEndOnCRLF(buffer.substring(0, splitPoint));
       let preLF = res[0];
       let rest = res[1];
       return [preLF, rest + buffer.substring(splitPoint)];
-    }
-  } else if (contentType.type == 'message/rfc822' ||
-      contentType.type == 'message/global' ||
-      contentType.type == 'message/news') {
+    };
+  } else if (contentType.type == "message/rfc822" ||
+      contentType.type == "message/global" ||
+      contentType.type == "message/news") {
     // The subpart is just another header/body pair that goes to EOF, so just
     // return the parse from that blob
     this._state = SEND_TO_SUBPARSER;
     this._subPartNum = partNum + "$";
     this._subparser = new MimeParser(this._emitter, this._options);
 
     // So, RFC 6532 happily allows message/global types to have CTE applied.
     // This means that subparts would need to be decoded to determine their
     // contents properly. There seems to be some evidence that message/rfc822
     // that is illegally-encoded exists in the wild, so be lenient and decode
     // for any message/* type that gets here.
-    let cte = this._extractHeader('content-transfer-encoding', '');
+    let cte = this._extractHeader("content-transfer-encoding", "");
     if (cte in ContentDecoders)
       this._convertData = ContentDecoders[cte];
   } else {
     // Okay, we just have to feed the data into the output
     this._state = SEND_TO_EMITTER;
-    if (this._options["bodyformat"] == "decode") {
+    if (this._options.bodyformat == "decode") {
       // If we wish to decode, look it up in one of our decoders.
-      let cte = this._extractHeader('content-transfer-encoding', '');
+      let cte = this._extractHeader("content-transfer-encoding", "");
       if (cte in ContentDecoders)
         this._convertData = ContentDecoders[cte];
     }
   }
 
   // Set up the encoder for charset conversions; only do this for text parts.
   // Other parts are almost certainly binary, so no translation should be
   // applied to them.
-  if (this._options["strformat"] == "unicode" &&
+  if (this._options.strformat == "unicode" &&
       contentType.mediatype == "text") {
     // If the charset is nonempty, initialize the decoder
     if (this._charset !== "") {
       this._decoder = new MimeTextDecoder(this._charset);
     } else {
       // There's no charset we can use for decoding, so pass through as an
       // identity encoder or otherwise this._coerceData will complain.
       this._decoder = {
-        decode: function identity_decoder(buffer) {
+        decode(buffer) {
           return MimeParser.prototype._coerceData(buffer, "binarystring", true);
-        }
+        },
       };
     }
   } else {
     this._decoder = null;
   }
 };
 
 // Internal split handling for multipart messages.
 /**
  * When a multipary boundary is found, handle the process of managing the
  * subparser state. This is meant to be used as a value for this._handleSplit.
  *
  * @param partNum    {String} The part number being currently parsed.
  * @param lastResult {Array}  The result of the regular expression match.
  */
-MimeParser.prototype._whenMultipart = function (partNum, lastResult) {
+MimeParser.prototype._whenMultipart = function(partNum, lastResult) {
   // Fix up the part number (don't do '' -> '.4' and don't do '1' -> '14')
   if (partNum != "") partNum += ".";
   if (!this._subPartNum) {
     // No count? This means that this is the first time we've seen the boundary,
     // so do some initialization for later here.
     this._count = 1;
   } else {
     // If we did not match a CRLF at the beginning of the line, strip CRLF from
     // the saved buffer. We do this in the else block because it is not
     // necessary for the prologue, since that gets ignored anyways.
-    if (this._savedBuffer != '' && lastResult[1] === '') {
+    if (this._savedBuffer != "" && lastResult[1] === "") {
       let useEnd = this._savedBuffer.length - 1;
-      if (this._savedBuffer[useEnd] == '\n')
+      if (this._savedBuffer[useEnd] == "\n")
         useEnd--;
-      if (useEnd >= 0 && this._savedBuffer[useEnd] == '\r')
+      if (useEnd >= 0 && this._savedBuffer[useEnd] == "\r")
         useEnd--;
       this._savedBuffer = this._savedBuffer.substring(0, useEnd + 1);
     }
     // If we have saved data and we matched a CRLF, pass the saved data in.
-    if (this._savedBuffer != '')
+    if (this._savedBuffer != "")
       this._subparser._dispatchData(this._subPartNum, this._savedBuffer, true);
     // We've seen the boundary at least once before, so this must end a subpart.
     // Tell that subpart that it has reached EOF.
     this._subparser._dispatchEOF(this._subPartNum);
   }
-  this._savedBuffer = '';
+  this._savedBuffer = "";
 
   // The regex feeder has a capture on the (--)?, so if its result is present,
   // then we have seen the terminator. Alternatively, the message may have been
   // mangled to exclude the terminator, so also check if EOF has occurred.
   if (lastResult[2] == undefined) {
     this._subparser.resetParser();
     this._state = SEND_TO_SUBPARSER;
     this._subPartNum = partNum + this._count;
@@ -2498,51 +2498,51 @@ MimeParser.prototype._whenMultipart = fu
 /**
  * Return the structured header from the current header block, or a default if
  * it is not present.
  *
  * @param name {String} The header name to get.
  * @param dflt {String} The default MIME value of the header.
  * @returns The structured representation of the header.
  */
-MimeParser.prototype._extractHeader = function (name, dflt) {
+MimeParser.prototype._extractHeader = function(name, dflt) {
   name = name.toLowerCase(); // Normalize name
   return this._headers.has(name) ? this._headers.get(name) :
     headerparser.parseStructuredHeader(name, [dflt]);
 };
 
 var ContentDecoders = {};
-ContentDecoders['quoted-printable'] = mimeutils.decode_qp;
-ContentDecoders['base64'] = mimeutils.decode_base64;
+ContentDecoders["quoted-printable"] = mimeutils.decode_qp;
+ContentDecoders.base64 = mimeutils.decode_base64;
 
 return MimeParser;
 });
-def('headeremitter', function(require) {
+def("headeremitter", function(require) {
 /**
  * This module implements the code for emitting structured representations of
  * MIME headers into their encoded forms. The code here is a companion to,
  * but completely independent of, jsmime.headerparser: the structured
  * representations that are used as input to the functions in this file are the
  * same forms that would be parsed.
  */
 
 "use strict";
 
-var mimeutils = require('./mimeutils');
+var mimeutils = require("./mimeutils");
 
 // Get the default structured encoders and add them to the map
-var structuredHeaders = require('./structuredHeaders');
+var structuredHeaders = require("./structuredHeaders");
 var encoders = new Map();
 var preferredSpellings = structuredHeaders.spellings;
 for (let [header, encoder] of structuredHeaders.encoders) {
   addStructuredEncoder(header, encoder);
 }
 
-/// Clamp a value in the range [min, max], defaulting to def
-/// if the object[property] does not contain the value.
+// Clamp a value in the range [min, max], defaulting to def
+// if the object[property] does not contain the value.
 function clamp(object, property, min, max, def) {
   if (!(property in object))
     return def;
   let value = object[property];
   if (value < min)
     return min;
   if (value > max)
     return max;
@@ -2588,19 +2588,19 @@ function clamp(object, property, min, ma
  *     The maximum number of logical characters that can be included in a line,
  *     not including the final CRLF pair. If this count would be exceeded, then
  *     an error will be thrown and encoding will not be possible.
  *   @param [options.useASCII=true] {Boolean}
  *     If true, then RFC 2047 and RFC 2231 encoding of headers will be performed
  *     as needed to retain headers as ASCII.
  */
 function HeaderEmitter(handler, options) {
-  /// The inferred value of options.useASCII
+  // The inferred value of options.useASCII
   this._useASCII = options.useASCII === undefined ? true : options.useASCII;
-  /// The handler to use.
+  // The handler to use.
   this._handler = handler;
   /**
    * The current line being built; note that we may insert a line break in the
    * middle to keep under the maximum line length.
    *
    * @type String
    * @private
    */
@@ -2622,19 +2622,18 @@ function HeaderEmitter(handler, options)
    *
    * @type Integer
    * @private
    */
   this._preferredBreakpoint = 0;
 }
 
 
-///////////////////////
-// Low-level methods //
-///////////////////////
+// Low-level methods
+// -----------------
 
 // Explanation of the emitter internals:
 // RFC 5322 requires that we wrap our lines, ideally at 78 characters and at
 // least by 998 octets. We can't wrap in arbitrary places, but wherever CFWS is
 // valid... and ideally wherever clients are likely to expect it. In theory, we
 // can break between every token (this is how RFC 822 operates), but, in RFC
 // 5322, many of those breaks are relegated to obsolete productions, mostly
 // because it is common to not properly handle breaks in those locations.
@@ -2671,58 +2670,55 @@ function HeaderEmitter(handler, options)
  * value being emitted is done and therefore we should not send a continuation
  * space. Otherwise, we presume that we're still working, so we will send the
  * continuation space.
  *
  * @private
  * @param [count] {Integer} The number of characters in the current line to
  *   include before wrapping.
  */
-HeaderEmitter.prototype._commitLine = function (count) {
+HeaderEmitter.prototype._commitLine = function(count) {
   let isContinuing = typeof count !== "undefined";
 
   // Split at the point, and lop off whitespace immediately before and after.
+  let firstN, lastN;
   if (isContinuing) {
-    var firstN = this._currentLine.slice(0, count).trimRight();
-    var lastN = this._currentLine.slice(count).trimLeft();
+    firstN = this._currentLine.slice(0, count).trimRight();
+    lastN = this._currentLine.slice(count).trimLeft();
   } else {
-    var firstN = this._currentLine.trimRight();
-    var lastN = "";
+    firstN = this._currentLine.trimRight();
+    lastN = "";
   }
 
-  // How many characters do we need to shift preferred/emergency breakpoints?
-  let shift = this._currentLine.length - lastN.length;
-
   // Send the line plus the final CRLF.
-  this._handler.deliverData(firstN + '\r\n');
+  this._handler.deliverData(firstN + "\r\n");
 
   // Fill the start of the line with the new data.
   this._currentLine = lastN;
 
   // If this is a continuation, add an extra space at the beginning of the line.
   // Adjust the breakpoint shift amount as well.
   if (isContinuing) {
-    this._currentLine = ' ' + this._currentLine;
-    shift++;
+    this._currentLine = " " + this._currentLine;
   }
 
   // We will always break at a point at or after the _preferredBreakpoint, if it
   // exists, so this always gets reset to 0.
   this._preferredBreakpoint = 0;
 };
 
 /**
  * Reserve at least length characters in the current line. If there aren't
  * enough characters, insert a line break.
  *
  * @private
  * @param length {Integer} The number of characters to reserve space for.
  * @return {Boolean} Whether or not there is enough space for length characters.
  */
-HeaderEmitter.prototype._reserveTokenSpace = function (length) {
+HeaderEmitter.prototype._reserveTokenSpace = function(length) {
   // We are not going to do a sanity check that length is within the wrap
   // margins. The rationale is that this lets code simply call this function to
   // force a higher-level line break than normal preferred line breaks (see
   // addAddress for an example use). The text that would be added may need to be
   // itself broken up, so it might not need all the length anyways, but it
   // starts the break already.
 
   // If we have enough space, we don't need to do anything.
@@ -2760,27 +2756,27 @@ HeaderEmitter.prototype._reserveTokenSpa
  * character may be added to the output. If the text could not be added without
  * violating line length restrictions, an error is thrown instead.
  *
  * @protected
  * @param {String}  text          The text to add to the output.
  * @param {Boolean} mayBreakAfter If true, the end of this text is a preferred
  *                                breakpoint.
  */
-HeaderEmitter.prototype.addText = function (text, mayBreakAfter) {
+HeaderEmitter.prototype.addText = function(text, mayBreakAfter) {
   // Try to reserve space for the tokens. If we can't, give up.
   if (!this._reserveTokenSpace(text.length))
     throw new Error("Cannot encode " + text + " due to length.");
 
   this._currentLine += text;
   if (mayBreakAfter) {
     // Make sure that there is an extra space if text could break afterwards.
     this._preferredBreakpoint = this._currentLine.length;
-    if (text[text.length - 1] != ' ') {
-      this._currentLine += ' ';
+    if (text[text.length - 1] != " ") {
+      this._currentLine += " ";
     }
   }
 };
 
 /**
  * Adds a block of text that may need quoting if it contains some character in
  * qchars. If it is already quoted, no quoting will be applied. If the text
  * cannot be added without violating maximum line length, an error is thrown
@@ -2788,26 +2784,26 @@ HeaderEmitter.prototype.addText = functi
  *
  * @protected
  * @param {String}  text          The text to add to the output.
  * @param {String}  qchars        The set of characters that cannot appear
  *                                outside of a quoted string.
  * @param {Boolean} mayBreakAfter If true, the end of this text is a preferred
  *                                breakpoint.
  */
-HeaderEmitter.prototype.addQuotable = function (text, qchars, mayBreakAfter) {
+HeaderEmitter.prototype.addQuotable = function(text, qchars, mayBreakAfter) {
   // No text -> no need to be quoted (prevents strict warning errors).
   if (text.length == 0)
     return;
 
   // Figure out if we need to quote the string. Don't quote a string which
   // already appears to be quoted.
   let needsQuote = false;
 
-  if (!(text[0] == '"' && text[text.length - 1] == '"') && qchars != '') {
+  if (!(text[0] == '"' && text[text.length - 1] == '"') && qchars != "") {
     for (let i = 0; i < text.length; i++) {
       if (qchars.includes(text[i])) {
         needsQuote = true;
         break;
       }
     }
   }
 
@@ -2825,17 +2821,17 @@ HeaderEmitter.prototype.addQuotable = fu
  *
  * @protected
  * @param {String}  text          The text to add to the output.
  * @param {String}  qchars        The set of characters that cannot appear
  *                                outside of a quoted string.
  * @param {Boolean} mayBreakAfter If true, the end of this text is a preferred
  *                                breakpoint.
  */
-HeaderEmitter.prototype.addPhrase = function (text, qchars, mayBreakAfter) {
+HeaderEmitter.prototype.addPhrase = function(text, qchars, mayBreakAfter) {
   // Collapse all whitespace spans into a single whitespace node.
   text = text.replace(/[ \t\r\n]+/g, " ");
 
   // If we have non-ASCII text, encode it using RFC 2047.
   if (this._useASCII && nonAsciiRe.test(text)) {
     this.encodeRFC2047Phrase(text, mayBreakAfter);
     return;
   }
@@ -2859,77 +2855,77 @@ HeaderEmitter.prototype.addPhrase = func
       // because the string was too long. Fall through to the case where we know
       // that the input was too long to begin with.
     }
   }
 
   // If the text is too long, split the quotable string at space boundaries and
   // add each word individually. If we still can't add all those words, there is
   // nothing that we can do.
-  let words = text.split(' ');
+  let words = text.split(" ");
   for (let i = 0; i < words.length; i++) {
     this.addQuotable(words[i], qchars,
       i == words.length - 1 ? mayBreakAfter : true);
   }
 };
 
-/// A regular expression for characters that need to be encoded.
+// A regular expression for characters that need to be encoded.
 var nonAsciiRe = /[^\x20-\x7e]/;
 
-/// The beginnings of RFC 2047 encoded-word
+// The beginnings of RFC 2047 encoded-word
 var b64Prelude = "=?UTF-8?B?", qpPrelude = "=?UTF-8?Q?";
 
-/// A list of ASCII characters forbidden in RFC 2047 encoded-words
+// A list of ASCII characters forbidden in RFC 2047 encoded-words
 var qpForbidden = "\"#$%&'(),.:;<=>?@[\\]^_`{|}~";
 
 var hexString = "0123456789abcdef";
 
 /**
  * Add a block of text as a single RFC 2047 encoded word. This does not try to
  * split words if they are too long.
  *
  * @private
  * @param {Uint8Array} encodedText   The octets to encode.
  * @param {Boolean}    useQP         If true, use quoted-printable; if false,
  *                                   use base64.
  * @param {Boolean}    mayBreakAfter If true, the end of this text is a
  *                                   preferred breakpoint.
  */
-HeaderEmitter.prototype._addRFC2047Word = function (encodedText, useQP,
-    mayBreakAfter) {
+HeaderEmitter.prototype._addRFC2047Word = function(encodedText, useQP, mayBreakAfter) {
   let binaryString = mimeutils.typedArrayToString(encodedText);
+  let token;
   if (useQP) {
-    var token = qpPrelude;
+    token = qpPrelude;
     for (let i = 0; i < encodedText.length; i++) {
       if (encodedText[i] < 0x20 || encodedText[i] >= 0x7F ||
           qpForbidden.includes(binaryString[i])) {
         let ch = encodedText[i];
         token += "=" + hexString[(ch & 0xf0) >> 4] + hexString[ch & 0x0f];
       } else if (binaryString[i] == " ") {
         token += "_";
       } else {
         token += binaryString[i];
       }
     }
     token += "?=";
   } else {
-    var token = b64Prelude + btoa(binaryString) + "?=";
+    token = b64Prelude + btoa(binaryString) + "?=";
   }
   this.addText(token, mayBreakAfter);
 };
 
 /**
  * Add a block of text as potentially several RFC 2047 encoded-word tokens.
  *
  * @protected
  * @param {String}  text          The text to add to the output.
  * @param {Boolean} mayBreakAfter If true, the end of this text is a preferred
  *                                breakpoint.
  */
-HeaderEmitter.prototype.encodeRFC2047Phrase = function (text, mayBreakAfter) {
+HeaderEmitter.prototype.encodeRFC2047Phrase = function(text, mayBreakAfter) {
   // Start by encoding the text into UTF-8 directly.
   let encodedText = new TextEncoder("UTF-8").encode(text);
 
   // Make sure there's enough room for a single token.
   let minLineLen = b64Prelude.length + 10; // Eight base64 characters plus ?=
   if (!this._reserveTokenSpace(minLineLen)) {
     this._commitLine(this._currentLine.length);
   }
@@ -2977,27 +2973,26 @@ HeaderEmitter.prototype.encodeRFC2047Phr
     }
   }
 
   // Add the entire array at this point.
   this._addRFC2047Word(encodedText.subarray(start), b64Len >= qpLen,
     mayBreakAfter);
 };
 
-////////////////////////
-// High-level methods //
-////////////////////////
+// High-level methods
+// ------------------
 
 /**
  * Add the header name, with the colon and trailing space, to the output.
  *
  * @public
  * @param {String} name The name of the header.
  */
-HeaderEmitter.prototype.addHeaderName = function (name) {
+HeaderEmitter.prototype.addHeaderName = function(name) {
   this._currentLine = this._currentLine.trimRight();
   if (this._currentLine.length > 0) {
     this._commitLine();
   }
   this.addText(name + ": ", false);
 };
 
 /**
@@ -3008,17 +3003,17 @@ HeaderEmitter.prototype.addHeaderName = 
  * case put into the name. If no structured encoder can be found, and the input
  * value is a string, then the header is assumed to be unstructured and the
  * value is added as if {@link addUnstructured} were called.
  *
  * @public
  * @param {String} name  The name of the header.
  * @param          value The structured value of the header.
  */
-HeaderEmitter.prototype.addStructuredHeader = function (name, value) {
+HeaderEmitter.prototype.addStructuredHeader = function(name, value) {
   let lowerName = name.toLowerCase();
   if (encoders.has(lowerName)) {
     this.addHeaderName(preferredSpellings.get(lowerName));
     encoders.get(lowerName).call(this, value);
   } else if (typeof value === "string") {
     // Assume it's an unstructured header.
     // All-lower-case-names are ugly, so capitalize first letters.
     name = name.replace(/(^|-)[a-z]/g, function(match) {
@@ -3036,17 +3031,17 @@ HeaderEmitter.prototype.addStructuredHea
  * possibly-empty display name and an email address.
  *
  * @public
  * @param Address addr The address to be added.
  * @param {String} addr.name  The (possibly-empty) name of the address to add.
  * @param {String} addr.email The email of the address to add.
  * @see headerparser.parseAddressingHeader
  */
-HeaderEmitter.prototype.addAddress = function (addr) {
+HeaderEmitter.prototype.addAddress = function(addr) {
   // If we have a display name, add that first.
   if (addr.name) {
     // This is a simple estimate that keeps names on one line if possible.
     this._reserveTokenSpace(addr.name.length + addr.email.length + 3);
     this.addPhrase(addr.name, ",()<>[]:;@.\"", true);
 
     // If we don't have an email address, don't write out the angle brackets for
     // the address. It's already an abnormal situation should this appear, and
@@ -3056,20 +3051,20 @@ HeaderEmitter.prototype.addAddress = fun
 
     this.addText("<", false);
   }
 
   // Find the local-part and domain of the address, since the local-part may
   // need to be quoted separately. Note that the @ goes to the domain, so that
   // the local-part may be quoted if it needs to be.
   let at = addr.email.lastIndexOf("@");
-  let localpart = "", domain = ""
-  if (at == -1)
+  let localpart = "", domain = "";
+  if (at == -1) {
     localpart = addr.email;
-  else {
+  } else {
     localpart = addr.email.slice(0, at);
     domain = addr.email.slice(at);
   }
 
   this.addQuotable(localpart, "()<>[]:;@\\,\" !", false);
   this.addText(domain + (addr.name ? ">" : ""), false);
 };
 
@@ -3083,17 +3078,17 @@ HeaderEmitter.prototype.addAddress = fun
  * @param {(Address|Group)[]} addrs A collection of addresses to add.
  * @param {String}    addrs[i].name    The (possibly-empty) name of the
  *                                     address or the group to add.
  * @param {String}    [addrs[i].email] The email of the address to add.
  * @param {Address[]} [addrs[i].group] A list of email addresses in the group.
  * @see HeaderEmitter.addAddress
  * @see headerparser.parseAddressingHeader
  */
-HeaderEmitter.prototype.addAddresses = function (addresses) {
+HeaderEmitter.prototype.addAddresses = function(addresses) {
   let needsComma = false;
   for (let addr of addresses) {
     // Add a comma if this is not the first element.
     if (needsComma)
       this.addText(", ", true);
     needsComma = true;
 
     if ("email" in addr) {
@@ -3113,17 +3108,17 @@ HeaderEmitter.prototype.addAddresses = f
 /**
  * Add an unstructured header value to the output. This effectively means only
  * inserting line breaks were necessary, and using RFC 2047 encoding where
  * necessary.
  *
  * @public
  * @param {String} text The text to add to the output.
  */
-HeaderEmitter.prototype.addUnstructured = function (text) {
+HeaderEmitter.prototype.addUnstructured = function(text) {
   if (text.length == 0)
     return;
 
   // Unstructured text is basically a phrase that can't be quoted. So, if we
   // have nothing in qchars, nothing should be quoted.
   this.addPhrase(text, "", false);
 };
 
@@ -3145,17 +3140,17 @@ function padTo2Digits(num) {
  *
  * Note that if the date is an invalid date (its internal date parameter is a
  * NaN value), this method throws an error instead of generating an invalid
  * string.
  *
  * @public
  * @param {Date} date The date to be added to the output string.
  */
-HeaderEmitter.prototype.addDate = function (date) {
+HeaderEmitter.prototype.addDate = function(date) {
   // Rather than make a header plastered with NaN values, throw an error on
   // specific invalid dates.
   if (isNaN(date.getTime()))
     throw new Error("Cannot encode an invalid date");
 
   // RFC 5322 says years can't be before 1900. The after 9999 is a bit that
   // derives from the specification saying that years have 4 digits.
   if (date.getFullYear() < 1900 || date.getFullYear() > 9999)
@@ -3176,29 +3171,29 @@ HeaderEmitter.prototype.addDate = functi
   let dayTime = [
     kDaysOfWeek[date.getDay()] + ",",
     date.getDate(),
     mimeutils.kMonthNames[date.getMonth()],
     date.getFullYear(),
     padTo2Digits(date.getHours()) + ":" +
       padTo2Digits(date.getMinutes()) + ":" +
       padTo2Digits(date.getSeconds()),
-    tzOffsetStr
+    tzOffsetStr,
   ].join(" ");
   this.addText(dayTime, false);
 };
 
 /**
  * Signal that the current header has been finished encoding.
  *
  * @public
  * @param {Boolean} deliverEOF If true, signal to the handler that no more text
  *                             will be arriving.
  */
-HeaderEmitter.prototype.finish = function (deliverEOF) {
+HeaderEmitter.prototype.finish = function(deliverEOF) {
   this._commitLine();
   if (deliverEOF)
     this._handler.deliverEOF();
 };
 
 /**
  * Make a streaming header emitter that outputs on the given handler.
  *
@@ -3208,18 +3203,18 @@ HeaderEmitter.prototype.finish = functio
  * @returns {HeaderEmitter} A header emitter constructed with the given options.
  */
 function makeStreamingEmitter(handler, options) {
   return new HeaderEmitter(handler, options);
 }
 
 function StringHandler() {
   this.value = "";
-  this.deliverData = function (str) { this.value += str; };
-  this.deliverEOF = function () { };
+  this.deliverData = function(str) { this.value += str; };
+  this.deliverEOF = function() {};
 }
 
 /**
  * Given a header name and its structured value, output a string containing its
  * MIME-encoded value. The trailing CRLF for the header is included.
  *
  * @param {String} name    The name of the structured header.
  * @param          value   The value of the structured header.
@@ -3249,18 +3244,18 @@ function emitStructuredHeader(name, valu
  *                                             constructor.
  * @returns {String} A MIME-encoded representation of the structured header.
  * @see HeaderEmitter.addStructuredHeader
  */
 function emitStructuredHeaders(headerValues, options) {
   let handler = new StringHandler();
   let emitter = new HeaderEmitter(handler, options);
   for (let instance of headerValues) {
-    instance[1].forEach(function (e) {
-      emitter.addStructuredHeader(instance[0], e)
+    instance[1].forEach(function(e) {
+      emitter.addStructuredHeader(instance[0], e);
     });
   }
   emitter.finish(true);
   return handler.value;
 }
 
 /**
  * Add a custom structured MIME encoder to the set of known encoders. These
@@ -3283,25 +3278,24 @@ function emitStructuredHeaders(headerVal
 function addStructuredEncoder(header, encoder) {
   let lowerName = header.toLowerCase();
   encoders.set(lowerName, encoder);
   if (!preferredSpellings.has(lowerName))
     preferredSpellings.set(lowerName, header);
 }
 
 return Object.freeze({
-  addStructuredEncoder: addStructuredEncoder,
-  emitStructuredHeader: emitStructuredHeader,
-  emitStructuredHeaders: emitStructuredHeaders,
-  makeStreamingEmitter: makeStreamingEmitter
+  addStructuredEncoder,
+  emitStructuredHeader,
+  emitStructuredHeaders,
+  makeStreamingEmitter,
 });
-
 });
 
-def('jsmime', function(require) {
+def("jsmime", function(require) {
   return {
-    MimeParser: require('./mimeparser'),
-    headerparser: require('./headerparser'),
-    headeremitter: require('./headeremitter')
-  }
+    MimeParser: require("./mimeparser"),
+    headerparser: require("./headerparser"),
+    headeremitter: require("./headeremitter"),
+  };
 });
-  return mods['jsmime'];
+  return mods.jsmime;
 }));
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/jsmime/test/.eslintrc.js
@@ -0,0 +1,14 @@
+"use strict";
+
+module.exports = {
+  "extends": "plugin:mozilla/xpcshell-test",
+
+  "rules": {
+    "func-names": "off",
+    "mozilla/import-headjs-globals": "error",
+    "no-unused-vars": ["error", {
+      "args": "none",
+      "vars": "all",
+    }],
+  },
+};
--- a/mailnews/mime/jsmime/test/head_xpcshell_glue.js
+++ b/mailnews/mime/jsmime/test/head_xpcshell_glue.js
@@ -3,63 +3,64 @@
 
 var {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var {Assert} = ChromeUtils.import("resource://testing-common/Assert.jsm");
 var requireCache = new Map();
 
 // Preload an assert module
 var assert = new Assert();
-assert.doesNotThrow = function (block, message) {
-  message = (message ? ' ' + message : '.');
+assert.doesNotThrow = function(block, message) {
+  message = (message ? " " + message : ".");
   try {
     block();
   } catch (e) {
-    this.report(true, e, null, 'Got unwanted exception' + message);
+    this.report(true, e, null, "Got unwanted exception" + message);
   }
 };
 requireCache.set("assert", assert);
 
 // Preload an fs module
 var fs = {
-  readFile: function (filename, options, callback) {
+  readFile(filename, options, callback) {
     if (callback === undefined) {
       callback = options;
       options = {};
     }
 
     // Convert according to encoding. For the moment, we don't support this
     // node.js feature in the shim since we don't need to.
     var translator = (contents => contents);
-    if (options !== undefined && 'encoding' in options) {
-      translator = function () {
+    if (options !== undefined && "encoding" in options) {
+      translator = function() {
         throw new Error("I can't do this!");
       };
     }
 
     Promise.resolve(filename)
            .then(do_get_file)
            .then(file => OS.File.read(file.path))
            .then(translator)
            .then(contents => callback(undefined, contents), callback);
   },
 };
 requireCache.set("fs", fs);
-Components.utils.import("resource:///modules/jsmime.jsm");
+var {jsmime} = ChromeUtils.import("resource:///modules/jsmime.jsm");
 requireCache.set("jsmime", jsmime);
 
 function require(path) {
   if (requireCache.has(path))
     return requireCache.get(path);
 
+  let file;
   if (path.startsWith("test/")) {
     let name = path.substring("test/".length);
-    var file = "resource://testing-common/jsmime/" + name + ".js";
+    file = "resource://testing-common/jsmime/" + name + ".js";
   } else {
-    var file = "resource:///modules/jsmime/" + path + ".js";
+    file = "resource:///modules/jsmime/" + path + ".js";
   }
 
   var globalObject = {
     define: innerDefine.bind(this, path),
   };
   Services.scriptloader.loadSubScript(file, globalObject);
   return requireCache.get(path);
 }
@@ -73,58 +74,57 @@ function innerDefine(moduleName, dfn) {
     return require(path);
   }
   var result = dfn(resolvingRequire);
   requireCache.set(moduleName, result);
 }
 
 var define = innerDefine.bind(this, "xpcshell-test");
 
-///////////////////////////
-// Mocha TDD UI Bindings //
-///////////////////////////
+// Mocha TDD UI Bindings
+// ---------------------
 
 /**
  * A block of tests, from the suite class.
  */
 function MochaSuite(name) {
   this.name = name;
   this.setup = [];
   this.tests = [];
   this.teardown = [];
   this.suites = [];
 }
 
-/// The real code for running a suite of tests, written as async function.
-MochaSuite.prototype._runSuite = async function () {
+// The real code for running a suite of tests, written as async function.
+MochaSuite.prototype._runSuite = async function() {
   info("Running suite " + this.name);
-  for (let setup of this.setup) {
-    await runFunction(setup);
+  for (let setup_ of this.setup) {
+    await runFunction(setup_);
   }
-  for (let test of this.tests) {
-    info("Running test " + test.name);
-    await runFunction(test.test);
+  for (let test_ of this.tests) {
+    info("Running test " + test_.name);
+    await runFunction(test_.test);
   }
-  for (let suite of this.suites) {
-    await suite.runSuite();
+  for (let suite_ of this.suites) {
+    await suite_.runSuite();
   }
   for (let fn of this.teardown) {
     await runFunction(fn);
   }
   info("Finished suite " + this.name);
 };
 
-/// The outer call to run a test suite, which returns a promise of completion.
-MochaSuite.prototype.runSuite = function () {
+// The outer call to run a test suite, which returns a promise of completion.
+MochaSuite.prototype.runSuite = function() {
   return this._runSuite();
 };
 
-/// Run the given function, returning a promise of when the test will complete.
+// Run the given function, returning a promise of when the test will complete.
 function runFunction(fn) {
-  let completed = new Promise(function (resolve, reject) {
+  let completed = new Promise(function(resolve, reject) {
     function onEnd(error) {
       if (error !== undefined)
         reject(error);
       else
         resolve();
     }
     // If the function is expecting an argument, that argument is the callback
     // above. If it's not, then it may be returning a promise.
@@ -134,37 +134,37 @@ function runFunction(fn) {
       // Promise.resolve nicely handles both promises and not-promise values for
       // us.
       resolve(fn());
     }
   });
   return completed;
 }
 
-var currentSuite = new MochaSuite('');
+var currentSuite = new MochaSuite("");
 function suite(name, tests) {
   name = name.toString();
   if (/[\x80-]/.exec(name))
     name = "<unprintable name>";
   let suiteParent = currentSuite;
   currentSuite = new MochaSuite(name);
   suiteParent.suites.push(currentSuite);
   tests();
   currentSuite = suiteParent;
 }
 function test(name, block) {
   name = name.toString();
   if (/[\x80-]/.exec(name))
     name = "<unprintable name>";
-  currentSuite.tests.push({name: name, test: block});
+  currentSuite.tests.push({name, test: block});
 }
 function setup(block) {
-  currentSetup.setup.push(block);
+  currentSuite.setup.push(block);
 }
 function teardown(block) {
-  currentSetup.teardown.push(block);
+  currentSuite.teardown.push(block);
 }
 
-/// The actual binding xpcshell needs to do its work.
+// The actual binding xpcshell needs to do its work.
 function run_test() {
   add_task(() => currentSuite.runSuite());
   run_next_test();
 }
--- a/mailnews/mime/jsmime/test/mock_date.js
+++ b/mailnews/mime/jsmime/test/mock_date.js
@@ -1,72 +1,78 @@
 "use strict";
-define(function (require) {
 
+/* globals define */
+
+define(function(require) {
 /**
  * A class which appears to act like the Date class with customizable timezone
  * offsets.
  * @param {String} iso8601String An ISO-8601 date/time string including a
  *                               timezone offset.
  */
 function MockDate(iso8601String) {
   // Find the timezone offset (Z or ±hhmm) from the ISO-8601 date string, and
   // then convert that into a number of minutes.
   let parse = /\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(Z|[+-]\d{4})/.exec(iso8601String);
   let tzOffsetStr = parse[1];
-  if (tzOffsetStr == 'Z')
+  if (tzOffsetStr == "Z") {
     this._tzOffset = 0;
-  else {
+  } else {
     this._tzOffset = parseInt(tzOffsetStr.substring(1, 3)) * 60 +
       parseInt(tzOffsetStr.substring(3));
-    if (tzOffsetStr[0] == '-')
+    if (tzOffsetStr[0] == "-")
       this._tzOffset = -this._tzOffset;
   }
 
   // To store the offset, we store both the real time in _realDate and a time
   // that is offset by the tzOffset in _shiftedDate. Only the getUTC* methods
   // should be used on these properties, to avoid problems caused by daylight
   // savings time or other timezone effects. This shifting is always legal
   // because ES6 is specified to assume that leap seconds do not exist, so there
   // are always 60 seconds in a minute.
   this._realDate = new Date(iso8601String);
   this._shiftedDate = new Date(this._realDate.getTime() +
     this._tzOffset * 60 * 1000);
 }
 MockDate.prototype = {
-  getTimezoneOffset: function () {
+  getTimezoneOffset() {
     // This property is reversed from how it's defined in ISO 8601, i.e.,
     // UTC +0100 needs to return -60.
     return -this._tzOffset;
   },
-  getTime: function () {
+  getTime() {
     return this._realDate.getTime();
-  }
+  },
 };
 
 // Provide an implementation of Date methods that will be need in JSMime. For
 // the time being, we only need .get* methods.
 for (let name of Object.getOwnPropertyNames(Date.prototype)) {
   // Only copy getters, not setters or x.toString.
-  if (!name.startsWith('get'))
+  if (!name.startsWith("get"))
     continue;
   // No redefining any other names on MockDate.
   if (MockDate.prototype.hasOwnProperty(name))
     continue;
 
-  if (name.includes('UTC')) {
+  if (name.includes("UTC")) {
     // 'name' is already supposed to be freshly bound per newest ES6 drafts, but
     // current ES6 implementations reuse the bindings. Until implementations
     // catch up, use a new let to bind it freshly.
     let boundName = name;
-    Object.defineProperty(MockDate.prototype, name, { value: function(...aArgs) {
-      return Date.prototype[boundName].call(this._realDate, aArgs);
-    }});
+    Object.defineProperty(MockDate.prototype, name, {
+      value(...aArgs) {
+        return Date.prototype[boundName].call(this._realDate, aArgs);
+      },
+    });
   } else {
-    let newName = 'getUTC' + name.substr(3);
-    Object.defineProperty(MockDate.prototype, name, { value: function(...aArgs) {
-      return Date.prototype[newName].call(this._shiftedDate, aArgs);
-    }});
+    let newName = "getUTC" + name.substr(3);
+    Object.defineProperty(MockDate.prototype, name, {
+      value(...aArgs) {
+        return Date.prototype[newName].call(this._shiftedDate, aArgs);
+      },
+    });
   }
 }
 
 return MockDate;
 });
--- a/mailnews/mime/jsmime/test/test_custom_headers.js
+++ b/mailnews/mime/jsmime/test/test_custom_headers.js
@@ -1,69 +1,36 @@
 "use strict";
-define(function (require) {
-
-var assert = require('assert');
-var jsmime = require('jsmime');
-
-function arrayTest(data, fn) {
-  fn.toString = function () {
-    let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
-      return JSON.stringify(data[p]);
-    });
-    return text;
-  };
-  return test(data[0], fn);
-}
+define(function(require) {
+var assert = require("assert");
+var jsmime = require("jsmime");
 
-function testHeader(header, tests) {
-  suite(header, function () {
-    tests.forEach(function (data) {
-      arrayTest(data, function () {
-        array.deepEqual(headerparser.parseStructuredHeader(header,
-          data[0]), data[1]);
-      });
-    });
-  });
-}
-
-function makeCT(media, sub, params) {
-  var object = new Map();
-  object.mediatype = media;
-  object.subtype = sub;
-  object.type = media + "/" + sub;
-  for (let k in params)
-    object.set(k, params[k]);
-  return object;
-}
-suite('Custom decoder support', function () {
+suite("Custom decoder support", function() {
   function customDecoder(values) {
-    let value = values.join('');
+    let value = values.join("");
     return atob(value);
   }
   function customEncoder(value) {
     this.addText(btoa(value), true);
   }
-  test('addStructuredEncoder', function () {
-    assert.equal('X-Base64: String\r\n',
-      jsmime.headeremitter.emitStructuredHeader('X-Base64', 'String', {}));
-    jsmime.headeremitter.addStructuredEncoder('X-Base64', customEncoder);
-    assert.equal('X-Base64: U3RyaW5n\r\n',
-      jsmime.headeremitter.emitStructuredHeader('X-Base64', 'String', {}));
-    assert.equal('X-Base64: U3RyaW5n\r\n',
-      jsmime.headeremitter.emitStructuredHeader('x-bASe64', 'String', {}));
+  test("addStructuredEncoder", function() {
+    assert.equal("X-Base64: String\r\n",
+      jsmime.headeremitter.emitStructuredHeader("X-Base64", "String", {}));
+    jsmime.headeremitter.addStructuredEncoder("X-Base64", customEncoder);
+    assert.equal("X-Base64: U3RyaW5n\r\n",
+      jsmime.headeremitter.emitStructuredHeader("X-Base64", "String", {}));
+    assert.equal("X-Base64: U3RyaW5n\r\n",
+      jsmime.headeremitter.emitStructuredHeader("x-bASe64", "String", {}));
   });
-  test('addStructuredDecoder', function () {
-    assert.throws(function () {
-      jsmime.headerparser.parseStructuredHeader('X-Base64', 'U3RyaW5n');
+  test("addStructuredDecoder", function() {
+    assert.throws(function() {
+      jsmime.headerparser.parseStructuredHeader("X-Base64", "U3RyaW5n");
     }, /Unknown structured header/);
-    jsmime.headerparser.addStructuredDecoder('X-Base64', customDecoder);
-    assert.equal('String',
-      jsmime.headerparser.parseStructuredHeader('X-Base64', 'U3RyaW5n'));
-    assert.throws(function () {
-      jsmime.headerparser.addStructuredDecoder('To', customDecoder);
+    jsmime.headerparser.addStructuredDecoder("X-Base64", customDecoder);
+    assert.equal("String",
+      jsmime.headerparser.parseStructuredHeader("X-Base64", "U3RyaW5n"));
+    assert.throws(function() {
+      jsmime.headerparser.addStructuredDecoder("To", customDecoder);
     }, /Cannot override header/);
   });
 });
-
 });
 
--- a/mailnews/mime/jsmime/test/test_header.js
+++ b/mailnews/mime/jsmime/test/test_header.js
@@ -1,53 +1,52 @@
 "use strict";
 define(function(require) {
-
-var headerparser = require('jsmime').headerparser;
-var assert = require('assert');
+var headerparser = require("jsmime").headerparser;
+var assert = require("assert");
 
 function arrayTest(data, fn) {
-  fn.toString = function () {
+  fn.toString = function() {
     let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
+    text = text.replace(/data\[([0-9]*)\]/g, function(m, p) {
       return JSON.stringify(data[p]);
     });
     return text;
   };
   return test(data[0], fn);
 }
-suite('headerparser', function () {
-  suite('parseParameterHeader', function () {
+suite("headerparser", function() {
+  suite("parseParameterHeader", function() {
     let header_tests = [
-      ['multipart/related', ["multipart/related", {}]],
+      ["multipart/related", ["multipart/related", {}]],
       ["a ; b=v", ["a", {"b": "v"}]],
       ["a ; b='v'", ["a", {"b": "'v'"}]],
       ['a; b = "v"', ["a", {"b": "v"}]],
       ["a;b=1;b=2", ["a", {"b": "1"}]],
       ["a;b=2;b=1", ["a", {"b": "2"}]],
       ['a;b="a;b"', ["a", {"b": "a;b"}]],
       ['a;b="\\\\"', ["a", {"b": "\\"}]],
       ['a;b="a\\b\\c"', ["a", {"b": "abc"}]],
-      ['a;b=1;c=2', ["a", {"b": "1", "c": "2"}]],
+      ["a;b=1;c=2", ["a", {"b": "1", "c": "2"}]],
       ['a;b="a\\', ["a", {"b": "a"}]],
-      ['a;b', ["a", {}]],
-      ['a;b=";";c=d', ["a", {"b": ';', 'c': "d"}]],
+      ["a;b", ["a", {}]],
+      ['a;b=";";c=d', ["a", {"b": ";", "c": "d"}]],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let testMap = new Map();
         for (let key in data[1][1])
           testMap.set(key, data[1][1][key]);
         testMap.preSemi = data[1][0];
         assert.deepEqual(headerparser.parseParameterHeader(data[0], false, false),
           testMap);
       });
     });
   });
-  suite('parseParameterHeader (2231/2047 support)', function () {
+  suite("parseParameterHeader (2231/2047 support)", function() {
     let header_tests = [
       // Copied from test_MIME_params.js and adapted
       ["attachment;", ["attachment", {}]],
       ["attachment; filename=basic", ["attachment", {filename: "basic"}]],
       ["attachment; filename=\"\\\"\"", ["attachment", {filename: '"'}]],
       ["attachment; filename=\"\\x\"", ["attachment", {filename: "x"}]],
       ["attachment; filename=\"\"", ["attachment", {filename: ""}]],
       ["attachment; filename=", ["attachment", {filename: ""}]],
@@ -173,28 +172,28 @@ suite('headerparser', function () {
         ["attachment", {extension: "bla"}]],
       ["attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=",
         ["attachment", {filename: "foo-\u00e4.html"}]],
       ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"",
         ["attachment", {filename: "foo-\u00e4.html"}]],
       ["attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"; filename*=UTF" +
         "-8''5987", ["attachment", {filename: "5987"}]],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let testMap = new Map();
         for (let key in data[1][1])
           testMap.set(key, data[1][1][key]);
         testMap.preSemi = data[1][0];
         assert.deepEqual(headerparser.parseParameterHeader(data[0], true, true),
           testMap);
       });
     });
   });
-  suite('parseAddressingHeader', function () {
+  suite("parseAddressingHeader", function() {
     let header_tests = [
       ["", []],
       ["Joe Schmoe <jschmoe@invalid.invalid>",
         [{name: "Joe Schmoe", email: "jschmoe@invalid.invalid"}]],
       ["user@tinderbox.invalid",
         [{name: "", email: "user@tinderbox.invalid"}]],
       ["Hello Kitty <a@b.c>, No Kitty <b@b.c>",
         [{name: "Hello Kitty", email: "a@b.c"},
@@ -235,17 +234,17 @@ suite('headerparser', function () {
          [{name: "Joe Q. Public", email: "john.q.public@example.com"},
           {name: "Test", email: "\"abc!x.yz\"@foo.invalid"},
           {name: "Test", email: "test@[xyz!]"},
           {name: "Giant; \"Big\" Box", email: "sysservices@example.net"}]],
       ["Unfortunate breaking < so . many . spaces @ here . invalid >",
         [{name: "Unfortunate breaking", email: "so.many.spaces@here.invalid"}]],
       ["so . many . spaces @ here . invalid",
         [{name: "", email: "so.many.spaces@here.invalid"}]],
-      ["abc@foo.invalid", [{name:"", email: "abc@foo.invalid"}]],
+      ["abc@foo.invalid", [{name: "", email: "abc@foo.invalid"}]],
       ["foo <ghj@foo.invalid>", [{name: "foo", email: "ghj@foo.invalid"}]],
       ["abc@foo.invalid, foo <ghj@foo.invalid>",
         [{name: "", email: "abc@foo.invalid"},
          {name: "foo", email: "ghj@foo.invalid"}]],
       ["foo bar <foo@bar.invalid>",
         [{name: "foo bar", email: "foo@bar.invalid"}]],
       ["foo bar <foo@bar.invalid>, abc@foo.invalid, foo <ghj@foo.invalid>",
         [{name: "foo bar", email: "foo@bar.invalid"},
@@ -277,24 +276,24 @@ suite('headerparser', function () {
       ['"foo bar" <me@foo.invalid>, "bar foo" <me2@foo.invalid>',
         [{name: "foo bar", email: "me@foo.invalid"},
          {name: "bar foo", email: "me2@foo.invalid"}]],
       ["A Group:Ed Jones <c@a.invalid>,joe@where.invalid,John <jdoe@one.invalid>;",
         [{name: "A Group", group: [
           {name: "Ed Jones", email: "c@a.invalid"},
           {name: "", email: "joe@where.invalid"},
           {name: "John", email: "jdoe@one.invalid"}]}]],
-      ['mygroup:;, empty:;, foo@foo.invalid, othergroup:bar@foo.invalid, bar2' +
-        '@foo.invalid;,       y@y.invalid, empty:;',
+      ["mygroup:;, empty:;, foo@foo.invalid, othergroup:bar@foo.invalid, bar2" +
+        "@foo.invalid;,       y@y.invalid, empty:;",
         [{name: "mygroup", group: []},
          {name: "empty", group: []},
          {name: "", email: "foo@foo.invalid"},
          {name: "othergroup", group: [
            {name: "", email: "bar@foo.invalid"},
-           {name: "", email: "bar2@foo.invalid"}
+           {name: "", email: "bar2@foo.invalid"},
          ]},
          {name: "", email: "y@y.invalid"},
          {name: "empty", group: []}]],
       ["Undisclosed recipients:;;;;;;;;;;;;;;;;,,,,,,,,,,,,,,,,",
         [{name: "Undisclosed recipients", group: []}]],
       ["a@xxx.invalid; b@xxx.invalid",
         [{name: "", email: "a@xxx.invalid"},
          {name: "", email: "b@xxx.invalid"}]],
@@ -308,36 +307,36 @@ suite('headerparser', function () {
         [{name: "A", email: "a@xxx.invalid"},
          {name: "B", email: "b@xxx.invalid"}]],
       ["A (this: is, a comment;) <a.invalid>; g:   (this: is, <a> comment;) C" +
         "<c.invalid>, d.invalid;",
         [{name: "A (this: is, a comment;)", email: "a.invalid"},
          {name: "g", group: [
            {name: "(this: is, <a> comment;) C", email: "c.invalid"},
            {name: "d.invalid", email: ""}]}]],
-      ['Mary Smith <mary@x.invalid>, extra:;, group:jdoe@example.invalid; Who' +
+      ["Mary Smith <mary@x.invalid>, extra:;, group:jdoe@example.invalid; Who" +
         '? <one@y.invalid>; <boss@nil.invalid>, "Giant; \\"Big\\" Box" <sysse' +
-        'rvices@example.invalid>,         ',
+        "rvices@example.invalid>,         ",
         [{name: "Mary Smith", email: "mary@x.invalid"},
          {name: "extra", group: []},
          {name: "group", group: [{name: "", email: "jdoe@example.invalid"}]},
          {name: "Who?", email: "one@y.invalid"},
          {name: "", email: "boss@nil.invalid"},
          {name: "Giant; \"Big\" Box", email: "sysservices@example.invalid"}]],
       ["Undisclosed recipients: a@foo.invalid ;;extra:;",
         [{name: "Undisclosed recipients", group: [
           {name: "", email: "a@foo.invalid"}]},
          {name: "extra", group: []}]],
       ["Undisclosed recipients:;;extra:a@foo.invalid;",
         [{name: "Undisclosed recipients", group: []},
          {name: "extra", group: [{name: "", email: "a@foo.invalid"}]}]],
       ["a < <a@b.c>", [{name: "a", email: "a@b.c"}]],
       ["Name <incomplete@email", [{name: "Name", email: "incomplete@email"}]],
       ["Name <space here@email.invalid>",
-        [{name: 'Name', email: '"space here"@email.invalid'}]],
+        [{name: "Name", email: '"space here"@email.invalid'}]],
       ["Name <not an email>", [{name: "Name", email: "not an email"}]],
       ["=?UTF-8?Q?Simple?= <a@b.c>",
         [{name: "=?UTF-8?Q?Simple?=", email: "a@b.c"}]],
       ["No email address", [{name: "No email address", email: ""}]],
       // Thought we were parsing an address, but it was a name.
       ["name@example.com <receiver@example.com>",
         [{name: "name@example.com", email: "receiver@example.com"}]],
       ["name@huhu.com <receiver@example.com>",
@@ -360,24 +359,24 @@ suite('headerparser', function () {
         [{name: "(c1) n (c2) (c9(c10)c11) (c12)", email: "a@b.d"}]],
       ["<(c3)a(c4)@(c5)b(c6).(c7)d(c8)> (c9(c10)c11)(c12)",
         [{name: "(c9(c10)c11) (c12)", email: "a@b.d"}]],
       ["(c3)a(c4)@(c5)b(c6).(c7)d(c8)(c9(c10)c11)(c12)", [{name: "c12", email: "a@b.d"}]],
       // Collapse extraneous whitespace.
       ["Friend \"<friend@huhu.com>\"                                \t <ws@example.com>",
         [{name: "Friend <friend@huhu.com>", email: "ws@example.com"}]],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.deepEqual(headerparser.parseAddressingHeader(data[0], false),
           data[1]);
       });
     });
   });
-  suite('parseAddressingHeader (RFC 2047 support)', function () {
+  suite("parseAddressingHeader (RFC 2047 support)", function() {
     let header_tests = [
       ["Simple <a@b.c>", [{name: "Simple", email: "a@b.c"}]],
       ["=?UTF-8?Q?Simple?= <a@b.c>", [{name: "Simple", email: "a@b.c"}]],
       ["=?UTF-8?Q?=3C@b.c?= <a@b.c>", [{name: "<@b.c", email: "a@b.c"}]],
 
       // RFC 2047 tokens should not interfere with lexical processing
       ["=?UTF-8?Q?a@b.c,?= <b@b.c>", [{name: "a@b.c,", email: "b@b.c"}]],
       ["=?UTF-8?Q?a@b.c=2C?= <b@b.c>", [{name: "a@b.c,", email: "b@b.c"}]],
@@ -392,45 +391,45 @@ suite('headerparser', function () {
       ["=?ISO-8859-1?Q?Joe_L=F6we?= <jl3@b.c> (c2)", [{name: "Joe Löwe (c2)", email: "jl3@b.c"}]],
       ["(=?ISO-8859-1?Q?Joe_L=F6we?=) <jl3@b.c> (c2)", [{name: "(Joe Löwe) (c2)", email: "jl3@b.c"}]],
       // Bug 1141446: Malformed From addresses with erroneous quotes,
       // note: acute accents: a \u00E1, e \u00E9, i \u00ED, o \u00F3, u \u00FA.
       ["\"=?UTF-8?Q?Jazzy_Fern=C3=A1ndez_Nunoz?= jazzy.f.nunoz@example.com " +
         "[BCN-FC]\" <Barcelona-Freecycle-noreply@yahoogroups.com>",
         [{name: "Jazzy Fern\u00E1ndez Nunoz jazzy.f.nunoz@example.com [BCN-FC]",
           email: "Barcelona-Freecycle-noreply@yahoogroups.com"}]],
-      ["\"=?UTF-8?B?TWlyaWFtIEJlcm5hYsOpIFBlcmVsbMOz?= miriam@example.com "+
+      ["\"=?UTF-8?B?TWlyaWFtIEJlcm5hYsOpIFBlcmVsbMOz?= miriam@example.com " +
         "[BCN-FC]\" <Barcelona-Freecycle-noreply@yahoogroups.com>",
         [{name: "Miriam Bernab\u00E9 Perell\u00F3 miriam@example.com [BCN-FC]",
           email: "Barcelona-Freecycle-noreply@yahoogroups.com"}]],
-      ["\"=?iso-8859-1?Q?First_Mar=EDa_Furi=F3_Gancho?= mail@yahoo.es "+
+      ["\"=?iso-8859-1?Q?First_Mar=EDa_Furi=F3_Gancho?= mail@yahoo.es " +
         "[BCN-FC]\" <Barcelona-Freecycle-noreply@yahoogroups.com>",
         [{name: "First Mar\u00EDa Furi\u00F3 Gancho mail@yahoo.es [BCN-FC]",
           email: "Barcelona-Freecycle-noreply@yahoogroups.com"}]],
-      ["\"=?iso-8859-1?B?U29maWEgQ2FzdGVsbPMgUm9tZXJv?= sonia@example.com "+
+      ["\"=?iso-8859-1?B?U29maWEgQ2FzdGVsbPMgUm9tZXJv?= sonia@example.com " +
         "[BCN-FC]\" <Barcelona-Freecycle-noreply@yahoogroups.com>",
         [{name: "Sofia Castell\u00F3 Romero sonia@example.com [BCN-FC]",
           email: "Barcelona-Freecycle-noreply@yahoogroups.com"}]],
       ["=?iso-8859-1?Q?Klaus_Eisschl=E4ger_=28k=2Eeisschlaeger=40t-onli?=" +
         "=?iso-8859-1?Q?ne=2Ede=29?= <k.eisschlaeger@t-online.de>",
         [{name: "Klaus Eisschläger (k.eisschlaeger@t-online.de)",
           email: "k.eisschlaeger@t-online.de"}]],
       ["\"=?UTF-8?Q?=22Claudia_R=C3=B6hschicht=22?= Claudia_Roehschicht@web.de [freecycle-berlin]\" " +
         "<freecycle-berlin-noreply@yahoogroups.de>",
         [{name: "\"Claudia Röhschicht\" Claudia_Roehschicht@web.de [freecycle-berlin]",
           email: "freecycle-berlin-noreply@yahoogroups.de"}]],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.deepEqual(headerparser.parseAddressingHeader(data[0], true),
           data[1]);
       });
     });
   });
-  suite('parseDateHeader', function () {
+  suite("parseDateHeader", function() {
     let header_tests = [
       // Some basic tests, derived from searching for Date headers in a mailing
       // list archive.
       ["Thu, 06 Sep 2012 08:08:21 -0700", "2012-09-06T08:08:21-0700"],
       ["Thu, 6 Sep 2012 14:49:05 -0400", "2012-09-06T14:49:05-0400"],
       ["Fri, 07 Sep 2012 07:30:11 -0700 (PDT)", "2012-09-07T07:30:11-0700"],
       ["9 Sep 2012 21:03:59 -0000", "2012-09-09T21:03:59Z"],
       ["Sun, 09 Sep 2012 19:10:59 -0400", "2012-09-09T19:10:59-0400"],
@@ -506,27 +505,27 @@ suite('headerparser', function () {
       ["Lun, 01 Apr 2014 15:04:13 -0500", "2014-04-01T15:04:13-0500"],
       ["Mar, 02 Apr 2014 15:04:13 -0500", "2014-04-02T15:04:13-0500"],
       ["Mar, 02 April 2014 15:04:13 -0500", "2014-04-02T15:04:13-0500"],
       ["Mar, 02 Avr 2014 15:04:13 -0500", NaN],
       ["Tue, 02 A 2014 15:04:13 -0500", NaN],
 
 
       // A truly invalid date
-      ["Coincident with the rapture", NaN]
+      ["Coincident with the rapture", NaN],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.equal(headerparser.parseDateHeader(data[0]).toString(),
           new Date(data[1]).toString());
       });
     });
   });
 
-  suite('decodeRFC2047Words', function () {
+  suite("decodeRFC2047Words", function() {
     let header_tests = [
       // Some basic sanity tests for the test process
       ["Test", "Test"],
       ["Test 2", "Test 2"],
       ["Basic  words", "Basic  words"],
       ["Not a =? word", "Not a =? word"],
 
       // Simple 2047 decodings
@@ -563,17 +562,17 @@ suite('headerparser', function () {
       ["=?UTF-8?B?8J+SqQ==?=", "\ud83d\udca9"],
       // The goal for the next one is to be a non-BMP in a non-full-Unicode
       // charset. The only category where this exists is a small set of
       // characters in Big5, which were previously mapped to a PUA in an older
       // version but then reassigned to Plane 1. However, Big5 is really a set
       // of slightly different, slightly incompatible charsets.
       // TODO: This requires future investigation. Bug 912470 discusses the
       // changes to Big5 proposed within Mozilla.
-      //["=?Big5?Q?=87E?=", "\ud85c\ude67"],
+      // ["=?Big5?Q?=87E?=", "\ud85c\ude67"],
       ["=?GB18030?B?lDnaMw==?=", "\ud83d\udca9"],
 
       // How to handle breaks in multi-byte encoding
       ["=?UTF-8?Q?=f0=9f?= =?UTF-8?Q?=92=a9?=", "\ud83d\udca9"],
       ["=?UTF-8?B?8J+S?= =?UTF-8?B?qQ==?=", "\ud83d\udca9"],
       ["=?UTF-8?B?8J+S?= =?UTF-8?Q?=a9?=", "\ud83d\udca9"],
       ["=?UTF-8?B?8J+S?= =?ISO-8859-1?B?qQ==?=", "\ufffd\u00a9"],
       ["=?UTF-8?Q?=f0?= =?UTF-8?Q?ab?=", "\ufffdab"],
@@ -603,24 +602,24 @@ suite('headerparser', function () {
         "==?=\n =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
         "\u2200  \u2201  \u2202  \u2203  \u2204  \u2205  \u2206  \u2207  " +
         "\u2208  \u2209  \u220a  \u220b  \u220c  \u220d  \u220e  \u220f"],
       ["=?UTF-8?b?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA" +
         "==?=\n =?UTF-8?b?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
         "\u2200  \u2201  \u2202  \u2203  \u2204  \u2205  \u2206  \u2207  " +
         "\u2208  \u2209  \u220a  \u220b  \u220c  \u220d  \u220e  \u220f"],
       ["=?utf-8?Q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n" +
-       " =?utf-8?Q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n"+
-       " =?utf-8?Q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n"+
+       " =?utf-8?Q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n" +
+       " =?utf-8?Q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n" +
        " =?utf-8?Q?=E2=88=8F?=",
         "\u2200  \u2201  \u2202  \u2203  \u2204  \u2205  \u2206  \u2207  " +
         "\u2208  \u2209  \u220a  \u220b  \u220c  \u220d  \u220e  \u220f"],
       ["=?utf-8?q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n" +
-       " =?utf-8?q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n"+
-       " =?utf-8?q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n"+
+       " =?utf-8?q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n" +
+       " =?utf-8?q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n" +
        " =?utf-8?q?=E2=88=8F?=",
         "\u2200  \u2201  \u2202  \u2203  \u2204  \u2205  \u2206  \u2207  " +
         "\u2208  \u2209  \u220a  \u220b  \u220c  \u220d  \u220e  \u220f"],
       ["=?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA=" +
         "==?=\n =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
         "\u2200  \u2201  \u2202  \u2203  \u2204  \u2205  \u2206  \u2207  " +
         "\u2208  \u2209  \u220a  \u220b  \u220c  \u220d  \u220e  \u220f"],
 
@@ -661,23 +660,23 @@ suite('headerparser', function () {
       ["=?us-ascii?B?VGVzdA====?=", "Test"],
       ["=?us-ascii?B?VGVzdA=====?=", "Test"],
       ["=?us-ascii?B?VGVzdA======?=", "Test"],
       ["=?us-ascii?B?VGVzdA========?=", "Test"],
       ["=?us-ascii?B?VGVzdA=========?=", "Test"],
       ["=?us-ascii?B?VGVzdA==========?=", "Test"],
       ["=?us-ascii?B?VGVzdA===========?=", "Test"],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.deepEqual(headerparser.decodeRFC2047Words(data[0]), data[1]);
       });
     });
   });
-  suite('8-bit header processing', function () {
+  suite("8-bit header processing", function() {
     let header_tests = [
       // Non-ASCII header values
       ["oxyg\xc3\xa8ne", "oxyg\u00e8ne", "UTF-8"],
       ["oxyg\xc3\xa8ne", "oxyg\u00e8ne", "ISO-8859-1"], // UTF-8 overrides
       ["oxyg\xc3\xa8ne", "oxyg\u00e8ne"], // default to UTF-8 if no charset
       ["oxyg\xe8ne", "oxyg\ufffdne", "UTF-8"],
       ["oxyg\xe8ne", "oxyg\u00e8ne", "ISO-8859-1"],
       ["\xc3\xa8\xe8", "\u00e8\ufffd", "UTF-8"],
@@ -690,18 +689,17 @@ suite('headerparser', function () {
       ["\xe8S!0", "\ufffdS!0", "utf-32"],
 
       // Don't combine encoded-word and header charset decoding
       ["=?UTF-8?Q?=c3?= \xa8", "\ufffd \ufffd", "UTF-8"],
       ["=?UTF-8?Q?=c3?= \xa8", "\ufffd \u00a8", "ISO-8859-1"],
       ["\xc3 =?UTF-8?Q?=a8?=", "\ufffd \ufffd", "UTF-8"],
       ["\xc3 =?UTF-8?Q?=a8?=", "\u00c3 \ufffd", "ISO-8859-1"],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.deepEqual(headerparser.decodeRFC2047Words(
           headerparser.convert8BitHeader(data[0], (data.length > 2 ? data[2] : null))), data[1]);
       });
     });
   });
 });
-
 });
--- a/mailnews/mime/jsmime/test/test_header_emitter.js
+++ b/mailnews/mime/jsmime/test/test_header_emitter.js
@@ -1,40 +1,39 @@
 "use strict";
 define(function(require) {
-
-var assert = require('assert');
-var jsmime = require('jsmime');
+var assert = require("assert");
+var jsmime = require("jsmime");
 var headeremitter = jsmime.headeremitter;
-var MockDate = require('test/mock_date');
+var MockDate = require("test/mock_date");
 
 function arrayTest(data, fn) {
-  fn.toString = function () {
+  fn.toString = function() {
     let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
+    text = text.replace(/data\[([0-9]*)\]/g, function(m, p) {
       return JSON.stringify(data[p]);
     });
     return text;
   };
   return test(JSON.stringify(data[0]), fn);
 }
 
-suite('headeremitter', function () {
-  suite('addAddresses', function () {
+suite("headeremitter", function() {
+  suite("addAddresses", function() {
     let handler = {
-      reset: function (expected) {
-        this.output = '';
+      reset(expected) {
+        this.output = "";
         this.expected = expected;
       },
-      deliverData: function (data) { this.output += data; },
-      deliverEOF: function () {
-        assert.equal(this.output, this.expected + '\r\n');
-        for (let line of this.output.split('\r\n'))
+      deliverData(data) { this.output += data; },
+      deliverEOF() {
+        assert.equal(this.output, this.expected + "\r\n");
+        for (let line of this.output.split("\r\n"))
           assert.ok(line.length <= 30, "Line is too long");
-      }
+      },
     };
     let header_tests = [
       [[{name: "", email: ""}], ""],
       [[{name: "", email: "a@example.com"}], "a@example.com"],
       [[{name: "John Doe", email: "a@example.com"}], "John Doe <a@example.com>"],
       [[{name: "", email: "a@b.c"}, {name: "", email: "b@b.c"}], "a@b.c, b@b.c"],
       [[{name: "JD", email: "a@a.c"}, {name: "SD", email: "b@b.c"}],
         "JD <a@a.c>, SD <b@b.c>"],
@@ -66,41 +65,41 @@ suite('headeremitter', function () {
                                 {name: "]u[ c", email: "b@b.c"}]}],
         "Group: \"]u[ d\" <a@a.c>,\r\n \"]u[ c\" <b@b.c>;"],
       [[{ name: "user@domain", email: "user@d.com" }],
         "\"user@domain\" <user@d.com>"],
       [[{ name: "Group", group: [{ name: "u@d", email: "a@a.c" },
                                  { name: "u@c", email: "b@b.c" }]}],
         "Group: \"u@d\" <a@a.c>,\r\n \"u@c\" <b@b.c>;"],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let emitter = headeremitter.makeStreamingEmitter(handler, {
           softMargin: 30,
           useASCII: false,
         });
         handler.reset(data[1]);
         emitter.addAddresses(data[0]);
         emitter.finish(true);
       });
     });
   });
-  suite('addAddresses (RFC 2047)', function () {
+  suite("addAddresses (RFC 2047)", function() {
     let handler = {
-      reset: function (expected) {
-        this.output = '';
+      reset(expected) {
+        this.output = "";
         this.expected = expected;
       },
-      deliverData: function (data) { this.output += data; },
-      deliverEOF: function () {
-        assert.equal(this.output, this.expected + '\r\n');
-        for (let line of this.output.split('\r\n'))
+      deliverData(data) { this.output += data; },
+      deliverEOF() {
+        assert.equal(this.output, this.expected + "\r\n");
+        for (let line of this.output.split("\r\n"))
           assert.ok(line.length <= 30, "Line is too long");
-      }
-    }
+      },
+    };
     let header_tests = [
       [[{name: "\u0436", email: "a@a.c"}], "=?UTF-8?B?0LY=?= <a@a.c>"],
       [[{name: "dioxyg\u00e8ne", email: "a@a.c"}],
         "=?UTF-8?Q?dioxyg=c3=a8ne?=\r\n <a@a.c>"],
       // Prefer QP if base64 and QP are exactly the same length
       [[{name: "oxyg\u00e8ne", email: "a@a.c"}],
       // =?UTF-8?B?b3h5Z8OobmU=?=
         "=?UTF-8?Q?oxyg=c3=a8ne?=\r\n <a@a.c>"],
@@ -108,41 +107,41 @@ suite('headeremitter', function () {
         email: "a@a.c"}],
         "=?UTF-8?B?8J+SqfCfkqnwn5Kp?=\r\n =?UTF-8?B?8J+SqQ==?= <a@a.c>"],
       // Bug 1088975: Since the encoded-word should be recognized as an atom,
       // encode commas.
       [[{name: "B\u00fcg 1088975, FirstName", email: "a@b.c"}],
         "=?UTF-8?Q?B=c3=bcg_1088975?=\r\n" +
         " =?UTF-8?Q?=2c_FirstName?=\r\n <a@b.c>"],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let emitter = headeremitter.makeStreamingEmitter(handler, {
           softMargin: 30,
-          useASCII: true
+          useASCII: true,
         });
         handler.reset(data[1]);
         emitter.addAddresses(data[0]);
         emitter.finish(true);
       });
     });
   });
-  suite('addUnstructured (RFC 2047)', function () {
+  suite("addUnstructured (RFC 2047)", function() {
     let handler = {
-      reset: function (expected) {
-        this.output = '';
+      reset(expected) {
+        this.output = "";
         this.expected = expected;
       },
-      deliverData: function (data) { this.output += data; },
-      deliverEOF: function () {
-        assert.equal(this.output, this.expected + '\r\n');
-        for (let line of this.output.split('\r\n'))
+      deliverData(data) { this.output += data; },
+      deliverEOF() {
+        assert.equal(this.output, this.expected + "\r\n");
+        for (let line of this.output.split("\r\n"))
           assert.ok(line.length <= 30, "Line is too long");
-      }
-    }
+      },
+    };
     let header_tests = [
       ["My house   burned down!", "My house burned down!"],
 
       // Which of the 32 "special" characters need to be encoded in QP encoding?
       // Note: Encoding is forced by adding a \x7f at the end.
       // These 5 don't need encoding:
       [" ! * + - / \x7f", "=?UTF-8?Q?_!_*_+_-_/_=7f?="],
 
@@ -201,38 +200,38 @@ suite('headeremitter', function () {
       //          1         2         3
       // 123456789012345678901234567890
         "=?UTF-8?B?TCdveHlnw6huZSBl?=\r\n" +
         " =?UTF-8?B?c3QgdW4gw6lsw6lt?=\r\n" +
         " =?UTF-8?Q?ent_chimique_du_g?=\r\n" +
         " =?UTF-8?Q?roupe_des_chalcog?=\r\n" +
         " =?UTF-8?B?w6huZXM=?="],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let emitter = headeremitter.makeStreamingEmitter(handler, {
           softMargin: 30,
-          useASCII: true
+          useASCII: true,
         });
         handler.reset(data[1]);
         emitter.addUnstructured(data[0]);
         emitter.finish(true);
       });
     });
   });
-  suite("addDate", function () {
+  suite("addDate", function() {
     let handler = {
-      reset: function (expected) {
-        this.output = '';
+      reset(expected) {
+        this.output = "";
         this.expected = expected;
       },
-      deliverData: function (data) { this.output += data; },
-      deliverEOF: function () {
-        assert.equal(this.output, this.expected + '\r\n');
-      }
+      deliverData(data) { this.output += data; },
+      deliverEOF() {
+        assert.equal(this.output, this.expected + "\r\n");
+      },
     };
     let header_tests = [
       // Test basic day/month names
       ["2000-01-01T00:00:00Z", "Sat, 1 Jan 2000 00:00:00 +0000"],
       ["2000-02-01T00:00:00Z", "Tue, 1 Feb 2000 00:00:00 +0000"],
       ["2000-03-01T00:00:00Z", "Wed, 1 Mar 2000 00:00:00 +0000"],
       ["2000-04-01T00:00:00Z", "Sat, 1 Apr 2000 00:00:00 +0000"],
       ["2000-05-01T00:00:00Z", "Mon, 1 May 2000 00:00:00 +0000"],
@@ -291,94 +290,93 @@ suite('headeremitter', function () {
       // Tests that are not actually missing:
       // We don't actually need to test daylight savings time issues, so long as
       // getTimezoneOffset is correct. We've confirmed black-box that the value
       // is being directly queried on every instance, since we have tests that
       // make MockDate.getTimezoneOffset return different values.
       // In addition, ES6 Date objects don't support leap seconds. Invalid dates
       // per RFC 5322 are handled in a later run of code.
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
-        let emitter = headeremitter.makeStreamingEmitter(handler, { });
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
+        let emitter = headeremitter.makeStreamingEmitter(handler, {});
         handler.reset(data[1]);
         emitter.addDate(new MockDate(data[0]));
         emitter.finish(true);
       });
     });
 
     // An invalid date should throw an error instead of make a malformed header.
-    test('Invalid dates', function () {
-      let emitter = headeremitter.makeStreamingEmitter(handler, { });
-      assert.throws(function () { emitter.addDate(new Date(NaN)); }, /Cannot encode an invalid date/);
-      assert.throws(function () { emitter.addDate(new Date("1850-01-01")); }, /Date year is out of encodable range/);
-      assert.throws(function () { emitter.addDate(new Date("10000-01-01")); }, /Cannot encode an invalid date/);
+    test("Invalid dates", function() {
+      let emitter = headeremitter.makeStreamingEmitter(handler, {});
+      assert.throws(function() { emitter.addDate(new Date(NaN)); }, /Cannot encode an invalid date/);
+      assert.throws(function() { emitter.addDate(new Date("1850-01-01")); }, /Date year is out of encodable range/);
+      assert.throws(function() { emitter.addDate(new Date("10000-01-01")); }, /Cannot encode an invalid date/);
     });
 
     // Test preferred breaking for the date header.
-    test('Break spot', function () {
+    test("Break spot", function() {
       let emitter = headeremitter.makeStreamingEmitter(handler, {
-        softMargin: 30
+        softMargin: 30,
       });
       handler.reset("Overly-Long-Date:\r\n Sat, 1 Jan 2000 00:00:00 +0000");
       emitter.addHeaderName("Overly-Long-Date");
       emitter.addDate(new MockDate("2000-01-01T00:00:00Z"));
       emitter.finish();
     });
 
-    test('Correctness of date', function () {
-      let emitter = headeremitter.makeStreamingEmitter(handler, { });
+    test("Correctness of date", function() {
+      let emitter = headeremitter.makeStreamingEmitter(handler, {});
       handler.reset();
       let now = new Date();
       emitter.addDate(now);
       emitter.finish();
       // All engines can parse the date strings we produce
       let reparsed = new Date(handler.output);
 
       // Now and reparsed should be correct to second-level precision.
       assert.equal(reparsed.getMilliseconds(), 0);
       assert.equal(now.getTime() - now.getMilliseconds(), reparsed.getTime());
     });
   });
 
-  suite("Header lengths", function () {
+  suite("Header lengths", function() {
     let handler = {
-      reset: function (expected) {
-        this.output = '';
+      reset(expected) {
+        this.output = "";
         this.expected = expected;
       },
-      deliverData: function (data) { this.output += data; },
-      deliverEOF: function () {
-        assert.equal(this.output, this.expected + '\r\n');
-      }
+      deliverData(data) { this.output += data; },
+      deliverEOF() {
+        assert.equal(this.output, this.expected + "\r\n");
+      },
     };
     let header_tests = [
       [[{name: "Supercalifragilisticexpialidocious", email: "a@b.c"}],
-        'Supercalifragilisticexpialidocious\r\n <a@b.c>'],
+        "Supercalifragilisticexpialidocious\r\n <a@b.c>"],
       [[{email: "supercalifragilisticexpialidocious@" +
           "the.longest.domain.name.in.the.world.invalid"}],
-        'supercalifragilisticexpialidocious\r\n' +
-        ' @the.longest.domain.name.in.the.world.invalid'],
+        "supercalifragilisticexpialidocious\r\n" +
+        " @the.longest.domain.name.in.the.world.invalid"],
       [[{name: "Lopadotemachoselachogaleokranioleipsanodrimhypotrimmatosilphi" +
         "paraomelitokatakechymenokichlepikossyphophattoperisteralektryonoptek" +
         "ephalliokigklopeleiolagoiosiraiobaphetraganopterygon", email: "a@b.c"}],
         new Error],
     ];
-    header_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    header_tests.forEach(function(data) {
+      arrayTest(data, function() {
         let emitter = headeremitter.makeStreamingEmitter(handler, {
           softMargin: 30,
           hardMargin: 50,
           useASCII: false,
         });
         handler.reset(data[1]);
-        if (data[1] instanceof Error)
-          assert.throws(function () { emitter.addAddresses(data[0]); }, /Cannot encode/);
-        else {
-          assert.doesNotThrow(function () { emitter.addAddresses(data[0]); });
+        if (data[1] instanceof Error) {
+          assert.throws(function() { emitter.addAddresses(data[0]); }, /Cannot encode/);
+        } else {
+          assert.doesNotThrow(function() { emitter.addAddresses(data[0]); });
           emitter.finish(true);
         }
       });
     });
   });
 });
-
 });
--- a/mailnews/mime/jsmime/test/test_mime_tree.js
+++ b/mailnews/mime/jsmime/test/test_mime_tree.js
@@ -1,71 +1,70 @@
 "use strict";
 define(function(require) {
-
-var assert = require('assert');
-var jsmime = require('jsmime');
-var fs = require('fs');
+var assert = require("assert");
+var jsmime = require("jsmime");
+var fs = require("fs");
 
 function arrayTest(data, fn) {
-  fn.toString = function () {
+  fn.toString = function() {
     let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
+    text = text.replace(/data\[([0-9]*)\]/g, function(m, p) {
       return JSON.stringify(data[p]);
     });
     return text;
   };
   return test(data[0], fn);
 }
 
-/// Returns and deletes object[field] if present, or undefined if not.
+// Returns and deletes object[field] if present, or undefined if not.
 function extract_field(object, field) {
   if (field in object) {
     var result = object[field];
     delete object[field];
     return result;
   }
   return undefined;
 }
 
-/// A file cache for read_file.
+// A file cache for read_file.
 var file_cache = {};
 
 /**
  * Read a file into a string (all line endings become CRLF).
  * @param file  The name of the file to read, relative to the data/ directory.
  * @param start The first line of the file to return, defaulting to 0
  * @param end   The last line of the file to return, defaulting to the number of
  *              lines in the file.
  * @return      Promise<String> The contents of the file as a binary string.
  */
 function read_file(file, start, end) {
   if (!(file in file_cache)) {
-    var realFile = new Promise(function (resolve, reject) {
-      fs.readFile("data/" + file, function (err, data) {
+    var realFile = new Promise(function(resolve, reject) {
+      fs.readFile("data/" + file, function(err, data) {
         if (err) reject(err);
         else resolve(data);
       });
     });
-    var loader = realFile.then(function (contents) {
-      var inStrForm = '';
+    var loader = realFile.then(function(contents) {
+      var inStrForm = "";
       while (contents.length > 0) {
         inStrForm += String.fromCharCode.apply(null,
           contents.subarray(0, 1024));
         contents = contents.subarray(1024);
       }
       return inStrForm.split(/\r\n|[\r\n]/);
     });
     file_cache[file] = loader;
   }
-  return file_cache[file].then(function (contents) {
+  return file_cache[file].then(function(contents) {
     if (start !== undefined) {
       contents = contents.slice(start - 1, end - 1);
     }
-    return contents.join('\r\n');
+    return contents.join("\r\n");
   });
 }
 
 /**
  * Helper for body tests.
  *
  * Some extra options are listed too:
  * _split: The contents of the file will be passed in packets split by this
@@ -92,21 +91,21 @@ function make_body_test(test, file, opts
     if (packetize !== undefined)
       msgcontents = msgcontents.split(packetize);
     if (eol !== undefined) {
       msgcontents = msgcontents.replace(/\r\n/g, eol);
     }
     return msgcontents;
   });
   if (eol !== undefined) {
-    results = results.then(function(results) {
-      for (var part of results) {
+    results = results.then(function(results_) {
+      for (let part of results_) {
         part[1] = part[1].replace(/\r\n/g, eol);
       }
-      return results;
+      return results_;
     });
   }
   return [test, msgtext, opts, results];
 }
 
 /**
  * Execute a single MIME tree test.
  *
@@ -125,487 +124,486 @@ function testParser(message, opts, resul
   var checkingHeaders;
   var calls = 0;
   var fusingParts = extract_field(opts, "_nofuseparts") === undefined;
   var emitter = {
     stack: [],
     startMessage: function emitter_startMsg() {
       assert.equal(this.stack.length, 0);
       calls++;
-      this.partData = '';
+      this.partData = "";
     },
     endMessage: function emitter_endMsg() {
       assert.equal(this.stack.length, 0);
       calls++;
     },
     startPart: function emitter_startPart(partNum, headers) {
       this.stack.push(partNum);
       if (checkingHeaders) {
         assert.ok(partNum in uncheckedValues);
         // Headers is a map, convert it to an object.
-        var objmap = new Object();
+        var objmap = {};
         for (let pair of headers)
           objmap[pair[0]] = pair[1];
         var expected = uncheckedValues[partNum];
-        var convresults = new Object();
+        var convresults = {};
         for (let key in expected) {
           try {
             convresults[key] =
               jsmime.headerparser.parseStructuredHeader(key, expected[key]);
           } catch (e) {
             convresults[key] = expected[key];
           }
         }
         assert.deepEqual(objmap, convresults);
         if (fusingParts)
-          assert.equal(this.partData, '');
+          assert.equal(this.partData, "");
         delete uncheckedValues[partNum];
       }
     },
     deliverPartData: function emitter_partData(partNum, data) {
       assert.equal(this.stack[this.stack.length - 1], partNum);
       if (!checkingHeaders) {
-        if (fusingParts)
+        if (fusingParts) {
           this.partData += data;
-        else {
+        } else {
           let check = uncheckedValues.shift();
           assert.equal(partNum, check[0]);
           assert.equal(data, check[1]);
         }
       }
     },
     endPart: function emitter_endPart(partNum) {
-      if (this.partData != '') {
+      if (this.partData != "") {
         let check = uncheckedValues.shift();
         assert.equal(partNum, check[0]);
         assert.equal(this.partData, check[1]);
-        this.partData = '';
+        this.partData = "";
       }
       assert.equal(this.stack.pop(), partNum);
-    }
+    },
   };
-  opts.onerror = function (e) { throw e; };
+  opts.onerror = function(e) { throw e; };
 
-  return Promise.all([message, results]).then(function (vals) {
-    let [message, results] = vals;
+  return Promise.all([message, results]).then(function(vals) {
+    let [message_, results_] = vals;
     // Clone the results array into uncheckedValues
-    if (Array.isArray(results)) {
-      uncheckedValues = Array.from(results);
+    if (Array.isArray(results_)) {
+      uncheckedValues = Array.from(results_);
       checkingHeaders = false;
     } else {
       uncheckedValues = {};
-      for (let key in results) {
-        uncheckedValues[key] = results[key];
+      for (let key in results_) {
+        uncheckedValues[key] = results_[key];
       }
       checkingHeaders = true;
     }
-    if (!Array.isArray(message))
-      message = [message];
+    if (!Array.isArray(message_))
+      message_ = [message_];
     var parser = new jsmime.MimeParser(emitter, opts);
-    message.forEach(function (packet) {
+    message_.forEach(function(packet) {
       parser.deliverData(packet);
     });
     parser.deliverEOF();
     assert.equal(calls, 2);
     if (!checkingHeaders)
       assert.equal(0, uncheckedValues.length);
     else
       assert.deepEqual({}, uncheckedValues);
   });
 }
 
-suite('MimeParser', function () {
-  /// This is the expected part specifier for the multipart-complex1 test file,
-  /// specified here because it is used in several cases.
-  let mpart_complex1 = [['1', 8, 10], ['2', 14, 16], ['3.1', 22, 24],
-      ['4', 29, 31], ['5', 33, 35]];
+suite("MimeParser", function() {
+  // This is the expected part specifier for the multipart-complex1 test file,
+  // specified here because it is used in several cases.
+  let mpart_complex1 = [["1", 8, 10], ["2", 14, 16], ["3.1", 22, 24],
+      ["4", 29, 31], ["5", 33, 35]];
 
-  suite('Simple tests', function () {
+  suite("Simple tests", function() {
     let parser_tests = [
       // The following tests are either degenerate or error cases that should
       // work
-      ["Empty string", "", {}, {'': {}}],
-      ["No value for header", "Header", {}, {'': {"Header": ['']}}],
+      ["Empty string", "", {}, {"": {}}],
+      ["No value for header", "Header", {}, {"": {"Header": [""]}}],
       ["No trailing newline", "To: eof@example.net", {},
-        {'': {"To": ["eof@example.net"]}}],
+        {"": {"To": ["eof@example.net"]}}],
       ["Header no val", "To: eof@example.net\r\n", {},
-        {'': {"To": ["eof@example.net"]}}],
-      ["No body no headers", "\r\n\r\n", {}, {'': {}}],
-      ["Body no headers", "\r\n\r\nA", {}, {'': {}}],
+        {"": {"To": ["eof@example.net"]}}],
+      ["No body no headers", "\r\n\r\n", {}, {"": {}}],
+      ["Body no headers", "\r\n\r\nA", {}, {"": {}}],
       // Basic cases for headers
-      ['Multiparts get headers', read_file("multipart-complex1"), {},
-        { '': {'Content-Type': ['multipart/mixed; boundary="boundary"']},
-          '1': {'Content-Type': ['application/octet-stream'],
-                'Content-Transfer-Encoding': ['base64']},
-          '2': {'Content-Type': ['image/png'],
-                'Content-Transfer-Encoding': ['base64']},
-          '3': {'Content-Type': ['multipart/related; boundary="boundary2"']},
-          '3.1': {'Content-Type': ['text/html']},
-          '4': {'Content-Type': ['text/plain']}, '5': {} }],
+      ["Multiparts get headers", read_file("multipart-complex1"), {},
+        { "": {"Content-Type": ['multipart/mixed; boundary="boundary"']},
+          "1": {"Content-Type": ["application/octet-stream"],
+                "Content-Transfer-Encoding": ["base64"]},
+          "2": {"Content-Type": ["image/png"],
+                "Content-Transfer-Encoding": ["base64"]},
+          "3": {"Content-Type": ['multipart/related; boundary="boundary2"']},
+          "3.1": {"Content-Type": ["text/html"]},
+          "4": {"Content-Type": ["text/plain"]}, "5": {} }],
     ];
-    parser_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    parser_tests.forEach(function(data) {
+      arrayTest(data, function() {
         return testParser(data[1], data[2], data[3]);
       });
     });
   });
 
-  suite('Body tests', function () {
+  suite("Body tests", function() {
     let parser_tests = [
       // Body tests from data
       // (Note: line numbers are 1-based. Also, to capture trailing EOF, add 2
       // to the last line number of the file).
-      make_body_test("Basic body", "basic1", {}, [['', 3, 5]]),
-      make_body_test("Basic multipart", "multipart1", {}, [['1', 10, 12]]),
-      make_body_test("Basic multipart", "multipart2", {}, [['1', 8, 11]]),
+      make_body_test("Basic body", "basic1", {}, [["", 3, 5]]),
+      make_body_test("Basic multipart", "multipart1", {}, [["1", 10, 12]]),
+      make_body_test("Basic multipart", "multipart2", {}, [["1", 8, 11]]),
       make_body_test("Complex multipart", "multipart-complex1", {},
         mpart_complex1),
       make_body_test("Truncated multipart", "multipart-complex2", {},
-        [['1.1.1.1', 21, 25], ['2', 27, 57], ['3', 60, 62]]),
+        [["1.1.1.1", 21, 25], ["2", 27, 57], ["3", 60, 62]]),
       make_body_test("No LF multipart", "multipartmalt-detach", {},
-        [['1', 20, 21], ['2.1', 27, 38], ['2.2', 42, 43], ['2.3', 47, 48],
-         ['3', 53, 54]]),
+        [["1", 20, 21], ["2.1", 27, 38], ["2.2", 42, 43], ["2.3", 47, 48],
+         ["3", 53, 54]]),
       make_body_test("Raw body", "multipart1", {bodyformat: "raw"},
-        [['', 4, 14]]),
+        [["", 4, 14]]),
       ["Base64 decode 1", read_file("base64-1"), {bodyformat: "decode"},
-        [['', "\r\nHello, world! (Again...)\r\n\r\nLet's see how well base64 " +
+        [["", "\r\nHello, world! (Again...)\r\n\r\nLet's see how well base64 " +
               "text is handled.                            Yay, lots of space" +
               "s! There's even a CRLF at the end and one at the beginning, bu" +
               "t the output shouldn't have it.\r\n"]]],
       ["Base64 decode 2", read_file("base64-2"), {bodyformat: "decode"},
-        [['', "<html><body>This is base64 encoded HTML text, and the tags sho" +
+        [["", "<html><body>This is base64 encoded HTML text, and the tags sho" +
               "uldn't be stripped.\r\n<b>Bold text is bold!</b></body></html>" +
               "\r\n"]]],
       ["Base64 decode line issues",
-        read_file("base64-2").then(function (s) { return s.split(/(\r\n)/) }),
+        read_file("base64-2").then(function(s) { return s.split(/(\r\n)/); }),
         {bodyformat: "decode"},
-        [['', "<html><body>This is base64 encoded HTML text, and the tags sho" +
+        [["", "<html><body>This is base64 encoded HTML text, and the tags sho" +
               "uldn't be stripped.\r\n<b>Bold text is bold!</b></body></html>" +
               "\r\n"]]],
-      make_body_test("Base64 nodecode", "base64-1", {}, [['', 4, 9]]),
+      make_body_test("Base64 nodecode", "base64-1", {}, [["", 4, 9]]),
       ["QP decode", read_file("bug505221"),
-        {pruneat: '1', bodyformat: "decode"},
-        [['1', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"' +
+        {pruneat: "1", bodyformat: "decode"},
+        [["1", '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"' +
                '>\r\n<HTML><HEAD>\r\n<META HTTP-EQUIV="Content-Type" CONTENT=' +
                '"text/html; charset=us-ascii">\r\n\r\n\r\n<META content="MSHT' +
                'ML 6.00.6000.16735" name=GENERATOR></HEAD>\r\n<BODY> bbb\r\n<' +
-               '/BODY></HTML>']]],
+               "/BODY></HTML>"]]],
       ["Nested messages", read_file("message-encoded"), {bodyformat: "decode"},
-        [['1$', 'This is a plain-text message.'],
-         ['2$', 'I am a plain-text message.'],
-         ['3$', 'I am an encoded plain-text message.']]],
+        [["1$", "This is a plain-text message."],
+         ["2$", "I am a plain-text message."],
+         ["3$", "I am an encoded plain-text message."]]],
       ["Nested message headers", read_file("message-encoded"), {},
-        {'': {'Content-Type': ['multipart/mixed; boundary="iamaboundary"']},
-         '1': {'Content-Type': ['message/rfc822']},
-         '1$': {'Subject': ['I am a subject']},
-         '2': {'Content-Type': ['message/global'],
-               'Content-Transfer-Encoding': ['base64']},
-         '2$': {'Subject': ['\u79c1\u306f\u3001\u4ef6\u540d\u5348\u524d']},
-         '3': {'Content-Type': ['message/news'],
-               'Content-Transfer-Encoding': ['quoted-printable']},
-         '3$': {'Subject': ['\u79c1\u306f\u3001\u4ef6\u540d\u5348\u524d']}}],
+        {"": {"Content-Type": ['multipart/mixed; boundary="iamaboundary"']},
+         "1": {"Content-Type": ["message/rfc822"]},
+         "1$": {"Subject": ["I am a subject"]},
+         "2": {"Content-Type": ["message/global"],
+               "Content-Transfer-Encoding": ["base64"]},
+         "2$": {"Subject": ["\u79c1\u306f\u3001\u4ef6\u540d\u5348\u524d"]},
+         "3": {"Content-Type": ["message/news"],
+               "Content-Transfer-Encoding": ["quoted-printable"]},
+         "3$": {"Subject": ["\u79c1\u306f\u3001\u4ef6\u540d\u5348\u524d"]}}],
     ];
-    parser_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    parser_tests.forEach(function(data) {
+      arrayTest(data, function() {
         return testParser(data[1], data[2], data[3]);
       });
     });
   });
 
-  suite('Torture tests', function () {
+  suite("Torture tests", function() {
     // Generate a very long message for tests
-    let teststr = 'a';
+    let teststr = "a";
     for (let i = 0; i < 16; i++)
       teststr += teststr;
     let parser_tests = [
       ["Base64 very long decode",
         "Content-Transfer-Encoding: base64\r\n\r\n" + btoa(teststr) + "\r\n",
-        {bodyformat: "decode"}, [['', teststr]]],
+        {bodyformat: "decode"}, [["", teststr]]],
       make_body_test("Torture regular body", "mime-torture", {}, [
-        ['1', 17, 21], ['2$.1', 58, 75], ['2$.2.1', 83, 97], ['2$.3', 102, 130],
-        ['3$', 155, 7742], ['4', 7747, 8213], ['5', 8218, 8242],
-        ['6$.1.1', 8284, 8301], ['6$.1.2', 8306, 8733], ['6$.2.1', 8742, 9095],
-        ['6$.2.2', 9100, 9354], ['6$.2.3', 9357, 11794],
-        ['6$.2.4', 11797, 12155], ['6$.3', 12161, 12809],
-        ['7$.1', 12844, 12845], ['7$.2', 12852, 13286],
-        ['7$.3', 13288, 13297], ['8$.1', 13331, 13358], ['8$.2', 13364, 13734],
-        ['9$', 13757, 20179], ['10', 20184, 21200], ['11$.1', 21223, 22031],
-        ['11$.2', 22036, 22586], ['12$.1', 22607, 23469],
-        ['12$.2', 23474, 23774], ['12$.3$.1', 23787, 23795],
-        ['12$.3$.2.1', 23803, 23820], ['12$.3$.2.2', 23825, 24633],
-        ['12$.3$.3', 24640, 24836], ['12$.3$.4$', 24848, 25872]]),
-      make_body_test("Torture pruneat", "mime-torture", {"pruneat": '4'},
-        [['4', 7747, 8213]]),
+        ["1", 17, 21], ["2$.1", 58, 75], ["2$.2.1", 83, 97], ["2$.3", 102, 130],
+        ["3$", 155, 7742], ["4", 7747, 8213], ["5", 8218, 8242],
+        ["6$.1.1", 8284, 8301], ["6$.1.2", 8306, 8733], ["6$.2.1", 8742, 9095],
+        ["6$.2.2", 9100, 9354], ["6$.2.3", 9357, 11794],
+        ["6$.2.4", 11797, 12155], ["6$.3", 12161, 12809],
+        ["7$.1", 12844, 12845], ["7$.2", 12852, 13286],
+        ["7$.3", 13288, 13297], ["8$.1", 13331, 13358], ["8$.2", 13364, 13734],
+        ["9$", 13757, 20179], ["10", 20184, 21200], ["11$.1", 21223, 22031],
+        ["11$.2", 22036, 22586], ["12$.1", 22607, 23469],
+        ["12$.2", 23474, 23774], ["12$.3$.1", 23787, 23795],
+        ["12$.3$.2.1", 23803, 23820], ["12$.3$.2.2", 23825, 24633],
+        ["12$.3$.3", 24640, 24836], ["12$.3$.4$", 24848, 25872]]),
+      make_body_test("Torture pruneat", "mime-torture", {"pruneat": "4"},
+        [["4", 7747, 8213]]),
 
       // Test packetization problems
       make_body_test("Large packets", "multipart-complex1",
         {"_split": /(.{30})/}, mpart_complex1),
       make_body_test("Split on newline", "multipart-complex1",
         {"_split": /(\r\n)/}, mpart_complex1),
       make_body_test("Pathological splitting", "multipart-complex1",
-        {"_split": ''}, mpart_complex1),
+        {"_split": ""}, mpart_complex1),
 
       // Non-CLRF line endings?
       make_body_test("LF-based messages", "multipart-complex1",
         {"_eol": "\n"}, mpart_complex1),
       make_body_test("CR-based messages", "multipart-complex1",
         {"_eol": "\r"}, mpart_complex1),
     ];
-    parser_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    parser_tests.forEach(function(data) {
+      arrayTest(data, function() {
         return testParser(data[1], data[2], data[3]);
       });
     });
   });
 
-  suite('Header tests', function () {
+  suite("Header tests", function() {
     let parser_tests = [
       // Basic cases for headers
-      ['Multiparts get headers', read_file("multipart-complex1"), {},
-        { '': {'Content-Type': ['multipart/mixed; boundary="boundary"']},
-          '1': {'Content-Type': ['application/octet-stream'],
-                'Content-Transfer-Encoding': ['base64']},
-          '2': {'Content-Type': ['image/png'],
-                'Content-Transfer-Encoding': ['base64']},
-          '3': {'Content-Type': ['multipart/related; boundary="boundary2"']},
-          '3.1': {'Content-Type': ['text/html']},
-          '4': {'Content-Type': ['text/plain']}, '5': {} }],
+      ["Multiparts get headers", read_file("multipart-complex1"), {},
+        { "": {"Content-Type": ['multipart/mixed; boundary="boundary"']},
+          "1": {"Content-Type": ["application/octet-stream"],
+                "Content-Transfer-Encoding": ["base64"]},
+          "2": {"Content-Type": ["image/png"],
+                "Content-Transfer-Encoding": ["base64"]},
+          "3": {"Content-Type": ['multipart/related; boundary="boundary2"']},
+          "3.1": {"Content-Type": ["text/html"]},
+          "4": {"Content-Type": ["text/plain"]}, "5": {} }],
       // 'From ' is not an [iterable] header
-      ['Exclude mbox delimiter', read_file('bugmail11'), {}, {'': {
-        'X-Mozilla-Status': ['0001'], 'X-Mozilla-Status2': ['00000000'],
-        'X-Mozilla-Keys': [''],
-        'Return-Path': ['<example@example.com>',
-           '<bugzilla-daemon@mozilla.org>'],
-        'Delivered-To': ['bugmail@example.org'],
-        'Received': ['by 10.114.166.12 with SMTP id o12cs163262wae;' +
-                     '        Fri, 11 Apr 2008 07:17:31 -0700 (PDT)',
-          'by 10.115.60.1 with SMTP id n1mr214763wak.181.1207923450166;' +
-          '        Fri, 11 Apr 2008 07:17:30 -0700 (PDT)',
-          'from webapp-out.mozilla.org (webapp01.sj.mozilla.com [63.245.208.1' +
-          '46])        by mx.google.com with ESMTP id n38si6807242wag.2.2008.' +
-          '04.11.07.17.29;        Fri, 11 Apr 2008 07:17:30 -0700 (PDT)',
-          'from mrapp51.mozilla.org (mrapp51.mozilla.org [127.0.0.1])' +
-          '\tby webapp-out.mozilla.org (8.13.8/8.13.8) with ESMTP id m3BEHTGU' +
-          '030132\tfor <bugmail@example.org>; Fri, 11 Apr 2008 07:17:29 -0700',
-          '(from root@localhost)' +
-          '\tby mrapp51.mozilla.org (8.13.8/8.13.8/Submit) id m3BEHTk4030129;' +
-          '\tFri, 11 Apr 2008 07:17:29 -0700'],
-        'Received-Spf': ['neutral (google.com: 63.245.208.146 is neither perm' +
-          'itted nor denied by best guess record for domain of bugzilla-daemo' +
-          'n@mozilla.org) client-ip=63.245.208.146;'],
-        'Authentication-Results': ['mx.google.com; spf=neutral (google.com: 6' +
-          '3.245.208.146 is neither permitted nor denied by best guess record' +
-          ' for domain of bugzilla-daemon@mozilla.org) smtp.mail=bugzilla-dae' +
-          'mon@mozilla.org'],
-        'Date': ['Fri, 11 Apr 2008 07:17:29 -0700'],
-        'Message-ID': ['<200804111417.m3BEHTk4030129@mrapp51.mozilla.org>'],
-        'From': ['bugzilla-daemon@mozilla.org'], 'To': ['bugmail@example.org'],
-        'Subject': ['Bugzilla: confirm account creation'],
-        'X-Bugzilla-Type': ['admin'],
-        'Content-Type': ['text/plain; charset="UTF-8"'],
-        'MIME-Version': ['1.0']}}],
+      ["Exclude mbox delimiter", read_file("bugmail11"), {}, {"": {
+        "X-Mozilla-Status": ["0001"], "X-Mozilla-Status2": ["00000000"],
+        "X-Mozilla-Keys": [""],
+        "Return-Path": ["<example@example.com>",
+           "<bugzilla-daemon@mozilla.org>"],
+        "Delivered-To": ["bugmail@example.org"],
+        "Received": ["by 10.114.166.12 with SMTP id o12cs163262wae;" +
+                     "        Fri, 11 Apr 2008 07:17:31 -0700 (PDT)",
+          "by 10.115.60.1 with SMTP id n1mr214763wak.181.1207923450166;" +
+          "        Fri, 11 Apr 2008 07:17:30 -0700 (PDT)",
+          "from webapp-out.mozilla.org (webapp01.sj.mozilla.com [63.245.208.1" +
+          "46])        by mx.google.com with ESMTP id n38si6807242wag.2.2008." +
+          "04.11.07.17.29;        Fri, 11 Apr 2008 07:17:30 -0700 (PDT)",
+          "from mrapp51.mozilla.org (mrapp51.mozilla.org [127.0.0.1])" +
+          "\tby webapp-out.mozilla.org (8.13.8/8.13.8) with ESMTP id m3BEHTGU" +
+          "030132\tfor <bugmail@example.org>; Fri, 11 Apr 2008 07:17:29 -0700",
+          "(from root@localhost)" +
+          "\tby mrapp51.mozilla.org (8.13.8/8.13.8/Submit) id m3BEHTk4030129;" +
+          "\tFri, 11 Apr 2008 07:17:29 -0700"],
+        "Received-Spf": ["neutral (google.com: 63.245.208.146 is neither perm" +
+          "itted nor denied by best guess record for domain of bugzilla-daemo" +
+          "n@mozilla.org) client-ip=63.245.208.146;"],
+        "Authentication-Results": ["mx.google.com; spf=neutral (google.com: 6" +
+          "3.245.208.146 is neither permitted nor denied by best guess record" +
+          " for domain of bugzilla-daemon@mozilla.org) smtp.mail=bugzilla-dae" +
+          "mon@mozilla.org"],
+        "Date": ["Fri, 11 Apr 2008 07:17:29 -0700"],
+        "Message-ID": ["<200804111417.m3BEHTk4030129@mrapp51.mozilla.org>"],
+        "From": ["bugzilla-daemon@mozilla.org"], "To": ["bugmail@example.org"],
+        "Subject": ["Bugzilla: confirm account creation"],
+        "X-Bugzilla-Type": ["admin"],
+        "Content-Type": ['text/plain; charset="UTF-8"'],
+        "MIME-Version": ["1.0"]}}],
     ];
-    parser_tests.forEach(function (data) {
-      arrayTest(data, function () {
+    parser_tests.forEach(function(data) {
+      arrayTest(data, function() {
         return testParser(data[1], data[2], data[3]);
       });
     });
   });
 
-  suite('Charset tests', function () {
+  suite("Charset tests", function() {
     function buildTree(file, options) {
       var tree = new Map();
       var emitter = {
-        startPart: function (part, headers) {
-          tree.set(part, {headers: headers, body: null});
+        startPart(part, headers) {
+          tree.set(part, {headers, body: null});
         },
-        deliverPartData: function (part, data) {
+        deliverPartData(part, data) {
           var obj = tree.get(part);
-          if (obj.body === null)
+          if (obj.body === null) {
             obj.body = data;
-          else if (typeof obj.body === "string")
+          } else if (typeof obj.body === "string") {
             obj.body += data;
-          else {
+          } else {
             var newData = new Uint8Array(obj.body.length + data.length);
             newData.set(obj.body);
             newData.subarray(obj.body.length).set(data);
             obj.body = newData;
           }
-        }
+        },
       };
-      return file.then(function (data) {
+      return file.then(function(data) {
         var parser = new jsmime.MimeParser(emitter, options);
         parser.deliverData(data);
         parser.deliverEOF();
         return tree;
       });
     }
-    test('Unicode decoding', function () {
-      return buildTree(read_file('shift-jis-image'), {
+    test("Unicode decoding", function() {
+      return buildTree(read_file("shift-jis-image"), {
         strformat: "unicode",
-        bodyformat: "decode"
-      }).then(function (tree) {
+        bodyformat: "decode",
+      }).then(function(tree) {
         // text/plain should be transcoded...
-        assert.equal(tree.get('1').headers.get('Content-Type').get('charset'),
-          'Shift-JIS');
-        assert.equal(tree.get('1').headers.charset, 'Shift-JIS');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb');
-        assert.equal(tree.get('1').body, 'Portable Network Graphics\uff08' +
-          '\u30dd\u30fc\u30bf\u30d6\u30eb\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc' +
-          '\u30af\u30fb\u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9\u3001PNG' +
-          '\uff09\u306f\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u3067\u30d3\u30c3' +
-          '\u30c8\u30de\u30c3\u30d7\u753b\u50cf\u3092\u6271\u3046\u30d5\u30a1' +
-          '\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b' +
-          '\u3002\u5727\u7e2e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3068\u3057' +
-          '\u3066Deflate\u3092\u63a1\u7528\u3057\u3066\u3044\u308b\u3001' +
-          '\u5727\u7e2e\u306b\u3088\u308b\u753b\u8cea\u306e\u52a3\u5316\u306e' +
-          '\u306a\u3044\u53ef\u9006\u5727\u7e2e\u306e\u753b\u50cf\u30d5\u30a1' +
-          '\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b' +
-          '\u3002\r\n');
+        assert.equal(tree.get("1").headers.get("Content-Type").get("charset"),
+          "Shift-JIS");
+        assert.equal(tree.get("1").headers.charset, "Shift-JIS");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb");
+        assert.equal(tree.get("1").body, "Portable Network Graphics\uff08" +
+          "\u30dd\u30fc\u30bf\u30d6\u30eb\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc" +
+          "\u30af\u30fb\u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9\u3001PNG" +
+          "\uff09\u306f\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u3067\u30d3\u30c3" +
+          "\u30c8\u30de\u30c3\u30d7\u753b\u50cf\u3092\u6271\u3046\u30d5\u30a1" +
+          "\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b" +
+          "\u3002\u5727\u7e2e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3068\u3057" +
+          "\u3066Deflate\u3092\u63a1\u7528\u3057\u3066\u3044\u308b\u3001" +
+          "\u5727\u7e2e\u306b\u3088\u308b\u753b\u8cea\u306e\u52a3\u5316\u306e" +
+          "\u306a\u3044\u53ef\u9006\u5727\u7e2e\u306e\u753b\u50cf\u30d5\u30a1" +
+          "\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b" +
+          "\u3002\r\n");
         // ... but not image/png
-        assert.ok(!tree.get('2').headers.get('Content-Type').has('charset'));
-        assert.equal(tree.get('2').headers.charset, '');
-        assert.equal(tree.get('2').headers.get('Content-Description'),
-          '\ufffdP\ufffdc\ufffd@\ufffd\ufffd\ufffdR\ufffdA\ufffdg\ufffd\ufffd');
-        assert.equal(tree.get('2').headers.getRawHeader('Content-Description'),
-          '\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b');
-        var imageData = 'iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE' +
-          'QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA' +
-          'AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0' +
-          'klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS' +
-          '8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt' +
-          'lmUAAAAASUVORK5CYII=';
+        assert.ok(!tree.get("2").headers.get("Content-Type").has("charset"));
+        assert.equal(tree.get("2").headers.charset, "");
+        assert.equal(tree.get("2").headers.get("Content-Description"),
+          "\ufffdP\ufffdc\ufffd@\ufffd\ufffd\ufffdR\ufffdA\ufffdg\ufffd\ufffd");
+        assert.equal(tree.get("2").headers.getRawHeader("Content-Description"),
+          "\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b");
+        var imageData = "iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE" +
+          "QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA" +
+          "AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0" +
+          "klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS" +
+          "8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt" +
+          "lmUAAAAASUVORK5CYII=";
         imageData = atob(imageData);
         var asArray = new Uint8Array(imageData.length);
         for (var i = 0; i < asArray.length; i++)
           asArray[i] = imageData.charCodeAt(i);
-        assert.deepEqual(tree.get('2').body, asArray);
+        assert.deepEqual(tree.get("2").body, asArray);
 
         // Touching the header charset should change the interpretation.
-        tree.get('1').headers.charset = 'Shift-JIS';
-        assert.equal(tree.get('1').headers.charset, 'Shift-JIS');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb');
+        tree.get("1").headers.charset = "Shift-JIS";
+        assert.equal(tree.get("1").headers.charset, "Shift-JIS");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb");
       });
     });
-    test('Fallback charset decoding', function () {
-      return buildTree(read_file('shift-jis-image'), {
+    test("Fallback charset decoding", function() {
+      return buildTree(read_file("shift-jis-image"), {
         strformat: "unicode",
         charset: "ISO-8859-1",
-        bodyformat: "decode"
-      }).then(function (tree) {
+        bodyformat: "decode",
+      }).then(function(tree) {
         // text/plain should be transcoded...
-        assert.equal(tree.get('1').headers.get('Content-Type').get('charset'),
-          'Shift-JIS');
-        assert.equal(tree.get('1').headers.charset, 'Shift-JIS');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb');
-        assert.equal(tree.get('1').body, 'Portable Network Graphics\uff08' +
-          '\u30dd\u30fc\u30bf\u30d6\u30eb\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc' +
-          '\u30af\u30fb\u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9\u3001PNG' +
-          '\uff09\u306f\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u3067\u30d3\u30c3' +
-          '\u30c8\u30de\u30c3\u30d7\u753b\u50cf\u3092\u6271\u3046\u30d5\u30a1' +
-          '\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b' +
-          '\u3002\u5727\u7e2e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3068\u3057' +
-          '\u3066Deflate\u3092\u63a1\u7528\u3057\u3066\u3044\u308b\u3001' +
-          '\u5727\u7e2e\u306b\u3088\u308b\u753b\u8cea\u306e\u52a3\u5316\u306e' +
-          '\u306a\u3044\u53ef\u9006\u5727\u7e2e\u306e\u753b\u50cf\u30d5\u30a1' +
-          '\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b' +
-          '\u3002\r\n');
+        assert.equal(tree.get("1").headers.get("Content-Type").get("charset"),
+          "Shift-JIS");
+        assert.equal(tree.get("1").headers.charset, "Shift-JIS");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb");
+        assert.equal(tree.get("1").body, "Portable Network Graphics\uff08" +
+          "\u30dd\u30fc\u30bf\u30d6\u30eb\u30fb\u30cd\u30c3\u30c8\u30ef\u30fc" +
+          "\u30af\u30fb\u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9\u3001PNG" +
+          "\uff09\u306f\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u3067\u30d3\u30c3" +
+          "\u30c8\u30de\u30c3\u30d7\u753b\u50cf\u3092\u6271\u3046\u30d5\u30a1" +
+          "\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b" +
+          "\u3002\u5727\u7e2e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3068\u3057" +
+          "\u3066Deflate\u3092\u63a1\u7528\u3057\u3066\u3044\u308b\u3001" +
+          "\u5727\u7e2e\u306b\u3088\u308b\u753b\u8cea\u306e\u52a3\u5316\u306e" +
+          "\u306a\u3044\u53ef\u9006\u5727\u7e2e\u306e\u753b\u50cf\u30d5\u30a1" +
+          "\u30a4\u30eb\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u3042\u308b" +
+          "\u3002\r\n");
         // ... but not image/png
-        assert.ok(!tree.get('2').headers.get('Content-Type').has('charset'));
-        assert.equal(tree.get('2').headers.charset, 'ISO-8859-1');
-        assert.equal(tree.get('2').headers.get('Content-Description'),
-          '\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039');
-        assert.equal(tree.get('2').headers.getRawHeader('Content-Description'),
-          '\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b');
-        var imageData = 'iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE' +
-          'QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA' +
-          'AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0' +
-          'klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS' +
-          '8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt' +
-          'lmUAAAAASUVORK5CYII=';
+        assert.ok(!tree.get("2").headers.get("Content-Type").has("charset"));
+        assert.equal(tree.get("2").headers.charset, "ISO-8859-1");
+        assert.equal(tree.get("2").headers.get("Content-Description"),
+          "\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039");
+        assert.equal(tree.get("2").headers.getRawHeader("Content-Description"),
+          "\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b");
+        var imageData = "iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE" +
+          "QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA" +
+          "AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0" +
+          "klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS" +
+          "8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt" +
+          "lmUAAAAASUVORK5CYII=";
         imageData = atob(imageData);
         var asArray = new Uint8Array(imageData.length);
         for (var i = 0; i < asArray.length; i++)
           asArray[i] = imageData.charCodeAt(i);
-        assert.deepEqual(tree.get('2').body, asArray);
+        assert.deepEqual(tree.get("2").body, asArray);
 
         // Touching the header charset should change the interpretation.
-        tree.get('1').headers.charset = 'Shift-JIS';
-        assert.equal(tree.get('1').headers.charset, 'Shift-JIS');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb');
+        tree.get("1").headers.charset = "Shift-JIS";
+        assert.equal(tree.get("1").headers.charset, "Shift-JIS");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb");
       });
     });
-    test('Forced charset decoding', function () {
-      return buildTree(read_file('shift-jis-image'), {
+    test("Forced charset decoding", function() {
+      return buildTree(read_file("shift-jis-image"), {
         strformat: "unicode",
         charset: "ISO-8859-1",
         "force-charset": true,
-        bodyformat: "decode"
-      }).then(function (tree) {
+        bodyformat: "decode",
+      }).then(function(tree) {
         // text/plain should be transcoded...
-        assert.equal(tree.get('1').headers.get('Content-Type').get('charset'),
-          'Shift-JIS');
-        assert.equal(tree.get('1').headers.charset, 'ISO-8859-1');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039');
-        assert.equal(tree.get('1').body, 'Portable Network Graphics\u0081i' +
-          '\u0192|\u0081[\u0192^\u0192u\u0192\u2039\u0081E\u0192l\u0192b' +
-          '\u0192g\u0192\u008f\u0081[\u0192N\u0081E\u0192O\u0192\u2030\u0192t' +
-          '\u0192B\u0192b\u0192N\u0192X\u0081APNG\u0081j\u201a\u00cd\u0192R' +
-          '\u0192\u201c\u0192s\u0192\u2026\u0081[\u0192^\u201a\u00c5\u0192r' +
-          '\u0192b\u0192g\u0192}\u0192b\u0192v\u2030\u00e6\u2018\u0153\u201a' +
-          '\u00f0\u02c6\u00b5\u201a\u00a4\u0192t\u0192@\u0192C\u0192\u2039' +
-          '\u0192t\u0192H\u0081[\u0192}\u0192b\u0192g\u201a\u00c5\u201a\u00a0' +
-          '\u201a\u00e9\u0081B\u02c6\u00b3\u008fk\u0192A\u0192\u2039\u0192S' +
-          '\u0192\u0160\u0192Y\u0192\u20ac\u201a\u00c6\u201a\u00b5\u201a' +
-          '\u00c4Deflate\u201a\u00f0\u008d\u00cc\u2014p\u201a\u00b5\u201a' +
-          '\u00c4\u201a\u00a2\u201a\u00e9\u0081A\u02c6\u00b3\u008fk\u201a' +
-          '\u00c9\u201a\u00e6\u201a\u00e9\u2030\u00e6\u017d\u00bf\u201a\u00cc' +
-          '\u2014\u00f2\u2030\u00bb\u201a\u00cc\u201a\u00c8\u201a\u00a2\u2030' +
-          '\u00c2\u2039t\u02c6\u00b3\u008fk\u201a\u00cc\u2030\u00e6\u2018' +
-          '\u0153\u0192t\u0192@\u0192C\u0192\u2039\u0192t\u0192H\u0081[\u0192' +
-          '}\u0192b\u0192g\u201a\u00c5\u201a\u00a0\u201a\u00e9\u0081B\r\n');
+        assert.equal(tree.get("1").headers.get("Content-Type").get("charset"),
+          "Shift-JIS");
+        assert.equal(tree.get("1").headers.charset, "ISO-8859-1");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039");
+        assert.equal(tree.get("1").body, "Portable Network Graphics\u0081i" +
+          "\u0192|\u0081[\u0192^\u0192u\u0192\u2039\u0081E\u0192l\u0192b" +
+          "\u0192g\u0192\u008f\u0081[\u0192N\u0081E\u0192O\u0192\u2030\u0192t" +
+          "\u0192B\u0192b\u0192N\u0192X\u0081APNG\u0081j\u201a\u00cd\u0192R" +
+          "\u0192\u201c\u0192s\u0192\u2026\u0081[\u0192^\u201a\u00c5\u0192r" +
+          "\u0192b\u0192g\u0192}\u0192b\u0192v\u2030\u00e6\u2018\u0153\u201a" +
+          "\u00f0\u02c6\u00b5\u201a\u00a4\u0192t\u0192@\u0192C\u0192\u2039" +
+          "\u0192t\u0192H\u0081[\u0192}\u0192b\u0192g\u201a\u00c5\u201a\u00a0" +
+          "\u201a\u00e9\u0081B\u02c6\u00b3\u008fk\u0192A\u0192\u2039\u0192S" +
+          "\u0192\u0160\u0192Y\u0192\u20ac\u201a\u00c6\u201a\u00b5\u201a" +
+          "\u00c4Deflate\u201a\u00f0\u008d\u00cc\u2014p\u201a\u00b5\u201a" +
+          "\u00c4\u201a\u00a2\u201a\u00e9\u0081A\u02c6\u00b3\u008fk\u201a" +
+          "\u00c9\u201a\u00e6\u201a\u00e9\u2030\u00e6\u017d\u00bf\u201a\u00cc" +
+          "\u2014\u00f2\u2030\u00bb\u201a\u00cc\u201a\u00c8\u201a\u00a2\u2030" +
+          "\u00c2\u2039t\u02c6\u00b3\u008fk\u201a\u00cc\u2030\u00e6\u2018" +
+          "\u0153\u0192t\u0192@\u0192C\u0192\u2039\u0192t\u0192H\u0081[\u0192" +
+          "}\u0192b\u0192g\u201a\u00c5\u201a\u00a0\u201a\u00e9\u0081B\r\n");
         // ... but not image/png
-        assert.ok(!tree.get('2').headers.get('Content-Type').has('charset'));
-        assert.equal(tree.get('2').headers.charset, 'ISO-8859-1');
-        assert.equal(tree.get('2').headers.get('Content-Description'),
-          '\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039');
-        assert.equal(tree.get('2').headers.getRawHeader('Content-Description'),
-          '\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b');
-        var imageData = 'iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE' +
-          'QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA' +
-          'AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0' +
-          'klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS' +
-          '8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt' +
-          'lmUAAAAASUVORK5CYII=';
+        assert.ok(!tree.get("2").headers.get("Content-Type").has("charset"));
+        assert.equal(tree.get("2").headers.charset, "ISO-8859-1");
+        assert.equal(tree.get("2").headers.get("Content-Description"),
+          "\u0192P\u0192c\u0192@\u0192\u2039\u0192R\u0192A\u0192g\u0192\u2039");
+        assert.equal(tree.get("2").headers.getRawHeader("Content-Description"),
+          "\x83\x50\x83\x63\x83\x40\x83\x8b\x83\x52\x83\x41\x83\x67\x83\x8b");
+        var imageData = "iVBORw0KGgoAAAANSUhEUgAAAIAAAABECAIAAADGJao+AAAAwklE" +
+          "QVR4Xu3UgQbDMBRA0bc03f//b7N0VuqJEmwoc+KqNEkDh9b+2HuJu1KNO4f+AQCAAA" +
+          "AQAAACAEAAAAgAAAEAIAAABACAAAAQAAACAEAAAAgAAAEAIAAAANReamRLlPWYfNH0" +
+          "klxcPs+cP3NxWF+vi3lb7pa2R+vx6tHOtuN1O+a5lY3HzgM5ya/GM5N7ZjfPq7/5yS" +
+          "8IgAAAEAAAAgBAAAAIAAABACAAAAQAgAAAEAAAAgBAAAAIAAABACAAAIw322gDIPvt" +
+          "lmUAAAAASUVORK5CYII=";
         imageData = atob(imageData);
         var asArray = new Uint8Array(imageData.length);
         for (var i = 0; i < asArray.length; i++)
           asArray[i] = imageData.charCodeAt(i);
-        assert.deepEqual(tree.get('2').body, asArray);
+        assert.deepEqual(tree.get("2").body, asArray);
 
         // Touching the header charset should change the interpretation.
-        tree.get('1').headers.charset = 'Shift-JIS';
-        assert.equal(tree.get('1').headers.charset, 'Shift-JIS');
-        assert.equal(tree.get('1').headers.get('Content-Description'),
-          '\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb');
+        tree.get("1").headers.charset = "Shift-JIS";
+        assert.equal(tree.get("1").headers.charset, "Shift-JIS");
+        assert.equal(tree.get("1").headers.get("Content-Description"),
+          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb");
       });
     });
-    test('Charset conversion', function () {
-      return buildTree(read_file('charsets'), {
+    test("Charset conversion", function() {
+      return buildTree(read_file("charsets"), {
         strformat: "unicode",
-        bodyformat: "decode"
-      }).then(function (tree) {
+        bodyformat: "decode",
+      }).then(function(tree) {
         var numParts = 12;
-        for (var i = 1; i < numParts; i+= 2) {
+        for (let i = 1; i < numParts; i += 2) {
           assert.equal(tree.get("" + i).body, tree.get("" + (i + 1)).body);
         }
         assert.ok(!tree.has("" + (numParts + 1)));
       });
     });
   });
 });
-
 });
--- a/mailnews/mime/jsmime/test/test_structured_header_emitters.js
+++ b/mailnews/mime/jsmime/test/test_structured_header_emitters.js
@@ -1,94 +1,92 @@
 "use strict";
-define(function (require) {
-
-var assert = require('assert');
-var headeremitter = require('jsmime').headeremitter;
-var MockDate = require('test/mock_date');
+define(function(require) {
+var assert = require("assert");
+var headeremitter = require("jsmime").headeremitter;
+var MockDate = require("test/mock_date");
 
 function arrayTest(data, fn) {
-  fn.toString = function () {
+  fn.toString = function() {
     let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
+    text = text.replace(/data\[([0-9]*)\]/g, function(m, p) {
       return JSON.stringify(data[p]);
     });
     return text;
   };
   return test(JSON.stringify(data[0]), fn);
 }
 
 function testHeader(header, tests) {
-  suite(header, function () {
-    tests.forEach(function (data) {
-      arrayTest(data, function () {
+  suite(header, function() {
+    tests.forEach(function(data) {
+      arrayTest(data, function() {
         assert.deepEqual(headeremitter.emitStructuredHeader(header,
           data[0], {softMargin: 100, useASCII: true}),
-          (header + ": " + data[1]).trim() + '\r\n');
+          (header + ": " + data[1]).trim() + "\r\n");
       });
     });
   });
 }
 
-suite('Structured header emitters', function () {
+suite("Structured header emitters", function() {
   // Ad-hoc header tests
   // TODO: add structured encoder tests for Content-Type when it is added.
 
   testHeader("Content-Transfer-Encoding", [
     ["", ""],
     ["8bit", "8bit"],
-    ["invalid", "invalid"]
+    ["invalid", "invalid"],
   ]);
 
   // Non-ad-hoc header tests
-  let addressing_headers = ['From', 'To', 'Cc', 'Bcc', 'Sender', 'Reply-To',
-    'Resent-Bcc', 'Resent-To', 'Resent-From', 'Resent-Cc', 'Resent-Sender',
-    'Approved', 'Disposition-Notification-To', 'Delivered-To',
-    'Return-Receipt-To', 'Resent-Reply-To', 'Mail-Reply-To', 'Mail-Followup-To'
+  let addressing_headers = ["From", "To", "Cc", "Bcc", "Sender", "Reply-To",
+    "Resent-Bcc", "Resent-To", "Resent-From", "Resent-Cc", "Resent-Sender",
+    "Approved", "Disposition-Notification-To", "Delivered-To",
+    "Return-Receipt-To", "Resent-Reply-To", "Mail-Reply-To", "Mail-Followup-To",
   ];
   let address_tests = [
     [{name: "", email: ""}, ""],
     [{name: "John Doe", email: "john.doe@test.invalid"},
       "John Doe <john.doe@test.invalid>"],
     [[{name: "John Doe", email: "john.doe@test.invalid"}],
       "John Doe <john.doe@test.invalid>"],
     [{name: "undisclosed-recipients", group: []},
       "undisclosed-recipients: ;"],
   ];
-  addressing_headers.forEach(function (header) {
+  addressing_headers.forEach(function(header) {
     testHeader(header, address_tests);
   });
 
-  let date_headers = ['Date', 'Expires', 'Injection-Date', 'NNTP-Posting-Date',
-    'Resent-Date'];
+  let date_headers = ["Date", "Expires", "Injection-Date", "NNTP-Posting-Date",
+    "Resent-Date"];
   let date_tests = [
     [new MockDate("2012-09-06T08:08:21-0700"), "Thu, 6 Sep 2012 08:08:21 -0700"],
   ];
-  date_headers.forEach(function (header) {
+  date_headers.forEach(function(header) {
     testHeader(header, date_tests);
   });
 
-  let unstructured_headers = ['Comments', 'Content-Description', 'Keywords',
-    'Subject'];
+  let unstructured_headers = ["Comments", "Content-Description", "Keywords",
+    "Subject"];
   let unstructured_tests = [
     ["", ""],
     ["This is a subject", "This is a subject"],
     ["\u79c1\u306f\u4ef6\u540d\u5348\u524d",
       "=?UTF-8?B?56eB44Gv5Lu25ZCN5Y2I5YmN?="],
   ];
-  unstructured_headers.forEach(function (header) {
+  unstructured_headers.forEach(function(header) {
     testHeader(header, unstructured_tests);
   });
 
-  test('emitStructuredHeaders', function () {
+  test("emitStructuredHeaders", function() {
     let headers = new Map();
-    headers.set('From', [{name:'', email: 'bugzilla-daemon@mozilla.org'}]);
-    headers.set('subject', ['[Bug 939557] browsercomps.dll failed to build']);
-    headers.set('x-capitalization-test', ['should capitalize']);
+    headers.set("From", [{name: "", email: "bugzilla-daemon@mozilla.org"}]);
+    headers.set("subject", ["[Bug 939557] browsercomps.dll failed to build"]);
+    headers.set("x-capitalization-test", ["should capitalize"]);
     let str = headeremitter.emitStructuredHeaders(headers, {});
     assert.equal(str,
-      'From: bugzilla-daemon@mozilla.org\r\n' +
-      'Subject: [Bug 939557] browsercomps.dll failed to build\r\n'+
-      'X-Capitalization-Test: should capitalize\r\n');
+      "From: bugzilla-daemon@mozilla.org\r\n" +
+      "Subject: [Bug 939557] browsercomps.dll failed to build\r\n" +
+      "X-Capitalization-Test: should capitalize\r\n");
   });
 });
-
 });
--- a/mailnews/mime/jsmime/test/test_structured_headers.js
+++ b/mailnews/mime/jsmime/test/test_structured_headers.js
@@ -1,169 +1,167 @@
 "use strict";
-define(function (require) {
-
-var assert = require('assert');
-var headerparser = require('jsmime').headerparser;
+define(function(require) {
+var assert = require("assert");
+var headerparser = require("jsmime").headerparser;
 
 function smartDeepEqual(actual, expected) {
   assert.deepEqual(actual, expected);
   if (actual instanceof Map && expected instanceof Map) {
     assert.deepEqual(Array.from(actual.entries()),
       Array.from(expected.entries()));
   }
 }
 
 function arrayTest(data, fn) {
-  fn.toString = function () {
+  fn.toString = function() {
     let text = Function.prototype.toString.call(this);
-    text = text.replace(/data\[([0-9]*)\]/g, function (m, p) {
+    text = text.replace(/data\[([0-9]*)\]/g, function(m, p) {
       return JSON.stringify(data[p]);
     });
     return text;
   };
   return test(data[0], fn);
 }
 
 function testHeader(header, tests) {
-  suite(header, function () {
-    tests.forEach(function (data) {
-      arrayTest(data, function () {
+  suite(header, function() {
+    tests.forEach(function(data) {
+      arrayTest(data, function() {
         smartDeepEqual(headerparser.parseStructuredHeader(header,
           data[0]), data[1]);
       });
     });
   });
 }
 
 function makeCT(media, sub, params) {
   var object = new Map();
   object.mediatype = media;
   object.subtype = sub;
   object.type = media + "/" + sub;
   for (let k in params)
     object.set(k, params[k]);
   return object;
 }
-suite('Structured headers', function () {
+suite("Structured headers", function() {
   // Ad-hoc header tests
-  testHeader('Content-Type', [
-    ['text/plain', makeCT("text", "plain", {})],
-    ['text/html', makeCT("text", "html", {})],
+  testHeader("Content-Type", [
+    ["text/plain", makeCT("text", "plain", {})],
+    ["text/html", makeCT("text", "html", {})],
     ['text/plain; charset="UTF-8"',
       makeCT("text", "plain", {charset: "UTF-8"})],
-    ['text/', makeCT("text", "", {})],
-    ['text', makeCT("text", "plain", {})],
-    ['image/', makeCT("image", "", {})],
-    ['image', makeCT("text", "plain", {})],
-    ['hacker/x-mailnews', makeCT("hacker", "x-mailnews", {})],
-    ['hacker/x-mailnews;', makeCT("hacker", "x-mailnews", {})],
-    ['HACKER/X-MAILNEWS', makeCT("hacker", "x-mailnews", {})],
-    ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+    ["text/", makeCT("text", "", {})],
+    ["text", makeCT("text", "plain", {})],
+    ["image/", makeCT("image", "", {})],
+    ["image", makeCT("text", "plain", {})],
+    ["hacker/x-mailnews", makeCT("hacker", "x-mailnews", {})],
+    ["hacker/x-mailnews;", makeCT("hacker", "x-mailnews", {})],
+    ["HACKER/X-MAILNEWS", makeCT("hacker", "x-mailnews", {})],
+    ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
       makeCT("application",
       "vnd.openxmlformats-officedocument.spreadsheetml.sheet", {})],
-    ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;\r' +
+    ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;\r" +
       '\n name="Presentation.pptx"',
       makeCT("application",
       "vnd.openxmlformats-officedocument.spreadsheetml.sheet",
       {name: "Presentation.pptx"})],
-    ['', makeCT("text", "plain", {})],
-    ['                                        ', makeCT("text", "plain", {})],
-    ['text/plain; c', makeCT("text", "plain", {})],
-    ['text/plain; charset=', makeCT("text", "plain", {charset: ""})],
+    ["", makeCT("text", "plain", {})],
+    ["                                        ", makeCT("text", "plain", {})],
+    ["text/plain; c", makeCT("text", "plain", {})],
+    ["text/plain; charset=", makeCT("text", "plain", {charset: ""})],
     ['text/plain; charset="', makeCT("text", "plain", {charset: ""})],
-    ['text\\/enriched', makeCT("text\\", "enriched", {})],
+    ["text\\/enriched", makeCT("text\\", "enriched", {})],
     ['multipart/mixed ";" wtf=stupid', makeCT("multipart", "mixed", {})],
-    ['multipart/mixed; wtf=stupid',
+    ["multipart/mixed; wtf=stupid",
       makeCT("multipart", "mixed", {wtf: "stupid"})],
-    ['text/plain; CHARSET=Big5', makeCT("text", "plain", {charset: "Big5"})],
+    ["text/plain; CHARSET=Big5", makeCT("text", "plain", {charset: "Big5"})],
     ['text/html; CHARSET="Big5"', makeCT("text", "html", {charset: "Big5"})],
     ['text/html; CHARSET="Big5', makeCT("text", "html", {charset: "Big5"})],
-    [['text/html', 'multipart/mixed'], makeCT("text", "html", {})],
+    [["text/html", "multipart/mixed"], makeCT("text", "html", {})],
   ]);
-  testHeader('Content-Transfer-Encoding', [
-    ['', ''],
-    ['8bit', '8bit'],
-    ['8BIT', '8bit'],
-    ['QuOtEd-PrInTaBlE', 'quoted-printable'],
-    ['Base64', 'base64'],
-    ['7bit', '7bit'],
-    [['7bit', '8bit'], '7bit'],
-    ['x-uuencode', 'x-uuencode']
+  testHeader("Content-Transfer-Encoding", [
+    ["", ""],
+    ["8bit", "8bit"],
+    ["8BIT", "8bit"],
+    ["QuOtEd-PrInTaBlE", "quoted-printable"],
+    ["Base64", "base64"],
+    ["7bit", "7bit"],
+    [["7bit", "8bit"], "7bit"],
+    ["x-uuencode", "x-uuencode"],
   ]);
 
   // Non-ad-hoc header tests
-  let addressing_headers = ['From', 'To', 'Cc', 'Bcc', 'Sender', 'Reply-To',
-    'Resent-Bcc', 'Resent-To', 'Resent-From', 'Resent-Cc', 'Resent-Sender',
-    'Approved', 'Disposition-Notification-To', 'Delivered-To',
-    'Return-Receipt-To', 'Resent-Reply-To', 'Mail-Reply-To', 'Mail-Followup-To'
+  let addressing_headers = ["From", "To", "Cc", "Bcc", "Sender", "Reply-To",
+    "Resent-Bcc", "Resent-To", "Resent-From", "Resent-Cc", "Resent-Sender",
+    "Approved", "Disposition-Notification-To", "Delivered-To",
+    "Return-Receipt-To", "Resent-Reply-To", "Mail-Reply-To", "Mail-Followup-To",
   ];
   let address_tests = [
     ["", []],
     ["a@example.invalid", [{name: "", email: "a@example.invalid"}]],
     ["John Doe <a@example.invalid>",
       [{name: "John Doe", email: "a@example.invalid"}]],
     ["John Doe <A@EXAMPLE.INVALID>",
       [{name: "John Doe", email: "A@EXAMPLE.INVALID"}]],
     ["=?UTF-8?B?5bGx55Sw5aSq6YOO?= <a@example.invalid>",
       [{name: "\u5c71\u7530\u592a\u90ce", email: "a@example.invalid"}]],
     ["undisclosed-recipients:;", [{name: "undisclosed-recipients", group: []}]],
     ["world: a@example.invalid, b@example.invalid;",
       [{name: "world", group: [
         {name: "", email: "a@example.invalid"},
-        {name: "", email: "b@example.invalid"}
+        {name: "", email: "b@example.invalid"},
       ]}]],
     // TODO when we support IDN:
     // This should be \u4f8b.invalid instead (Japanese kanji for "example")
     ["\u5c71\u7530\u592a\u90ce <a@xn--fsq.invalid>",
       [{name: "\u5c71\u7530\u592a\u90ce", email: "a@xn--fsq.invalid"}]],
     ["\u5c71\u7530\u592a\u90ce <a@\u4f8b.invalid>",
       [{name: "\u5c71\u7530\u592a\u90ce", email: "a@\u4f8b.invalid"}]],
     ["\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb@\u4f8b.invalid",
       [{name: "", email:
          "\u30b1\u30c4\u30a1\u30eb\u30b3\u30a2\u30c8\u30eb@\u4f8b.invalid"}]],
     [["a@example.invalid", "b@example.invalid"],
       [{name: "", email: "a@example.invalid"},
        {name: "", email: "b@example.invalid"}]],
   ];
-  addressing_headers.forEach(function (header) {
+  addressing_headers.forEach(function(header) {
     testHeader(header, address_tests);
   });
 
-  let date_headers = ['Date', 'Expires', 'Injection-Date', 'NNTP-Posting-Date',
-    'Resent-Date'];
+  let date_headers = ["Date", "Expires", "Injection-Date", "NNTP-Posting-Date",
+    "Resent-Date"];
   let date_tests = [
     ["Thu, 06 Sep 2012 08:08:21 -0700", new Date("2012-09-06T08:08:21-0700")],
     ["This is so not a date", new Date(NaN)],
   ];
-  date_headers.forEach(function (header) {
+  date_headers.forEach(function(header) {
     testHeader(header, date_tests);
   });
 
-  let multiple_unstructured_headers = ['In-Reply-To', 'References'];
+  let multiple_unstructured_headers = ["In-Reply-To", "References"];
   let multiple_unstructured_tests = [
     ["<asdasdasd@asdasdasd.com>", "<asdasdasd@asdasdasd.com>"],
     ["<asd@asd.com> <asdf@asdf.com>", "<asd@asd.com> <asdf@asdf.com>"],
 
     // This test is needed for clients sending non-compliant headers, see bug 1154521
     ["<asd@asd.com>,<asdf@asdf.com>,<asdfg@asdfg.com>", "<asd@asd.com> <asdf@asdf.com> <asdfg@asdfg.com>"],
     // Test for bug 1197686
     ["<asd@asd.com><asdf@asdf.com><asdfg@asdfg.com>", "<asd@asd.com> <asdf@asdf.com> <asdfg@asdfg.com>"],
   ];
-  multiple_unstructured_headers.forEach(function (header) {
+  multiple_unstructured_headers.forEach(function(header) {
     testHeader(header, multiple_unstructured_tests);
   });
 
-  let unstructured_headers = ['Comments', 'Content-Description', 'Keywords',
-    'Subject'];
+  let unstructured_headers = ["Comments", "Content-Description", "Keywords",
+    "Subject"];
   let unstructured_tests = [
     ["", ""],
     ["This is a subject", "This is a subject"],
     [["Subject 1", "Subject 2"], "Subject 1"],
     ["=?UTF-8?B?56eB44Gv5Lu25ZCN5Y2I5YmN?=",
       "\u79c1\u306f\u4ef6\u540d\u5348\u524d"],
   ];
-  unstructured_headers.forEach(function (header) {
+  unstructured_headers.forEach(function(header) {
     testHeader(header, unstructured_tests);
   });
 });
-
 });
--- a/mailnews/mime/src/extraMimeParsers.jsm
+++ b/mailnews/mime/src/extraMimeParsers.jsm
@@ -1,25 +1,27 @@
 /* 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/. */
 
+/* globals jsmime */
+
 function parseNewsgroups(headers) {
   let ng = [];
   for (let header of headers) {
     ng = ng.concat(header.split(/\s*,\s*/));
   }
   return ng;
 }
 
 function emitNewsgroups(groups) {
   // Don't encode the newsgroups names in RFC 2047...
-  if (groups.length == 1)
+  if (groups.length == 1) {
     this.addText(groups[0], false);
-  else {
+  } else {
     this.addText(groups[0], false);
     for (let i = 1; i < groups.length; i++) {
       this.addText(",", false); // only comma, no space!
       this.addText(groups[i], false);
     }
   }
 }
 
--- a/mailnews/mime/src/jsmime.jsm
+++ b/mailnews/mime/src/jsmime.jsm
@@ -12,55 +12,56 @@ const {Services} = ChromeUtils.import("r
 
 // Load the core MIME parser. Since it doesn't define EXPORTED_SYMBOLS, we must
 // use the subscript loader instead.
 Services.scriptloader.loadSubScript("resource:///modules/jsmime/jsmime.js");
 
 var EXPORTED_SYMBOLS = ["jsmime"];
 
 function bytesToString(buffer) {
-  var string = '';
+  var string = "";
   for (var i = 0; i < buffer.length; i++)
     string += String.fromCharCode(buffer[i]);
   return string;
 }
 
 // Our UTF-7 decoder.
 function UTF7TextDecoder(options = {}, manager) {
   this.manager = manager;
   this.collectInput = "";
 }
 UTF7TextDecoder.prototype = {
   // Since the constructor checked, this will only be called for UTF-7.
-  decode: function (input, options = {}) {
-    let more = 'stream' in options ? options.stream : false;
+  decode(input, options = {}) {
+    let more = "stream" in options ? options.stream : false;
     // There are cases where this is called without input.
     if (!input)
       return "";
     this.collectInput += bytesToString(input);
     if (more)
       return "";
     return this.manager.utf7ToUnicode(this.collectInput);
   },
 };
 
+/* exported MimeTextDecoder */
 function MimeTextDecoder(charset, options) {
   let manager = Cc["@mozilla.org/charset-converter-manager;1"]
                   .createInstance(Ci.nsICharsetConverterManager);
   // The following will throw if the charset is unknown.
   let newCharset = manager.getCharsetAlias(charset);
   if (newCharset.toLowerCase() == "utf-7")
     return new UTF7TextDecoder(options, manager);
   return new TextDecoder(newCharset, options);
 }
 
 
 // The following code loads custom MIME encoders.
 var CATEGORY_NAME = "custom-mime-encoder";
-Services.obs.addObserver(function (subject, topic, data) {
+Services.obs.addObserver(function(subject, topic, data) {
   subject = subject.QueryInterface(Ci.nsISupportsCString)
                    .data;
   if (data == CATEGORY_NAME) {
     let url = Services.catMan.getCategoryEntry(CATEGORY_NAME, subject);
     Services.scriptloader.loadSubScript(url, {}, "UTF-8");
   }
 }, "xpcom-category-entry-added");
 
--- a/mailnews/mime/src/mimeJSComponents.js
+++ b/mailnews/mime/src/mimeJSComponents.js
@@ -3,125 +3,124 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var {jsmime} = ChromeUtils.import("resource:///modules/jsmime.jsm");
 var {MimeParser} = ChromeUtils.import("resource:///modules/mimeParser.jsm");
 var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function HeaderHandler() {
   this.value = "";
-  this.deliverData = function (str) { this.value += str; };
-  this.deliverEOF = function () {};
+  this.deliverData = function(str) { this.value += str; };
+  this.deliverEOF = function() {};
 }
 
 function StringEnumerator(iterator) {
   this._iterator = iterator;
   this._next = undefined;
 }
 StringEnumerator.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIUTF8StringEnumerator]),
-  [Symbol.iterator]: function () {
+  [Symbol.iterator]() {
     return this._iterator;
   },
-  _setNext: function () {
+  _setNext() {
     if (this._next !== undefined)
       return;
     this._next = this._iterator.next();
   },
-  hasMore: function () {
+  hasMore() {
     this._setNext();
     return !this._next.done;
   },
-  getNext: function () {
+  getNext() {
     this._setNext();
     let result = this._next;
     this._next = undefined;
     if (result.done)
       throw Cr.NS_ERROR_UNEXPECTED;
     return result.value;
-  }
+  },
 };
 
 /**
  * If we get XPConnect-wrapped objects for msgIAddressObjects, we will have
  * properties defined for 'group' that throws off jsmime. This function converts
  * the addresses into the form that jsmime expects.
  */
 function fixXpconnectAddresses(addrs) {
   return addrs.map((addr) => {
     // This is ideally !addr.group, but that causes a JS strict warning, if
     // group is not in addr, since that's enabled in all chrome code now.
-    if (!('group' in addr) || addr.group === undefined || addr.group === null) {
+    if (!("group" in addr) || addr.group === undefined || addr.group === null) {
       return MimeAddressParser.prototype.makeMailboxObject(addr.name,
         addr.email);
-    } else {
-      return MimeAddressParser.prototype.makeGroupObject(addr.name,
-        fixXpconnectAddresses(addr.group));
     }
+    return MimeAddressParser.prototype.makeGroupObject(addr.name,
+      fixXpconnectAddresses(addr.group));
   });
 }
 
 /**
  * This is a base handler for supporting msgIStructuredHeaders, since we have
  * two implementations that need the readable aspects of the interface.
  */
 function MimeStructuredHeaders() {
 }
 MimeStructuredHeaders.prototype = {
-  getHeader: function (aHeaderName) {
+  getHeader(aHeaderName) {
     let name = aHeaderName.toLowerCase();
     return this._headers.get(name);
   },
 
-  hasHeader: function (aHeaderName) {
+  hasHeader(aHeaderName) {
     return this._headers.has(aHeaderName.toLowerCase());
   },
 
-  getUnstructuredHeader: function (aHeaderName) {
+  getUnstructuredHeader(aHeaderName) {
     let result = this.getHeader(aHeaderName);
     if (result === undefined || typeof result == "string")
       return result;
     throw Cr.NS_ERROR_ILLEGAL_VALUE;
   },
 
-  getAddressingHeader: function (aHeaderName, aPreserveGroups, count) {
+  getAddressingHeader(aHeaderName, aPreserveGroups, count) {
     let addrs = this.getHeader(aHeaderName);
     if (addrs === undefined) {
       addrs = [];
     } else if (!Array.isArray(addrs)) {
       throw Cr.NS_ERROR_ILLEGAL_VALUE;
     }
     return fixArray(addrs, aPreserveGroups, count);
   },
 
-  getRawHeader: function (aHeaderName) {
+  getRawHeader(aHeaderName) {
     let result = this.getHeader(aHeaderName);
     if (result === undefined)
       return result;
 
     let value = jsmime.headeremitter.emitStructuredHeader(aHeaderName,
       result, {});
     // Strip off the header name and trailing whitespace before returning...
     value = value.substring(aHeaderName.length + 2).trim();
     // ... as well as embedded newlines.
-    value = value.replace(/\r\n/g, '');
+    value = value.replace(/\r\n/g, "");
     return value;
   },
 
   get headerNames() {
     return new StringEnumerator(this._headers.keys());
   },
 
-  buildMimeText: function () {
+  buildMimeText() {
     if (this._headers.size == 0) {
       return "";
     }
     let handler = new HeaderHandler();
     let emitter = jsmime.headeremitter.makeStreamingEmitter(handler, {
-      useASCII: true
+      useASCII: true,
     });
     for (let [value, header] of this._headers) {
       emitter.addStructuredHeader(value, header);
     }
     emitter.finish();
     return handler.value;
   },
 };
@@ -132,115 +131,115 @@ function MimeHeaders() {
 MimeHeaders.prototype = {
   __proto__: MimeStructuredHeaders.prototype,
   classDescription: "Mime headers implementation",
   classID: Components.ID("d1258011-f391-44fd-992e-c6f4b461a42f"),
   contractID: "@mozilla.org/messenger/mimeheaders;1",
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMimeHeaders,
     Ci.msgIStructuredHeaders]),
 
-  initialize: function MimeHeaders_initialize(allHeaders) {
+  initialize(allHeaders) {
     this._headers = MimeParser.extractHeaders(allHeaders);
   },
 
-  extractHeader: function MimeHeaders_extractHeader(header, getAll) {
+  extractHeader(header, getAll) {
     if (!this._headers)
       throw Cr.NS_ERROR_NOT_INITIALIZED;
     // Canonicalized to lower-case form
     header = header.toLowerCase();
     if (!this._headers.has(header))
       return null;
     var values = this._headers.getRawHeader(header);
     if (getAll)
       return values.join(",\r\n\t");
-    else
-      return values[0];
+    return values[0];
   },
 
   get allHeaders() {
     return this._headers.rawHeaderText;
-  }
+  },
 };
 
 function MimeWritableStructuredHeaders() {
   this._headers = new Map();
 }
 MimeWritableStructuredHeaders.prototype = {
   __proto__: MimeStructuredHeaders.prototype,
   classID: Components.ID("c560806a-425f-4f0f-bf69-397c58c599a7"),
   QueryInterface: ChromeUtils.generateQI([
     Ci.msgIStructuredHeaders,
     Ci.msgIWritableStructuredHeaders]),
 
-  setHeader: function (aHeaderName, aValue) {
+  setHeader(aHeaderName, aValue) {
     this._headers.set(aHeaderName.toLowerCase(), aValue);
   },
 
-  deleteHeader: function (aHeaderName) {
+  deleteHeader(aHeaderName) {
     this._headers.delete(aHeaderName.toLowerCase());
   },
 
-  addAllHeaders: function (aHeaders) {
+  addAllHeaders(aHeaders) {
     for (let header of aHeaders.headerNames) {
       this.setHeader(header, aHeaders.getHeader(header));
     }
   },
 
-  setUnstructuredHeader: function (aHeaderName, aValue) {
+  setUnstructuredHeader(aHeaderName, aValue) {
     this.setHeader(aHeaderName, aValue);
   },
 
-  setAddressingHeader: function (aHeaderName, aAddresses, aCount) {
+  setAddressingHeader(aHeaderName, aAddresses, aCount) {
     this.setHeader(aHeaderName, fixXpconnectAddresses(aAddresses));
   },
 
-  setRawHeader: function (aHeaderName, aValue, aCharset) {
+  setRawHeader(aHeaderName, aValue, aCharset) {
     aValue = jsmime.headerparser.convert8BitHeader(aValue, aCharset);
     try {
       this.setHeader(aHeaderName,
         jsmime.headerparser.parseStructuredHeader(aHeaderName, aValue));
     } catch (e) {
       // This means we don't have a structured encoder. Just assume it's a raw
       // string value then.
       this.setHeader(aHeaderName, aValue);
     }
-  }
+  },
 };
 
 // These are prototypes for nsIMsgHeaderParser implementation
 var Mailbox = {
-  toString: function () {
+  toString() {
     return this.name ? this.name + " <" + this.email + ">" : this.email;
-  }
+  },
 };
 
 var EmailGroup = {
-  toString: function () {
+  toString() {
     return this.name + ": " + this.group.map(x => x.toString()).join(", ");
-  }
+  },
 };
 
 // A helper method for parse*Header that takes into account the desire to
 // preserve group and also tweaks the output to support the prototypes for the
 // XPIDL output.
 function fixArray(addresses, preserveGroups, count) {
   function resetPrototype(obj, prototype) {
     let prototyped = Object.create(prototype);
     for (let key of Object.getOwnPropertyNames(obj)) {
       if (typeof obj[key] == "string") {
-        prototyped[key] = obj[key].replace(/\x00/g, '');
+        // eslint-disable-next-line no-control-regex
+        prototyped[key] = obj[key].replace(/\x00/g, "");
       } else {
         prototyped[key] = obj[key];
       }
     }
     return prototyped;
   }
   let outputArray = [];
   for (let element of addresses) {
-    if ('group' in element) {
+    if ("group" in element) {
       // Fix up the prototypes of the group and the list members
       element = resetPrototype(element, EmailGroup);
       element.group = element.group.map(e => resetPrototype(e, Mailbox));
 
       // Add to the output array
       if (preserveGroups)
         outputArray.push(element);
       else
@@ -257,75 +256,75 @@ function fixArray(addresses, preserveGro
 }
 
 function MimeAddressParser() {
 }
 MimeAddressParser.prototype = {
   classID: Components.ID("96bd8769-2d0e-4440-963d-22b97fb3ba77"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgHeaderParser]),
 
-  parseEncodedHeader: function (aHeader, aCharset, aPreserveGroups, count) {
+  parseEncodedHeader(aHeader, aCharset, aPreserveGroups, count) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(aHeader,
       MimeParser.HEADER_ADDRESS | MimeParser.HEADER_OPTION_ALL_I18N, aCharset);
     return fixArray(value, aPreserveGroups, count);
   },
-  parseEncodedHeaderW: function (aHeader, count) {
+  parseEncodedHeaderW(aHeader, count) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(aHeader,
       MimeParser.HEADER_ADDRESS |
       MimeParser.HEADER_OPTION_DECODE_2231 |
       MimeParser.HEADER_OPTION_DECODE_2047,
       undefined);
     return fixArray(value, false, count);
   },
-  parseDecodedHeader: function (aHeader, aPreserveGroups, count) {
+  parseDecodedHeader(aHeader, aPreserveGroups, count) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(aHeader, MimeParser.HEADER_ADDRESS);
     return fixArray(value, aPreserveGroups, count);
   },
 
-  makeMimeHeader: function (addresses, length) {
+  makeMimeHeader(addresses, length) {
     addresses = fixXpconnectAddresses(addresses);
     // Don't output any necessary continuations, so make line length as large as
     // possible first.
     let options = {
       softMargin: 900,
       hardMargin: 900,
-      useASCII: false // We don't want RFC 2047 encoding here.
+      useASCII: false, // We don't want RFC 2047 encoding here.
     };
     let handler = new HeaderHandler();
     let emitter = new jsmime.headeremitter.makeStreamingEmitter(handler,
       options);
     emitter.addAddresses(addresses);
     emitter.finish(true);
-    return handler.value.replace(/\r\n( |$)/g, '');
+    return handler.value.replace(/\r\n( |$)/g, "");
   },
 
-  extractFirstName: function (aHeader) {
+  extractFirstName(aHeader) {
     let addresses = this.parseDecodedHeader(aHeader, false);
     return (addresses.length > 0) ? (addresses[0].name || addresses[0].email) : "";
   },
 
-  removeDuplicateAddresses: function (aAddrs, aOtherAddrs) {
+  removeDuplicateAddresses(aAddrs, aOtherAddrs) {
     // This is actually a rather complicated algorithm, especially if we want to
     // preserve group structure. Basically, we use a set to identify which
     // headers we have seen and therefore want to remove. To work in several
     // various forms of edge cases, we need to normalize the entries in that
     // structure.
     function normalize(email) {
       // XXX: This algorithm doesn't work with IDN yet. It looks like we have to
       // convert from IDN then do lower case, but I haven't confirmed yet.
       return email.toLowerCase();
     }
 
     // The filtration function, which removes email addresses that are
     // duplicates of those we have already seen.
     function filterAccept(e) {
-      if ('email' in e) {
+      if ("email" in e) {
         // If we've seen the address, don't keep this one; otherwise, add it to
         // the list.
         let key = normalize(e.email);
         if (allAddresses.has(key))
           return false;
         allAddresses.add(key);
       } else {
         // Groups -> filter out all the member addresses.
@@ -340,68 +339,67 @@ MimeAddressParser.prototype = {
       allAddresses.add(normalize(element.email));
     }
 
     // The actual data to filter
     let filtered = this.parseDecodedHeader(aAddrs, true).filter(filterAccept);
     return this.makeMimeHeader(filtered);
   },
 
-  makeMailboxObject: function (aName, aEmail) {
+  makeMailboxObject(aName, aEmail) {
     let object = Object.create(Mailbox);
     object.name = aName;
     object.email = aEmail ? aEmail.trim() : aEmail;
     return object;
   },
 
-  makeGroupObject: function (aName, aMembers) {
+  makeGroupObject(aName, aMembers) {
     let object = Object.create(EmailGroup);
     object.name = aName;
     object.group = aMembers;
     return object;
   },
 
-  makeFromDisplayAddress: function (aDisplay, count) {
+  makeFromDisplayAddress(aDisplay, count) {
     // The basic idea is to split on every comma, so long as there is a
     // preceding @.
     let output = [];
     while (aDisplay.length) {
-      let at = aDisplay.indexOf('@');
-      let comma = aDisplay.indexOf(',', at + 1);
+      let at = aDisplay.indexOf("@");
+      let comma = aDisplay.indexOf(",", at + 1);
       let addr;
       if (comma > 0) {
         addr = aDisplay.substr(0, comma);
         aDisplay = aDisplay.substr(comma + 1);
       } else {
         addr = aDisplay;
         aDisplay = "";
       }
       output.push(this._makeSingleAddress(addr.trimLeft()));
     }
     if (count)
       count.value = output.length;
     return output;
   },
 
-  /// Construct a single email address from a name <local@domain> token.
-  _makeSingleAddress: function (aDisplayName) {
-    if (aDisplayName.includes('<')) {
-      let lbracket = aDisplayName.lastIndexOf('<');
-      let rbracket = aDisplayName.lastIndexOf('>');
+  // Construct a single email address from a name <local@domain> token.
+  _makeSingleAddress(aDisplayName) {
+    if (aDisplayName.includes("<")) {
+      let lbracket = aDisplayName.lastIndexOf("<");
+      let rbracket = aDisplayName.lastIndexOf(">");
       return this.makeMailboxObject(
-        lbracket == 0 ? '' : aDisplayName.slice(0, lbracket).trim(),
+        lbracket == 0 ? "" : aDisplayName.slice(0, lbracket).trim(),
         aDisplayName.slice(lbracket + 1, rbracket));
-    } else {
-      return this.makeMailboxObject('', aDisplayName);
     }
+    return this.makeMailboxObject("", aDisplayName);
   },
 
   // What follows is the deprecated API that will be removed shortly.
 
-  parseHeadersWithArray: function (aHeader, aAddrs, aNames, aFullNames) {
+  parseHeadersWithArray(aHeader, aAddrs, aNames, aFullNames) {
     let addrs = [], names = [], fullNames = [];
     let allAddresses = this.parseEncodedHeader(aHeader, undefined, false);
 
     // Don't index the dummy empty address.
     if (aHeader.trim() == "")
       allAddresses = [];
     for (let address of allAddresses) {
       addrs.push(address.email);
@@ -410,39 +408,39 @@ MimeAddressParser.prototype = {
     }
 
     aAddrs.value = addrs;
     aNames.value = names;
     aFullNames.value = fullNames;
     return allAddresses.length;
   },
 
-  extractHeaderAddressMailboxes: function (aLine) {
+  extractHeaderAddressMailboxes(aLine) {
     return this.parseDecodedHeader(aLine).map(addr => addr.email).join(", ");
   },
 
-  makeMimeAddress: function (aName, aEmail) {
+  makeMimeAddress(aName, aEmail) {
     let object = this.makeMailboxObject(aName, aEmail);
     return this.makeMimeHeader([object]);
   },
 };
 
 function MimeConverter() {
 }
 MimeConverter.prototype = {
   classID: Components.ID("93f8c049-80ed-4dda-9000-94ad8daba44c"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMimeConverter]),
 
-  encodeMimePartIIStr_UTF8: function (aHeader, aStructured,
+  encodeMimePartIIStr_UTF8(aHeader, aStructured,
       aFieldNameLen, aLineLength) {
     // Compute the encoding options. The way our API is structured in this
     // method is really horrendous and does not align with the way that JSMime
     // handles it. Instead, we'll need to create a fake header to take into
     // account the aFieldNameLen parameter.
-    let fakeHeader = '-'.repeat(aFieldNameLen);
+    let fakeHeader = "-".repeat(aFieldNameLen);
     let options = {
       softMargin: aLineLength,
       useASCII: true,
     };
     let handler = new HeaderHandler();
     let emitter = new jsmime.headeremitter.makeStreamingEmitter(handler,
       options);
 
@@ -468,29 +466,29 @@ MimeConverter.prototype = {
     // Compute the output. We need to strip off the fake prefix added earlier
     // and the extra CRLF at the end.
     emitter.finish(true);
     let value = handler.value;
     value = value.replace(new RegExp(fakeHeader + ":\\s*"), "");
     return value.substring(0, value.length - 2);
   },
 
-  decodeMimeHeader: function (aHeader, aDefaultCharset, aOverride, aUnfold) {
+  decodeMimeHeader(aHeader, aDefaultCharset, aOverride, aUnfold) {
     let value = MimeParser.parseHeaderField(aHeader,
       MimeParser.HEADER_UNSTRUCTURED | MimeParser.HEADER_OPTION_ALL_I18N,
       aDefaultCharset);
     if (aUnfold) {
-      value = value.replace(/[\r\n]\t/g, ' ')
-                   .replace(/[\r\n]/g, '');
+      value = value.replace(/[\r\n]\t/g, " ")
+                   .replace(/[\r\n]/g, "");
     }
     return value;
   },
 
   // This is identical to the above, except for factors that are handled by the
   // xpconnect conversion process
-  decodeMimeHeaderToUTF8: function (...aArgs) {
+  decodeMimeHeaderToUTF8(...aArgs) {
     return this.decodeMimeHeader(...aArgs);
   },
 };
 
 var components = [MimeHeaders, MimeWritableStructuredHeaders, MimeAddressParser,
   MimeConverter];
 var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/mailnews/mime/src/mimeParser.jsm
+++ b/mailnews/mime/src/mimeParser.jsm
@@ -1,38 +1,36 @@
 /* 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/. */
 // vim:set ts=2 sw=2 sts=2 et ft=javascript:
 
-var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {jsmime} = ChromeUtils.import("resource:///modules/jsmime.jsm");
 
 var EXPORTED_SYMBOLS = ["MimeParser"];
 
 // Emitter helpers, for internal functions later on.
 var ExtractHeadersEmitter = {
-  startPart: function (partNum, headers) {
-    if (partNum == '') {
+  startPart(partNum, headers) {
+    if (partNum == "") {
       this.headers = headers;
     }
-  }
+  },
 };
 
 var ExtractHeadersAndBodyEmitter = {
-  body: '',
+  body: "",
   startPart: ExtractHeadersEmitter.startPart,
-  deliverPartData: function (partNum, data) {
-    if (partNum == '')
+  deliverPartData(partNum, data) {
+    if (partNum == "")
       this.body += data;
-  }
+  },
 };
 
-/// Sets appropriate default options for chrome-privileged environments
+// Sets appropriate default options for chrome-privileged environments
 function setDefaultParserOptions(opts) {
   if (!("onerror" in opts)) {
     opts.onerror = Cu.reportError;
   }
 }
 
 var MimeParser = {
   /**
@@ -42,17 +40,17 @@ var MimeParser = {
    * closed upon completion. Both blocking and nonblocking streams are
    * supported by this implementation, but it is still guaranteed that the first
    * callback will not happen before this method returns.
    *
    * @param input   An input stream of text to parse.
    * @param emitter The emitter to receive callbacks on.
    * @param opts    A set of options for the parser.
    */
-  parseAsync: function MimeParser_parseAsync(input, emitter, opts) {
+  parseAsync(input, emitter, opts) {
     // Normalize the input into an input stream.
     if (!(input instanceof Ci.nsIInputStream)) {
       throw new Error("input is not a recognizable type!");
     }
 
     // We need a pump for the listener
     var pump = Cc["@mozilla.org/network/input-stream-pump;1"]
                  .createInstance(Ci.nsIInputStreamPump);
@@ -69,112 +67,110 @@ var MimeParser = {
    *
    * The input is a string that is immediately parsed, calling all functions on
    * the emitter before this function returns.
    *
    * @param input   A string or input stream of text to parse.
    * @param emitter The emitter to receive callbacks on.
    * @param opts    A set of options for the parser.
    */
-  parseSync: function MimeParser_parseSync(input, emitter, opts) {
+  parseSync(input, emitter, opts) {
     // We only support string parsing if we are trying to do this parse
     // synchronously.
     if (typeof input != "string") {
       throw new Error("input is not a recognizable type!");
     }
     setDefaultParserOptions(opts);
     var parser = new jsmime.MimeParser(emitter, opts);
     parser.deliverData(input);
     parser.deliverEOF();
-    return;
   },
 
   /**
    * Returns a stream listener that feeds data into a parser.
    *
    * In addition to the functions on the emitter that the parser may use, the
    * generated stream listener will also make calls to onStartRequest and
    * onStopRequest on the emitter (if they exist).
    *
    * @param emitter The emitter to receive callbacks on.
    * @param opts    A set of options for the parser.
    */
-  makeStreamListenerParser: function MimeParser_makeSLParser(emitter, opts) {
+  makeStreamListenerParser(emitter, opts) {
     var StreamListener = {
-      onStartRequest: function SLP_onStartRequest(aRequest) {
+      onStartRequest(aRequest) {
         try {
           if ("onStartRequest" in emitter)
             emitter.onStartRequest(aRequest);
         } finally {
           this._parser.resetParser();
         }
       },
-      onStopRequest: function SLP_onStopRequest(aRequest, aStatus) {
+      onStopRequest(aRequest, aStatus) {
         this._parser.deliverEOF();
         if ("onStopRequest" in emitter)
           emitter.onStopRequest(aRequest, aStatus);
       },
-      onDataAvailable: function SLP_onData(aRequest, aStream,
-                                           aOffset, aCount) {
+      onDataAvailable(aRequest, aStream, aOffset, aCount) {
         var scriptIn = Cc["@mozilla.org/scriptableinputstream;1"]
                          .createInstance(Ci.nsIScriptableInputStream);
         scriptIn.init(aStream);
         // Use readBytes instead of read to handle embedded NULs properly.
         this._parser.deliverData(scriptIn.readBytes(aCount));
       },
       QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener,
-        Ci.nsIRequestObserver])
+        Ci.nsIRequestObserver]),
     };
     setDefaultParserOptions(opts);
     StreamListener._parser = new jsmime.MimeParser(emitter, opts);
     return StreamListener;
   },
 
   /**
    * Returns a new raw MIME parser.
    *
    * Prefer one of the other methods where possible, since the input here must
    * be driven manually.
    *
    * @param emitter The emitter to receive callbacks on.
    * @param opts    A set of options for the parser.
    */
-  makeParser: function MimeParser_makeParser(emitter, opts) {
+  makeParser(emitter, opts) {
     setDefaultParserOptions(opts);
     return new jsmime.MimeParser(emitter, opts);
   },
 
   /**
    * Returns a dictionary of headers for the given input.
    *
    * The input is any type of input that would be accepted by parseSync. What
    * is returned is a JS object that represents the headers of the entire
    * envelope as would be received by startPart when partNum is the empty
    * string.
    *
    * @param input   A string of text to parse.
    */
-  extractHeaders: function MimeParser_extractHeaders(input) {
+  extractHeaders(input) {
     var emitter = Object.create(ExtractHeadersEmitter);
-    MimeParser.parseSync(input, emitter, {pruneat: '', bodyformat: 'none'});
+    MimeParser.parseSync(input, emitter, {pruneat: "", bodyformat: "none"});
     return emitter.headers;
   },
 
   /**
    * Returns the headers and body for the given input message.
    *
    * The return value is an array whose first element is the dictionary of
    * headers (as would be returned by extractHeaders) and whose second element
    * is a binary string of the entire body of the message.
    *
    * @param input   A string of text to parse.
    */
-  extractHeadersAndBody: function MimeParser_extractHeaders(input) {
+  extractHeadersAndBody(input) {
     var emitter = Object.create(ExtractHeadersAndBodyEmitter);
-    MimeParser.parseSync(input, emitter, {pruneat: '', bodyformat: 'raw'});
+    MimeParser.parseSync(input, emitter, {pruneat: "", bodyformat: "raw"});
     return [emitter.headers, emitter.body];
   },
 
   // Parameters for parseHeaderField
 
   /**
    * Parse the header as if it were unstructured.
    *
@@ -204,17 +200,17 @@ var MimeParser = {
    * This decodes the inline encoded-words that are in RFC 2047.
    */
   HEADER_OPTION_DECODE_2047: 0x20,
   /**
    * This converts the header from a raw string to proper Unicode.
    */
   HEADER_OPTION_ALLOW_RAW:   0x40,
 
-  /// Convenience for all three of the above.
+  // Convenience for all three of the above.
   HEADER_OPTION_ALL_I18N:    0x70,
 
   /**
    * Parse a header field according to the specification given by flags.
    *
    * Permissible flags begin with one of the HEADER_* flags, which may be or'd
    * with any of the HEADER_OPTION_* flags to modify the result appropriately.
    *
@@ -224,17 +220,17 @@ var MimeParser = {
    * is not provided, then no fallback decoding will be done. If
    * HEADER_OPTION_ALLOW_RAW is not passed, then no attempt will be made to
    * convert charsets.
    *
    * @param text    The value of a MIME or message header to parse.
    * @param flags   A set of flags that controls interpretation of the header.
    * @param charset A default charset to assume if no information may be found.
    */
-  parseHeaderField: function MimeParser_parseHeaderField(text, flags, charset) {
+  parseHeaderField(text, flags, charset) {
     // If we have a raw string, convert it to Unicode first
     if (flags & MimeParser.HEADER_OPTION_ALLOW_RAW)
       text = jsmime.headerparser.convert8BitHeader(text, charset);
 
     // The low 4 bits indicate the type of the header we are parsing. All of the
     // higher-order bits are flags.
     switch (flags & 0x0f) {
     case MimeParser.HEADER_UNSTRUCTURED:
@@ -244,12 +240,12 @@ var MimeParser = {
     case MimeParser.HEADER_PARAMETER:
       return jsmime.headerparser.parseParameterHeader(text,
         (flags & MimeParser.HEADER_OPTION_DECODE_2047) != 0,
         (flags & MimeParser.HEADER_OPTION_DECODE_2231) != 0);
     case MimeParser.HEADER_ADDRESS:
       return jsmime.headerparser.parseAddressingHeader(text,
         (flags & MimeParser.HEADER_OPTION_DECODE_2047) != 0);
     default:
-      throw "Illegal type of header field";
+      throw new Error("Illegal type of header field");
     }
   },
 };
--- a/mailnews/mime/src/mimemcms.cpp
+++ b/mailnews/mime/src/mimemcms.cpp
@@ -87,17 +87,16 @@ typedef struct MimeMultCMSdata {
         self(nullptr),
         parent_is_encrypted_p(false),
         parent_holds_stamp_p(false) {}
 
   ~MimeMultCMSdata() {
     PR_FREEIF(sender_addr);
 
     // Do a graceful shutdown of the nsICMSDecoder and release the nsICMSMessage
-    // //
     if (sig_decoder_context) {
       nsCOMPtr<nsICMSMessage> cinfo;
       sig_decoder_context->Finish(getter_AddRefs(cinfo));
     }
 
     delete[] item_data;
   }
 } MimeMultCMSdata;
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/test/unit/.eslintrc.js
@@ -0,0 +1,14 @@
+"use strict";
+
+module.exports = {
+  "extends": "plugin:mozilla/xpcshell-test",
+
+  "rules": {
+    "func-names": "off",
+    "mozilla/import-headjs-globals": "error",
+    "no-unused-vars": ["error", {
+      "args": "none",
+      "vars": "all",
+    }],
+  },
+};
--- a/mailnews/mime/test/unit/custom_header.js
+++ b/mailnews/mime/test/unit/custom_header.js
@@ -1,9 +1,11 @@
 // Custom header support for testing structured_headers.js
 
-jsmime.headerparser.addStructuredDecoder("X-Unusual", function (hdrs) {
+/* globals jsmime */
+
+jsmime.headerparser.addStructuredDecoder("X-Unusual", function(hdrs) {
   return Number.parseInt(hdrs[hdrs.length - 1], 16);
 });
 
-jsmime.headeremitter.addStructuredEncoder("X-Unusual", function (val) {
+jsmime.headeremitter.addStructuredEncoder("X-Unusual", function(val) {
   this.addUnstructured(val.toString(16));
 });
--- a/mailnews/mime/test/unit/head_mime.js
+++ b/mailnews/mime/test/unit/head_mime.js
@@ -5,17 +5,17 @@
 /**
  * Utility code for converting encoded MIME data.
  */
 
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 var {mailTestUtils} = ChromeUtils.import("resource://testing-common/mailnews/mailTestUtils.js");
-var {promiseTestUtils} = ChromeUtils.import("resource://testing-common/mailnews/PromiseTestUtils.jsm");
+var {PromiseTestUtils} = ChromeUtils.import("resource://testing-common/mailnews/PromiseTestUtils.jsm");
 const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 
 var CC = Components.Constructor;
 
 // Ensure the profile directory is set up
 do_get_profile();
 
 var gDEPTH = "../../../../";
@@ -26,52 +26,52 @@ registerCleanupFunction(function() {
 
 class DummyMsgHeader {
   constructor() {
     this.mProperties = {};
     this.messageSize = 0;
     this.recipients = null;
     this.from = null;
     this.subject = "";
-    this.ccList = null,
-    this.messageId = null,
-    this.listPost = null,
-    this.date = 0,
-    this.accountKey = "",
-    this.flags = 0,
-    this.folder = null
+    this.ccList = null;
+    this.messageId = null;
+    this.listPost = null;
+    this.date = 0;
+    this.accountKey = "";
+    this.flags = 0;
+    this.folder = null;
   }
   getStringProperty(aProperty) { return this.mProperties[aProperty]; }
   setStringProperty(aProperty, aVal) { this.mProperties[aProperty] = aVal; }
   getUint32Property(aProperty) {
     if (aProperty in this.mProperties)
       return parseInt(this.mProperties[aProperty]);
     return 0;
   }
   setUint32Property(aProperty, aVal) {
     this.mProperties[aProperty] = aVal.toString();
   }
   markHasAttachments(hasAttachments) { }
   get mime2DecodedSubject() { return this.subject; }
 }
 
-function apply_mime_conversion(msgUri, headerSink={}) {
+function apply_mime_conversion(msgUri, headerSink = {}) {
   let stubHeaderSink = {
     processHeaders(aHeaderNames, aHeaderValues, dontCollectAddress) {},
     handleAttachment(contentType, url, displayName, uri, aNotDownloaded) {},
     addAttachmentField(field, value) {},
     onEndAllAttachments() {},
     onEndMsgHeaders(url) {},
     onEndMsgDownload(url) {},
     securityInfo: null,
     onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
     dummyMsgHeader: new DummyMsgHeader(),
     get properties() { return null; },
     resetProperties() {},
-    QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgHeaderSink])
+    QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgHeaderSink]),
   };
 
   // Copy the descriptors from headerSink to stubHeaderSink.
   let fullHeaderSink = Object.create(headerSink);
   for (let name of Object.getOwnPropertyNames(stubHeaderSink)) {
     if (!(name in headerSink)) {
       Object.defineProperty(fullHeaderSink, name,
         Object.getOwnPropertyDescriptor(stubHeaderSink, name));
--- a/mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
+++ b/mailnews/mime/test/unit/test_EncodeMimePartIIStr_UTF8.js
@@ -4,27 +4,25 @@
 
 // This tests minimal mime encoding fixed in bug 458685
 
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
   var i;
 
-  var checks =
-  [
+  var checks = [
     ["", false, ""],
-    ["\u0436", false, "=?UTF-8?B?0LY=?="], //CYRILLIC SMALL LETTER ZHE
+    ["\u0436", false, "=?UTF-8?B?0LY=?="], // CYRILLIC SMALL LETTER ZHE
     ["IamASCII", false, "IamASCII"],
     // Although an invalid email, we shouldn't crash on it (bug 479206)
     ["crash test@foo.invalid>", true, "\"crash test\"@foo.invalid"],
     ["MXR now displays links to Github log & Blame for\r\n Gaia/Rust/Servo", false,
      "MXR now displays links to Github log & Blame for\r\n Gaia/Rust/Servo"],
     ["-----------------------:", false, "-----------------------:"],
   ];
 
-  for (i = 0; i < checks.length; ++i)
-  {
+  for (i = 0; i < checks.length; ++i) {
     Assert.equal(
       MailServices.mimeConverter.encodeMimePartIIStr_UTF8(checks[i][0], checks[i][1], "Subject".length, 72),
       checks[i][2]);
   }
 }
--- a/mailnews/mime/test/unit/test_alternate_p7m_handling.js
+++ b/mailnews/mime/test/unit/test_alternate_p7m_handling.js
@@ -1,50 +1,49 @@
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var {MsgHdrToMimeMessage} = ChromeUtils.import("resource:///modules/gloda/mimemsg.js");
 
-var gMessenger = Cc["@mozilla.org/messenger;1"]
-                   .createInstance(Ci.nsIMessenger);
-
 // Create a message generator
-var msgGen = gMessageGenerator = new MessageGenerator();
+var gMessageGenerator = new MessageGenerator();
 
 var p7mAttachment = "dGhpcyBpcyBub3QgYSByZWFsIHMvbWltZSBwN20gZW50aXR5";
 
 // create a message with a p7m attachment
 var messages = {
   attachments: [{
     body: p7mAttachment,
-    filename: 'test.txt.p7m',
-    contentType: 'application/pkcs7-mime',
-    format:'',
-    encoding: "base64"
-  }]
+    filename: "test.txt.p7m",
+    contentType: "application/pkcs7-mime",
+    format: "",
+    encoding: "base64",
+  }],
 };
 
-var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
-                  .createInstance(Ci.nsIMsgWindow);
-
 function* worker(params) {
   let synMsg = gMessageGenerator.makeMessage(params.messages);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgHdr = synSet.getMsgHdr(0);
 
   Services.prefs.setBoolPref("mailnews.p7m_external", params.all_external);
   Services.prefs.setBoolPref("mailnews.p7m_subparts_external", params.subparts_external);
 
-  MsgHdrToMimeMessage(msgHdr, null, function (aMsgHdr, aMimeMsg) {
+  MsgHdrToMimeMessage(msgHdr, null, function(aMsgHdr, aMimeMsg) {
     try {
       Assert.ok(aMimeMsg.allUserAttachments.length == params.count);
       async_driver();
     } catch (err) {
       do_throw(err);
     }
   });
 
@@ -54,17 +53,17 @@ function* worker(params) {
 /* ===== Driver ===== */
 
 var tests = [
   parameterizeTest(worker, [{ messages, all_external: false, subparts_external: false, count: 0 }]),
   // We are only testing with a p7m attachment, so whether all parts or just subparts are
   // made external yields the same result: one attachment which is not inlined.
   parameterizeTest(worker, [{ messages, all_external: true,  subparts_external: false, count: 1 }]),
   parameterizeTest(worker, [{ messages, all_external: false, subparts_external: true,  count: 1 }]),
-  parameterizeTest(worker, [{ messages, all_external: true,  subparts_external: true,  count: 1 }])
+  parameterizeTest(worker, [{ messages, all_external: true,  subparts_external: true,  count: 1 }]),
 ];
 
 var gInbox;
 
 function run_test() {
   gInbox = configure_message_injection({mode: "local"});
   async_run_tests(tests);
 }
--- a/mailnews/mime/test/unit/test_attachment_size.js
+++ b/mailnews/mime/test/unit/test_attachment_size.js
@@ -1,283 +1,309 @@
 /* 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 test creates some messages with attachments of different types and
  * checks that libmime reports the expected size for each of them.
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 // Somehow we hit the blocklist service, and that needs appInfo defined
 const {updateAppInfo} = ChromeUtils.import("resource://testing-common/AppInfo.jsm");
 updateAppInfo();
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
 var msgGen = gMessageGenerator = new MessageGenerator();
-// Create a message scenario generator using that message generator
-var scenarios = gMessageScenarioFactory = new MessageScenarioFactory(msgGen);
 
 /* Today's gory details (thanks to Jonathan Protzenko): libmime somehow
  * counts the trailing newline for an attachment MIME part. Most of the time,
  * assuming attachment has N bytes (no matter what's inside, newlines or
  * not), libmime will return N + 1 bytes. On Linux and Mac, this always
  * holds. However, on Windows, if the attachment is not encoded (that is, is
  * inline text), libmime will return N + 2 bytes.
  */
-var epsilon = ('@mozilla.org/windows-registry-key;1' in Cc) ? 4 : 2;
+var epsilon = ("@mozilla.org/windows-registry-key;1" in Cc) ? 4 : 2;
 
 var textAttachment =
   "Can't make the frug contest, Helen; stomach's upset. I'll fix you, " +
   "Ubik! Ubik drops you back in the thick of things fast. Taken as " +
   "directed, Ubik speeds relief to head and stomach. Remember: Ubik is " +
   "only seconds away. Avoid prolonged use.";
 
 var binaryAttachment = textAttachment;
 
 var imageAttachment =
-  'iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS' +
-  'FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA' +
-  'A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe' +
-  'SNQAAlmAY+71EgFoAAAAASUVORK5CYII=';
+  "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS" +
+  "FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA" +
+  "A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe" +
+  "SNQAAlmAY+71EgFoAAAAASUVORK5CYII=";
 var imageSize = 188;
 
 var uuAttachment =
-  'begin 644 /home/jvporter/Desktop/out.txt\n' +
+  "begin 644 /home/jvporter/Desktop/out.txt\n" +
   'M0V%N)W0@;6%K92!T:&4@9G)U9R!C;VYT97-T+"!(96QE;CL@<W1O;6%C:"=S\n' +
   'M(\'5P<V5T+B!))VQL(&9I>"!Y;W4L(%5B:6LA(%5B:6L@9\')O<\',@>6]U(&)A\n' +
-  'M8VL@:6X@=&AE(\'1H:6-K(&]F(\'1H:6YG<R!F87-T+B!486ME;B!A<R!D:7)E\n' +
+  "M8VL@:6X@=&AE('1H:6-K(&]F('1H:6YG<R!F87-T+B!486ME;B!A<R!D:7)E\n" +
   'M8W1E9"P@56)I:R!S<&5E9\',@<F5L:65F(\'1O(&AE860@86YD(\'-T;VUA8V@N\n' +
   'M(%)E;65M8F5R.B!58FEK(&ES(&]N;\'D@<V5C;VYD<R!A=V%Y+B!!=F]I9"!P\n' +
-  '.<F]L;VYG960@=7-E+@H`\n' +
-  '`\n' +
-  'end';
+  ".<F]L;VYG960@=7-E+@H`\n" +
+  "`\n" +
+  "end";
 
 var yencText =
-  "Hello there --\n"+
-  "=ybegin line=128 size=174 name=jane\n"+
-  "\x76\x99\x98\x91\x9e\x8f\x97\x9a\x9d\x56\x4a\x94\x8f\x4a\x97\x8f"+
-  "\x4a\x9d\x9f\x93\x9d\x4a\x8d\x99\x9f\x8d\x92\xed\xd3\x4a\x8e\x8f"+
-  "\x4a\x8c\x99\x98\x98\x8f\x4a\x92\x8f\x9f\x9c\x8f\x58\x4a\x7a\x8b"+
-  "\x9c\x90\x99\x93\x9d\x56\x4a\xed\xca\x4a\x9a\x8f\x93\x98\x8f\x4a"+
-  "\x97\x8b\x4a\x8c\x99\x9f\x91\x93\x8f\x4a\xed\xd3\x9e\x8f\x93\x98"+
-  "\x9e\x8f\x56\x4a\x97\x8f\x9d\x4a\xa3\x8f\x9f\xa2\x4a\x9d\x8f\x4a"+
-  "\x90\x8f\x9c\x97\x8b\x93\x8f\x98\x9e\x4a\x9d\x93\x4a\xa0\x93\x9e"+
-  "\x8f\x4a\x9b\x9f\x8f\x4a\x94\x8f\x4a\x98\x51\x8b\xa0\x8b\x93\x9d"+
-  "\x0d\x0a\x4a\x9a\x8b\x9d\x4a\x96\x8f\x4a\x9e\x8f\x97\x9a\x9d\x4a"+
-  "\x8e\x8f\x4a\x97\x8f\x4a\x8e\x93\x9c\x8f\x4a\x64\x4a\xec\xd5\x4a"+
-  "\x74\x8f\x4a\x97\x51\x8f\x98\x8e\x99\x9c\x9d\x58\x4a\xec\xe5\x34"+
-  "\x0d\x0a"+
+  "Hello there --\n" +
+  "=ybegin line=128 size=174 name=jane\n" +
+  "\x76\x99\x98\x91\x9e\x8f\x97\x9a\x9d\x56\x4a\x94\x8f\x4a\x97\x8f" +
+  "\x4a\x9d\x9f\x93\x9d\x4a\x8d\x99\x9f\x8d\x92\xed\xd3\x4a\x8e\x8f" +
+  "\x4a\x8c\x99\x98\x98\x8f\x4a\x92\x8f\x9f\x9c\x8f\x58\x4a\x7a\x8b" +
+  "\x9c\x90\x99\x93\x9d\x56\x4a\xed\xca\x4a\x9a\x8f\x93\x98\x8f\x4a" +
+  "\x97\x8b\x4a\x8c\x99\x9f\x91\x93\x8f\x4a\xed\xd3\x9e\x8f\x93\x98" +
+  "\x9e\x8f\x56\x4a\x97\x8f\x9d\x4a\xa3\x8f\x9f\xa2\x4a\x9d\x8f\x4a" +
+  "\x90\x8f\x9c\x97\x8b\x93\x8f\x98\x9e\x4a\x9d\x93\x4a\xa0\x93\x9e" +
+  "\x8f\x4a\x9b\x9f\x8f\x4a\x94\x8f\x4a\x98\x51\x8b\xa0\x8b\x93\x9d" +
+  "\x0d\x0a\x4a\x9a\x8b\x9d\x4a\x96\x8f\x4a\x9e\x8f\x97\x9a\x9d\x4a" +
+  "\x8e\x8f\x4a\x97\x8f\x4a\x8e\x93\x9c\x8f\x4a\x64\x4a\xec\xd5\x4a" +
+  "\x74\x8f\x4a\x97\x51\x8f\x98\x8e\x99\x9c\x9d\x58\x4a\xec\xe5\x34" +
+  "\x0d\x0a" +
   "=yend size=174 crc32=7efccd8e\n";
 var yencSize = 174;
 
 var partHtml = new SyntheticPartLeaf(
   "<html><head></head><body>I am HTML! Woo! </body></html>",
-  {
-    contentType: "text/html"
-  }
+  { contentType: "text/html" }
 );
 
 var attachedMessage1 = msgGen.makeMessage({ body: { body: textAttachment } });
 var attachedMessage2 = msgGen.makeMessage({
   body: { body: textAttachment },
-  attachments: [{ body: imageAttachment,
-                  contentType: 'application/x-ubik',
-                  filename: 'ubik',
-                  encoding: 'base64',
-                  format: '' }]
+  attachments: [{
+    body: imageAttachment,
+    contentType: "application/x-ubik",
+    filename: "ubik",
+    encoding: "base64",
+    format: "",
+  }],
 });
 
 /**
  * Return the size of a synthetic message. Much like the above comment, libmime
  * counts bytes differently on Windows, where it counts newlines (\r\n) as 2
  * bytes. Mac and Linux treats them as 1 byte.
  *
  * @param message a synthetic message from makeMessage()
  * @return the message's size in bytes
  */
 function get_message_size(message) {
   let messageString = message.toMessageString();
   if (epsilon == 4) // Windows
     return messageString.length;
-  else // Mac/Linux
-    return messageString.replace(/\r\n/g, "\n").length;
+  return messageString.replace(/\r\n/g, "\n").length;
 }
 
 // create some messages that have various types of attachments
 var messages = [
-  // text attachment
-  { attachments: [{ body: textAttachment,
-                    filename: 'ubik.txt',
-                    format: '' }],
-    size: textAttachment.length },
-  // (inline) image attachment
-  { attachments: [{ body: imageAttachment,
-                    contentType: 'image/png',
-                    filename: 'lines.png',
-                    encoding: 'base64',
-                    format: '' }],
-    size: imageSize },
-  // binary attachment, no encoding
-  { attachments: [{ body: binaryAttachment,
-                    contentType: 'application/x-ubik',
-                    filename: 'ubik',
-                    format: '' }],
-    size: binaryAttachment.length },
-  // binary attachment, b64 encoding
-  { attachments: [{ body: imageAttachment,
-                    contentType: 'application/x-ubik',
-                    filename: 'ubik',
-                    encoding: 'base64',
-                    format: '' }],
-    size: imageSize },
-  // uuencoded attachment
-  { attachments: [{ body: uuAttachment,
-                    contentType: 'application/x-uuencode',
-                    filename: 'ubik',
-                    format: '',
-                    encoding: 'uuencode' }],
-    size: textAttachment.length },
-  // yencoded attachment
-  { bodyPart: new SyntheticPartLeaf("I am text! Woo!\n\n"+yencText,
-                                    { contentType: '' } ),
+  {
+    // text attachment
+    attachments: [{
+      body: textAttachment,
+      filename: "ubik.txt",
+      format: "",
+    }],
+    size: textAttachment.length,
+  }, {
+    // (inline) image attachment
+    attachments: [{
+      body: imageAttachment,
+      contentType: "image/png",
+      filename: "lines.png",
+      encoding: "base64",
+      format: "",
+    }],
+    size: imageSize,
+  }, {
+    // binary attachment, no encoding
+    attachments: [{
+      body: binaryAttachment,
+      contentType: "application/x-ubik",
+      filename: "ubik",
+      format: "",
+    }],
+    size: binaryAttachment.length,
+  }, {
+    // binary attachment, b64 encoding
+    attachments: [{
+      body: imageAttachment,
+      contentType: "application/x-ubik",
+      filename: "ubik",
+      encoding: "base64",
+      format: "",
+    }],
+    size: imageSize,
+  }, {
+    // uuencoded attachment
+    attachments: [{
+      body: uuAttachment,
+      contentType: "application/x-uuencode",
+      filename: "ubik",
+      format: "",
+      encoding: "uuencode",
+    }],
+    size: textAttachment.length,
+  }, {
+    // yencoded attachment
+    bodyPart: new SyntheticPartLeaf("I am text! Woo!\n\n" + yencText,
+                                    { contentType: "" }),
     subject: "yEnc-Prefix: \"jane\" 174 yEnc bytes - yEnc test (1)",
-    size: yencSize },
-  // an attached eml that used to return a size that's -1
-  {
+    size: yencSize,
+  }, {
+    // an attached eml that used to return a size that's -1
     bodyPart: new SyntheticPartMultiMixed([
       partHtml,
       attachedMessage1,
     ]),
     size: get_message_size(attachedMessage1),
-  },
-  // this is an attached message that itself has an attachment
-  {
+  }, {
+    // this is an attached message that itself has an attachment
     bodyPart: new SyntheticPartMultiMixed([
       partHtml,
       attachedMessage2,
     ]),
     size: get_message_size(attachedMessage2),
-  },
-  // an "attachment" that's really the body of the message
-  { body: { body: textAttachment,
-            contentType: 'application/x-ubik; name=attachment.ubik' },
+  }, {
+    // an "attachment" that's really the body of the message
+    body: {
+      body: textAttachment,
+      contentType: "application/x-ubik; name=attachment.ubik",
+    },
     size: textAttachment.length,
-  },
-  // a message/rfc822 "attachment" that's really the body of the message
-  { bodyPart: attachedMessage1,
+  }, {
+    // a message/rfc822 "attachment" that's really the body of the message
+    bodyPart: attachedMessage1,
     size: get_message_size(attachedMessage1),
+  }, {
+    // an external http link attachment (as constructed for feed enclosures) - no 'size' parm.
+    attachments: [{
+      body: "This MIME attachment is stored separately from the message.",
+      contentType: 'application/unknown; name="somefile"',
+      extraHeaders: {
+        "X-Mozilla-External-Attachment-URL": "http://myblog.com/somefile",
+      },
+      disposition: 'attachment; filename="somefile"',
+    }],
+    size: -1,
+  }, {
+    // an external http link attachment (as constructed for feed enclosures) - file with 'size' parm.
+    attachments: [{
+      body: "This MIME attachment is stored separately from the message.",
+      contentType: 'audio/mpeg; name="file.mp3"; size=123456789',
+      extraHeaders: {
+        "X-Mozilla-External-Attachment-URL": "https://myblog.com/file.mp3",
+      },
+      disposition: 'attachment; name="file.mp3"',
+    }],
+    size: 123456789,
   },
-  // an external http link attachment (as constructed for feed enclosures) - no 'size' parm.
-  { attachments: [{ body: 'This MIME attachment is stored separately from the message.',
-                    contentType: 'application/unknown; name="somefile"',
-                    extraHeaders: {
-                      'X-Mozilla-External-Attachment-URL': 'http://myblog.com/somefile',
-                    },
-                    disposition: 'attachment; filename="somefile"' }],
-    size: -1 },
-  // an external http link attachment (as constructed for feed enclosures) - file with 'size' parm.
-  { attachments: [{ body: 'This MIME attachment is stored separately from the message.',
-                    contentType: 'audio/mpeg; name="file.mp3"; size=123456789',
-                    extraHeaders: {
-                      'X-Mozilla-External-Attachment-URL': 'https://myblog.com/file.mp3',
-                    },
-                    disposition: 'attachment; name="file.mp3"' }],
-    size: 123456789 },
 ];
 
 
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
     // We reset the size here because we know that we only expect one attachment
     //  per test email. In the case of the attached .eml with nested
     //  attachments, this allows us to properly discard the nested attachment
     //  sizes.
     // msgHdrViewOverlay.js has a stack of attachment infos that properly
     //  handles this.
     gMessageHeaderSink.size = null;
   },
-  onStopRequest: function (aRequest, aStatusCode) {
-    dump("*** Size is "+gMessageHeaderSink.size+" (expecting "+this.expectedSize+")\n\n");
+  onStopRequest(aRequest, aStatusCode) {
+    dump("*** Size is " + gMessageHeaderSink.size + " (expecting " + this.expectedSize + ")\n\n");
     Assert.ok(Math.abs(gMessageHeaderSink.size - this.expectedSize) <= epsilon);
     this._stream = null;
     async_driver();
   },
 
   // nsIStreamListener part
-  _stream : null,
+  _stream: null,
 
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this._stream === null) {
       this._stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this._stream.init(aInputStream);
     }
     this._stream.read(aCount);
   },
 };
 
 var gMessageHeaderSink = {
-  handleAttachment: function(aContentType, aUrl, aDisplayName, aUri,
+  handleAttachment(aContentType, aUrl, aDisplayName, aUri,
                              aIsExternalAttachment) {
   },
-  addAttachmentField: function(aName, aValue) {
+  addAttachmentField(aName, aValue) {
     // Only record the information for the first attachment.
     if (aName == "X-Mozilla-PartSize" && (this.size == null))
       this.size = parseInt(aValue);
   },
 
   // stub functions from nsIMsgHeaderSink
-  onStartHeaders: function() {},
-  onEndHeaders: function() {},
-  processHeaders: function(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
-  onEndAllAttachments: function() {},
-  onEndMsgDownload: function() {},
-  onEndMsgHeaders: function(aUrl) {},
-  onMsgHasRemoteContent: function(aMsgHdr, aContentURI) {},
+  onStartHeaders() {},
+  onEndHeaders() {},
+  processHeaders(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
+  onEndAllAttachments() {},
+  onEndMsgDownload() {},
+  onEndMsgHeaders(aUrl) {},
+  onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
   securityInfo: null,
   mDummyMsgHeader: null,
   properties: null,
-  resetProperties: function () {}
+  resetProperties() {},
 };
 
 var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
                   .createInstance(Ci.nsIMsgWindow);
 msgWindow.msgHeaderSink = gMessageHeaderSink;
 
 function* test_message_attachments(info) {
   let synMsg = gMessageGenerator.makeMessage(info);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
   gStreamListener.expectedSize = info.size;
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
-    false);
+    false
+  );
 
   yield false;
 }
 
 /* ===== Driver ===== */
 
 var tests = [
   parameterizeTest(test_message_attachments, messages),
--- a/mailnews/mime/test/unit/test_badContentType.js
+++ b/mailnews/mime/test/unit/test_badContentType.js
@@ -2,104 +2,113 @@
  * 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 test checks handling of bad content type of the
  * type reported in bug 659355.
  * Adapted from test_attachment_size.js
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
-var msgGen = gMessageGenerator = new MessageGenerator();
-// Create a message scenario generator using that message generator
-var scenarios = gMessageScenarioFactory = new MessageScenarioFactory(msgGen);
+var gMessageGenerator = new MessageGenerator();
 
 var imageAttachment =
-  'iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS' +
-  'FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA' +
-  'A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe' +
-  'SNQAAlmAY+71EgFoAAAAASUVORK5CYII=';
+  "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwS" +
+  "FlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAA" +
+  "A5SURBVCiRY/z//z8DKYCJJNXkaGBgYGD4D8NQ5zUgiTVAxeBqSLaBkVRPM0KtIhrQ3km0jwe" +
+  "SNQAAlmAY+71EgFoAAAAASUVORK5CYII=";
 
 // create some messages that have various types of attachments
 var messages = [
   // image attachment (normal content type sanity test)
-  { attachments: [{ body: imageAttachment,
-                    contentType: 'image/png',
-                    filename: 'lines.png',
-                    encoding: 'base64',
-                    format: '' }],
-    testContentType: "image/png" },
-  { attachments: [{ body: imageAttachment,
-                    contentType: '=?windows-1252?q?application/pdf',
-                    filename: 'lines.pdf',
-                    encoding: 'base64',
-                    format: '' }],
-    testContentType: "application/pdf" },
+  {
+    attachments: [{
+      body: imageAttachment,
+      contentType: "image/png",
+      filename: "lines.png",
+      encoding: "base64",
+      format: "",
+    }],
+    testContentType: "image/png",
+  }, {
+    attachments: [{
+      body: imageAttachment,
+      contentType: "=?windows-1252?q?application/pdf",
+      filename: "lines.pdf",
+      encoding: "base64",
+      format: "",
+    }],
+    testContentType: "application/pdf",
+  },
 ];
 
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
     // We reset the size here because we know that we only expect one attachment
     //  per test email
     // msgHdrViewOverlay.js has a stack of attachment infos that properly
     //  handles this.
     gMessageHeaderSink.size = null;
   },
-  onStopRequest: function (aRequest, aStatusCode) {
-    dump("*** ContentType is "+gMessageHeaderSink.contentType+" (expecting "+this.expectedContentType+")\n\n");
+  onStopRequest(aRequest, aStatusCode) {
+    dump("*** ContentType is " + gMessageHeaderSink.contentType + " (expecting " + this.expectedContentType + ")\n\n");
     Assert.equal(gMessageHeaderSink.contentType, this.expectedContentType);
     this._stream = null;
     async_driver();
   },
 
   // nsIStreamListener part
-  _stream : null,
+  _stream: null,
 
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this._stream === null) {
       this._stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this._stream.init(aInputStream);
     }
     this._stream.read(aCount);
   },
 };
 
 var gMessageHeaderSink = {
-  handleAttachment: function(aContentType, aUrl, aDisplayName, aUri,
-                             aIsExternalAttachment) {
+  handleAttachment(aContentType, aUrl, aDisplayName, aUri, aIsExternalAttachment) {
     gMessageHeaderSink.contentType = aContentType;
   },
 
   // stub functions from nsIMsgHeaderSink
-  addAttachmentField: function(aName, aValue) {},
-  onStartHeaders: function() {},
-  onEndHeaders: function() {},
-  processHeaders: function(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
-  onEndAllAttachments: function() {},
-  onEndMsgDownload: function() {},
-  onEndMsgHeaders: function(aUrl) {},
-  onMsgHasRemoteContent: function(aMsgHdr, aContentURI) {},
+  addAttachmentField(aName, aValue) {},
+  onStartHeaders() {},
+  onEndHeaders() {},
+  processHeaders(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
+  onEndAllAttachments() {},
+  onEndMsgDownload() {},
+  onEndMsgHeaders(aUrl) {},
+  onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
   securityInfo: null,
   mDummyMsgHeader: null,
   properties: null,
-  resetProperties: function () {}
+  resetProperties() {},
 };
 
 var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
                   .createInstance(Ci.nsIMsgWindow);
 msgWindow.msgHeaderSink = gMessageHeaderSink;
 
 function* test_message_attachments(info) {
   let synMsg = gMessageGenerator.makeMessage(info);
@@ -107,17 +116,17 @@ function* test_message_attachments(info)
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
   gStreamListener.expectedContentType = info.testContentType;
 
   dump("*** original ContentType=" + info.attachments[0].contentType + "\n");
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
     false);
--- a/mailnews/mime/test/unit/test_bug493544.js
+++ b/mailnews/mime/test/unit/test_bug493544.js
@@ -1,84 +1,92 @@
 //
 // Tests if a multi-line MIME header is parsed even if it violates RFC 2047
 //
 
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
   const headers = [
-    { encoded:
-      "Subject: AAA =?UTF-8?Q?bbb?= CCC =?UTF-8?Q?ddd?= EEE =?UTF-8?Q?fff?= GGG"
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: AAA bbb CCC ddd EEE fff GGG"
-    }, // Bug 833028
-    { encoded:
-      "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiCAg?=\n"
-    + " =?UTF-8?B?4oiJICDiiIogIOKIiyAg4oiMICDiiI0gIOKIjiAg4oiP?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Bug 493544
-    { encoded:
-      "Subject: =?utf-8?Q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__=E2?=\n"
-    + " =?utf-8?Q?=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__=E2=88?=\n"
-    + " =?utf-8?Q?=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__=E2=88=8F?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Bug 476741
-    { encoded:
-      "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA==?=\n"
-    + " =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Normal case
-    { encoded:
-      "Subject: =?UTF-8?b?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA==?=\n"
-    + " =?UTF-8?b?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Normal case with the encoding character in lower case
-    { encoded:
-      "Subject: =?utf-8?Q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n"
-    + " =?utf-8?Q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n"
-    + " =?utf-8?Q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n"
-    + " =?utf-8?Q?=E2=88=8F?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Normal case
-    { encoded:
-      "Subject: =?utf-8?q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n"
-    + " =?utf-8?q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n"
-    + " =?utf-8?q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n"
-    + " =?utf-8?q?=E2=88=8F?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Normal case with the encoding character in lower case
-    { encoded:
-      "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA===?=\n"
-    + " =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?="
-    , defaultCharset: "UTF-8"
-    , overrideCharset: false
-    , eatContinuation: false
-    , decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏"
-    }, // Regression test for bug 227290
+    {
+      // Bug 833028
+      encoded: "Subject: AAA =?UTF-8?Q?bbb?= CCC =?UTF-8?Q?ddd?= EEE =?UTF-8?Q?fff?= GGG",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: AAA bbb CCC ddd EEE fff GGG",
+    }, {
+      // Bug 493544
+      encoded:
+        "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiCAg?=\n" +
+        " =?UTF-8?B?4oiJICDiiIogIOKIiyAg4oiMICDiiI0gIOKIjiAg4oiP?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Bug 476741
+      encoded:
+        "Subject: =?utf-8?Q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__=E2?=\n" +
+        " =?utf-8?Q?=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__=E2=88?=\n" +
+        " =?utf-8?Q?=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__=E2=88=8F?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Normal case
+      encoded:
+        "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA==?=\n" +
+        " =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Normal case with the encoding character in lower case
+      encoded:
+        "Subject: =?UTF-8?b?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA==?=\n" +
+        " =?UTF-8?b?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Normal case
+      encoded:
+        "Subject: =?utf-8?Q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n" +
+        " =?utf-8?Q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n" +
+        " =?utf-8?Q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n" +
+        " =?utf-8?Q?=E2=88=8F?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Normal case with the encoding character in lower case
+      encoded:
+        "Subject: =?utf-8?q?=E2=88=80__=E2=88=81__=E2=88=82__=E2=88=83__=E2=88=84__?=\n" +
+        " =?utf-8?q?=E2=88=85__=E2=88=86__=E2=88=87__=E2=88=88__=E2=88=89__?=\n" +
+        " =?utf-8?q?=E2=88=8A__=E2=88=8B__=E2=88=8C__=E2=88=8D__=E2=88=8E__?=\n" +
+        " =?utf-8?q?=E2=88=8F?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    }, {
+      // Regression test for bug 227290
+      encoded:
+        "Subject: =?UTF-8?B?4oiAICDiiIEgIOKIgiAg4oiDICDiiIQgIOKIhSAg4oiGICDiiIcgIOKIiA===?=\n" +
+        " =?UTF-8?B?ICDiiIkgIOKIiiAg4oiLICDiiIwgIOKIjSAg4oiOICDiiI8=?=",
+      defaultCharset: "UTF-8",
+      overrideCharset: false,
+      eatContinuation: false,
+      decoded: "Subject: ∀  ∁  ∂  ∃  ∄  ∅  ∆  ∇  ∈  ∉  ∊  ∋  ∌  ∍  ∎  ∏",
+    },
   ];
 
   for (let i = 0; i < headers.length; ++i) {
     let decoded = MailServices.mimeConverter.decodeMimeHeader(headers[i].encoded,
                                                               headers[i].defaultCharset,
                                                               headers[i].overrideCharset,
                                                               headers[i].eatContinuation);
     Assert.equal(decoded, headers[i].decoded);
--- a/mailnews/mime/test/unit/test_hidden_attachments.js
+++ b/mailnews/mime/test/unit/test_hidden_attachments.js
@@ -1,110 +1,131 @@
 /* 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 test creates some messages with attachments of different types and
  * checks that libmime emits (or doesn't emit) the attachments as appropriate.
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
-var msgGen = gMessageGenerator = new MessageGenerator();
-// Create a message scenario generator using that message generator
-var scenarios = gMessageScenarioFactory = new MessageScenarioFactory(msgGen);
+var gMessageGenerator = new MessageGenerator();
 
 // create some messages that have various types of attachments
 var messages = [
   {},
 
-  /***** Attachments with Content-Disposition: attachment *****/
+  /* Attachments with Content-Disposition: attachment */
 
-  // inline-able attachment with a name
-  { attachments: [{ body: "attachment",
-                    filename: "ubik.txt",
-                    disposition: "attachment",
-                    format: "",
-                    shouldShow: true }],
-  },
-  // inline-able attachment with no name
-  { attachments: [{ body: "attachment",
-                    filename: "",
-                    disposition: "attachment",
-                    format: "",
-                    shouldShow: true }],
-  },
-  // non-inline-able attachment with a name
-  { attachments: [{ body: "attachment",
-                    filename: "ubik.ubk",
-                    disposition: "attachment",
-                    contentType: "application/x-ubik",
-                    format: "",
-                    shouldShow: true }],
-  },
-  // non-inline-able attachment with no name
-  { attachments: [{ body: "attachment",
-                    filename: "",
-                    disposition: "attachment",
-                    contentType: "application/x-ubik",
-                    format: "",
-                    shouldShow: true }],
+  {
+    // inline-able attachment with a name
+    attachments: [{
+      body: "attachment",
+      filename: "ubik.txt",
+      disposition: "attachment",
+      format: "",
+      shouldShow: true,
+    }],
+  }, {
+    // inline-able attachment with no name
+    attachments: [{
+      body: "attachment",
+      filename: "",
+      disposition: "attachment",
+      format: "",
+      shouldShow: true,
+    }],
+  }, {
+    // non-inline-able attachment with a name
+    attachments: [{
+      body: "attachment",
+      filename: "ubik.ubk",
+      disposition: "attachment",
+      contentType: "application/x-ubik",
+      format: "",
+      shouldShow: true,
+    }],
+  }, {
+    // non-inline-able attachment with no name
+    attachments: [{
+      body: "attachment",
+      filename: "",
+      disposition: "attachment",
+      contentType: "application/x-ubik",
+      format: "",
+      shouldShow: true,
+    }],
   },
 
-  /***** Attachments with Content-Disposition: inline *****/
+  /* Attachments with Content-Disposition: inline */
 
-  // inline-able attachment with a name
-  { attachments: [{ body: "attachment",
-                    filename: "ubik.txt",
-                    disposition: "inline",
-                    format: "",
-                    shouldShow: true }],
-  },
-  // inline-able attachment with no name
-  { attachments: [{ body: "attachment",
-                    filename: "",
-                    disposition: "inline",
-                    format: "",
-                    shouldShow: false }],
-  },
-  // non-inline-able attachment with a name
-  { attachments: [{ body: "attachment",
-                    filename: "ubik.ubk",
-                    disposition: "inline",
-                    contentType: "application/x-ubik",
-                    format: "",
-                    shouldShow: true }],
-  },
-  // non-inline-able attachment with no name
-  { attachments: [{ body: "attachment",
-                    filename: "",
-                    disposition: "inline",
-                    contentType: "application/x-ubik",
-                    format: "",
-                    shouldShow: true }],
+  {
+    // inline-able attachment with a name
+    attachments: [{
+      body: "attachment",
+      filename: "ubik.txt",
+      disposition: "inline",
+      format: "",
+      shouldShow: true,
+    }],
+  }, {
+    // inline-able attachment with no name
+    attachments: [{
+      body: "attachment",
+      filename: "",
+      disposition: "inline",
+      format: "",
+      shouldShow: false,
+    }],
+  }, {
+    // non-inline-able attachment with a name
+    attachments: [{
+      body: "attachment",
+      filename: "ubik.ubk",
+      disposition: "inline",
+      contentType: "application/x-ubik",
+      format: "",
+      shouldShow: true,
+    }],
+  }, {
+    // non-inline-able attachment with no name
+    attachments: [{
+      body: "attachment",
+      filename: "",
+      disposition: "inline",
+      contentType: "application/x-ubik",
+      format: "",
+      shouldShow: true,
+    }],
   },
 ];
 
 
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
   },
-  onStopRequest: function (aRequest, aStatusCode) {
+  onStopRequest(aRequest, aStatusCode) {
     let expectedAttachments = this.allAttachments.filter(i => i.shouldShow).
       map(i => i.filename);
     Assert.equal(expectedAttachments.length,
                  gMessageHeaderSink.attachments.length);
 
     for (let i = 0; i < gMessageHeaderSink.attachments.length; i++) {
       // If the expected attachment's name is empty, we probably generated a
       // name like "Part 1.2", so don't bother checking that the names match
@@ -113,73 +134,73 @@ var gStreamListener = {
         Assert.equal(expectedAttachments[i], gMessageHeaderSink.attachments[i]);
     }
     this._stream = null;
 
     async_driver();
   },
 
   // nsIStreamListener part
-  _stream : null,
+  _stream: null,
 
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this._stream === null) {
       this._stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this._stream.init(aInputStream);
     }
     this._stream.read(aCount);
   },
 };
 
 var gMessageHeaderSink = {
-  onEndMsgHeaders: function(aUrl) {
+  onEndMsgHeaders(aUrl) {
     this.attachments = [];
   },
-  handleAttachment: function(aContentType, aUrl, aDisplayName, aUri,
-                             aIsExternalAttachment) {
+  handleAttachment(aContentType, aUrl, aDisplayName, aUri, aIsExternalAttachment) {
     this.attachments.push(aDisplayName);
   },
 
   // stub functions from nsIMsgHeaderSink
-  onStartHeaders: function() {},
-  onEndHeaders: function() {},
-  processHeaders: function(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
-  addAttachmentField: function(aName, aValue) {},
-  onEndAllAttachments: function() {},
-  onEndMsgDownload: function() {},
-  onMsgHasRemoteContent: function(aMsgHdr, aContentURI) {},
+  onStartHeaders() {},
+  onEndHeaders() {},
+  processHeaders(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
+  addAttachmentField(aName, aValue) {},
+  onEndAllAttachments() {},
+  onEndMsgDownload() {},
+  onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
   securityInfo: null,
   mDummyMsgHeader: null,
   properties: null,
-  resetProperties: function () {}
+  resetProperties() {},
 };
 
 var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
                   .createInstance(Ci.nsIMsgWindow);
 msgWindow.msgHeaderSink = gMessageHeaderSink;
 
 function* test_message_attachments(info) {
   let synMsg = gMessageGenerator.makeMessage(info);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
   gStreamListener.allAttachments = info.attachments || [];
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
-    false);
+    false
+  );
 
   yield false;
 }
 
 /* ===== Driver ===== */
 
 var tests = [
   parameterizeTest(test_message_attachments, messages),
--- a/mailnews/mime/test/unit/test_jsmime_charset.js
+++ b/mailnews/mime/test/unit/test_jsmime_charset.js
@@ -22,13 +22,13 @@ var tests = [
   ["=?cp932?B?grGCsYLJlnuVtoKqgquC3IK3gUI=?=", "ここに本文がきます。"],
 ];
 
 function run_test() {
   for (let test of tests) {
     dump("Testing message " + test[0]);
     let value = test[0];
     if (test.length > 2)
-      value = jsmime.headerparser.convert8BitHeader(value, test[2])
+      value = jsmime.headerparser.convert8BitHeader(value, test[2]);
     Assert.equal(jsmime.headerparser.parseStructuredHeader("Subject", value),
       test[1]);
   }
 }
--- a/mailnews/mime/test/unit/test_message_attachment.js
+++ b/mailnews/mime/test/unit/test_message_attachment.js
@@ -1,145 +1,163 @@
 /* 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 test verifies that we generate proper attachment filenames.
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
 var msgGen = gMessageGenerator = new MessageGenerator();
 
 var textAttachment =
   "inline text attachment";
 
 // create a message with a text attachment
 var messages = [
-  // unnamed email attachment
-  { attachments: [{ body: textAttachment,
-                    filename: 'test.txt',
-                    format: '' },
-                  { body: '',
-                    expectedFilename: 'ForwardedMessage.eml',
-                    contentType: 'message/rfc822', },
-                 ]},
-  // named email attachment
-  { attachments: [{ body: textAttachment,
-                    filename: 'test.txt',
-                    format: '' },
-                  { body: '',
-                    filename: 'Attached Message',
-                    contentType: 'message/rfc822', },
-                 ]},
-  { attachments: [{ body: textAttachment,
-                    filename: 'test.html',
-                    format: '' },
-                  { body: '',
-                    filename: '<iframe src=&quote;http://www.example.com&quote></iframe>.htm',
-                    expectedFilename: '&lt;iframe src=&amp;quote;http://www.example.com&amp;quote&gt;&lt;/iframe&gt;.htm',
-                    contentType: 'text/html;', },
-                 ]},
-  // no named email attachment with subject header
-  { attachments: [{ body: '', expectedFilename: 'testSubject.eml' }],
+  {
+    // unnamed email attachment
+    attachments: [{
+      body: textAttachment,
+      filename: "test.txt",
+      format: "",
+    }, {
+      body: "",
+      expectedFilename: "ForwardedMessage.eml",
+      contentType: "message/rfc822",
+    }],
+  }, {
+    // named email attachment
+    attachments: [{
+      body: textAttachment,
+      filename: "test.txt",
+      format: "",
+    }, {
+      body: "",
+      filename: "Attached Message",
+      contentType: "message/rfc822",
+    }],
+  }, {
+    attachments: [{
+      body: textAttachment,
+      filename: "test.html",
+      format: "",
+    }, {
+      body: "",
+      filename: "<iframe src=&quote;http://www.example.com&quote></iframe>.htm",
+      expectedFilename: "&lt;iframe src=&amp;quote;http://www.example.com&amp;quote&gt;&lt;/iframe&gt;.htm",
+      contentType: "text/html;",
+    }],
+  }, {
+    // no named email attachment with subject header
+    attachments: [{
+      body: "",
+      expectedFilename: "testSubject.eml",
+    }],
     bodyPart: new SyntheticPartMultiMixed([
-      new SyntheticPartLeaf('plain body text'),
+      new SyntheticPartLeaf("plain body text"),
       msgGen.makeMessage({
-        subject: '=?UTF-8?B?dGVzdFN1YmplY3Q=?=', // This string is 'testSubject'.
-        charset: 'UTF-8',
+        subject: "=?UTF-8?B?dGVzdFN1YmplY3Q=?=", // This string is 'testSubject'.
+        charset: "UTF-8",
       }),
-    ])},
+    ]),
+  },
 ];
 
-
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   index: 0, // The index of the message we're currently looking at.
 
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
     this.contents = "";
     this.stream = null;
   },
-  onStopRequest: function (aRequest, aStatusCode) {
+  onStopRequest(aRequest, aStatusCode) {
     // Check that the attachments' filenames are as expected. Just use a regex
     // here because it's simple.
     let regex = /<legend class="mimeAttachmentHeaderName">(.*?)<\/legend>/gi;
 
     for (let attachment of messages[this.index].attachments) {
       let match = regex.exec(this.contents);
       Assert.notEqual(match, null);
       Assert.equal(match[1], attachment.expectedFilename || attachment.filename);
     }
     Assert.equal(regex.exec(this.contents), null);
 
     this.index++;
     async_driver();
   },
 
   // nsIStreamListener part
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this.stream === null) {
       this.stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this.stream.init(aInputStream);
     }
     this.contents += this.stream.read(aCount);
   },
 };
 
 var gMessageHeaderSink = {
-  handleAttachment: function(aContentType, aUrl, aDisplayName, aUri,
-                             aIsExternalAttachment) {},
-  addAttachmentField: function(aName, aValue) {},
+  handleAttachment(aContentType, aUrl, aDisplayName, aUri, aIsExternalAttachment) {},
+  addAttachmentField(aName, aValue) {},
 
   // stub functions from nsIMsgHeaderSink
-  onStartHeaders: function() {},
-  onEndHeaders: function() {},
-  processHeaders: function(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
-  onEndAllAttachments: function() {},
-  onEndMsgDownload: function() {},
-  onEndMsgHeaders: function(aUrl) {},
-  onMsgHasRemoteContent: function(aMsgHdr, aContentURI) {},
+  onStartHeaders() {},
+  onEndHeaders() {},
+  processHeaders(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
+  onEndAllAttachments() {},
+  onEndMsgDownload() {},
+  onEndMsgHeaders(aUrl) {},
+  onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
   securityInfo: null,
   mDummyMsgHeader: null,
   properties: null,
-  resetProperties: function () {}
+  resetProperties() {},
 };
 
 var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
                   .createInstance(Ci.nsIMsgWindow);
 msgWindow.msgHeaderSink = gMessageHeaderSink;
 
 function* test_message_attachments(info) {
   let synMsg = gMessageGenerator.makeMessage(info);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     "header=filter",
-    false);
+    false
+  );
 
   yield false;
 }
 
 /* ===== Driver ===== */
 
 var tests = [
   parameterizeTest(test_message_attachments, messages),
--- a/mailnews/mime/test/unit/test_mimeContentType.js
+++ b/mailnews/mime/test/unit/test_mimeContentType.js
@@ -1,71 +1,70 @@
 /* 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/. */
 
-function run_test()
-{
-  const headers =
-  [
-    { header:
+function run_test() {
+  const headers = [
+    {
+      header:
       "Content-Type: text/plain\r\n" +
       "Content-Disposition: inline\r\n" +
       "\r\n",
       result:
-      "text/plain"
-    },
-    { header:
+      "text/plain",
+    }, {
+      header:
       "Content-Type:\r\n" +
       "\tapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet\r\n" +
       "Content-Transfer-Encoding: base64\r\n" +
       "Content-Disposition: attachment; filename=\"List.xlsx\"\r\n" +
       "\r\n",
       result:
-      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
-    },
-    { header:
+      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+    }, {
+      header:
       "Content-Type: \r\n" +
       " application/vnd.openxmlformats-officedocument.presentationml.presentation;\r\n" +
       " name=\"Presentation.pptx\"\r\n" +
       "\r\n",
       result:
       "application/vnd.openxmlformats-officedocument.presentationml.presentation;" +
-      " name=\"Presentation.pptx\""
-    },
-    { header:
+      " name=\"Presentation.pptx\"",
+    }, {
+      header:
       "Content-Type:\r\n" +
       "text/plain; charset=utf-8\r\n" +
       "Content-Transfer-Encoding: quoted-printable\r\n" +
       "Content-Disposition: inline\r\n" +
       "\r\n",
       result:
-      ""
-    },
-    { header:
+      "",
+    }, {
+      header:
       "Content-Type:\r\n" +
       "\r\n",
       result:
-      ""
-    },
-    /* possible crash case for Bug 574961 */
-    { header:
+      "",
+    }, {
+      /* possible crash case for Bug 574961 */
+      header:
       "Content-Type: \r\n" +
       "                                " +
       "                                " +
       "                                " +
       "                                " +
       "                                " +
       "                                " +
       "                                " +
       "                                " +
       "              \r\n",
       result:
       "",
-    }
+    },
   ];
 
   let mimeHdr = Cc["@mozilla.org/messenger/mimeheaders;1"]
                   .createInstance(Ci.nsIMimeHeaders);
 
   for (let i = 0; i < headers.length; i++) {
     mimeHdr.initialize(headers[i].header);
     let receivedHeader = mimeHdr.extractHeader("Content-Type", false);
--- a/mailnews/mime/test/unit/test_mimeStreaming.js
+++ b/mailnews/mime/test/unit/test_mimeStreaming.js
@@ -4,78 +4,77 @@
 
 /**
  * This test iterates over the test files in gTestFiles, and streams
  * each as a message and makes sure the streaming doesn't assert or crash.
  */
 const {localAccountUtils} = ChromeUtils.import("resource://testing-common/mailnews/localAccountUtils.js");
 var {IOUtils} = ChromeUtils.import("resource:///modules/IOUtils.js");
 
-var gTestFiles =[
+var gTestFiles = [
   "../../../data/bug505221",
   "../../../data/bug513543",
 ];
 
 var gMsgEnumerator;
 
 var gMessenger = Cc["@mozilla.org/messenger;1"].
                    createInstance(Ci.nsIMessenger);
 
 var gUrlListener = {
-  OnStartRunningUrl: function (aUrl) {
+  OnStartRunningUrl(aUrl) {
   },
-  OnStopRunningUrl: function (aUrl, aExitCode) {
+  OnStopRunningUrl(aUrl, aExitCode) {
     do_test_finished();
   },
 };
 
 
 localAccountUtils.loadLocalMailAccount();
 
-function run_test()
-{
+function run_test() {
   do_test_pending();
   localAccountUtils.inboxFolder.QueryInterface(Ci.nsIMsgLocalMailFolder);
   for (let fileName of gTestFiles) {
     localAccountUtils.inboxFolder.addMessage(IOUtils.loadFileToString(do_get_file(fileName)));
-  };
+  }
   gMsgEnumerator = localAccountUtils.inboxFolder.msgDatabase.EnumerateMessages();
   doNextTest();
 }
 
-function streamMsg(msgHdr)
-{
+function streamMsg(msgHdr) {
   let msgURI = localAccountUtils.inboxFolder.getUriForMsg(msgHdr);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     null,
     gUrlListener,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
-    true);
+    true
+  );
 }
 
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
-  _stream : null,
+  _stream: null,
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
   },
-  onStopRequest: function (aRequest, aStatusCode) {
+  onStopRequest(aRequest, aStatusCode) {
     doNextTest();
   },
 
   /* okay, our onDataAvailable should actually never be called.  the stream
      converter is actually eating everything except the start and stop
      notification. */
   // nsIStreamListener part
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this._stream === null) {
       this._stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this._stream.init(aInputStream);
     }
     this._stream.read(aCount);
   },
 };
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser1.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser1.js
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
  * Test suite for nsIMsgHeaderParser functions.
  */
 
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
-  var checks =
-  [
+  var checks = [
     ["", "test@foo.invalid", "test@foo.invalid"],
     ["Test", "test@foo.invalid", "Test <test@foo.invalid>"],
     ["Test", "\"abc!x.yz\"@foo.invalid", "Test <\"abc!x.yz\"@foo.invalid>"],
     ["Test", "test.user@foo.invalid", "Test <test.user@foo.invalid>"],
     ["Test", "test@[xyz!]", "Test <test@[xyz!]>"],
     // Based on RFC 2822 A.1.1
     ["John Doe", "jdoe@machine.example", "John Doe <jdoe@machine.example>"],
     // Next 2 tests Based on RFC 2822 A.1.2
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser2.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser2.js
@@ -9,18 +9,17 @@
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
   // In this array, the sub arrays consist of the following elements:
   // 0: input string (a comma separated list of recipients)
   // 1: expected output from extractHeaderAddressMailboxes
   // 2: list of recipient names in the string
   // 3: first recipient name in the string
-  const checks =
-  [
+  const checks = [
     ["abc@foo.invalid",
      "abc@foo.invalid",
      "abc@foo.invalid",
      "abc@foo.invalid" ],
     ["foo <ghj@foo.invalid>",
      "ghj@foo.invalid",
      "foo",
      "foo" ],
@@ -46,31 +45,31 @@ function run_test() {
      "john.q.public@example.com, \"abc!x.yz\"@foo.invalid, test@[xyz!], sysservices@example.net",
      "Joe Q. Public, Test, Test, Giant; \"Big\" Box",
      // extractFirstName returns unquoted names, hence the difference.
      "Joe Q. Public" ],
     // Bug 549931
     ["Undisclosed recipients:;",
      "", // Mailboxes
      "", // Address Names
-     ""] // Address Name
+     ""], // Address Name
   ];
 
   // this used to cause memory read overruns
   let addresses = {}, names = {}, fullAddresses = {};
   MailServices.headerParser.parseHeadersWithArray("\" \"@a a;b", addresses, names, fullAddresses);
 
   // Test - empty strings
 
   Assert.equal(MailServices.headerParser.extractHeaderAddressMailboxes(""), "");
   Assert.equal(MailServices.headerParser.extractFirstName(""), "");
 
   // Test - extractHeaderAddressMailboxes
 
   for (let i = 0; i < checks.length; ++i) {
     Assert.equal(MailServices.headerParser.extractHeaderAddressMailboxes(checks[i][0]), checks[i][1]);
-    let names = MailServices.headerParser.parseDecodedHeader(checks[i][0])
-                                         .map(addr => addr.name || addr.email)
-                                         .join(", ");
-    Assert.equal(names, checks[i][2]);
+    let _names = MailServices.headerParser.parseDecodedHeader(checks[i][0])
+                                          .map(addr => addr.name || addr.email)
+                                          .join(", ");
+    Assert.equal(_names, checks[i][2]);
     Assert.equal(MailServices.headerParser.extractFirstName(checks[i][0]), checks[i][3]);
   }
 }
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser3.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser3.js
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
  * Test suite for nsIMsgHeaderParser function removeDuplicateAddresses:
  */
 
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
-  const checks =
-  [
+  const checks = [
     { addrs: "test@foo.invalid",
       otherAddrs: "",
       expectedResult: "test@foo.invalid" },
     { addrs: "foo bar <test@foo.invalid>",
       otherAddrs: "",
       expectedResult: "foo bar <test@foo.invalid>" },
     { addrs: "foo bar <test@foo.invalid>, abc@foo.invalid",
       otherAddrs: "",
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
@@ -1,18 +1,17 @@
 /* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
  * Test suite for nsIMsgHeaderParser::makeFromDisplayAddress
  */
 
 var {MailServices} = ChromeUtils.import("resource:///modules/MailServices.jsm");
 
 function run_test() {
-  const checks =
-  [
+  const checks = [
     { displayString: "",
       addresses: [] },
     { displayString: "test@foo.invalid",
       addresses: [["", "test@foo.invalid"]] },
     { displayString: "test@foo.invalid, test2@foo.invalid",
       addresses: [["", "test@foo.invalid"],
                   ["", "test2@foo.invalid"]] },
     { displayString: "John Doe <test@foo.invalid>",
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser5.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser5.js
@@ -15,18 +15,17 @@ function equalArrays(arr1, arr2) {
   }
 }
 
 function run_test() {
   // In this array, the sub arrays consist of the following elements:
   // 0: input string
   // 1: expected output from parseDecodedHeader
   // 2: expected output from parseEncodedHeader
-  const checks =
-  [
+  const checks = [
     ["abc@foo.invalid",
      [{name: "", email: "abc@foo.invalid"}],
      [{name: "", email: "abc@foo.invalid"}]],
     ["foo <ghj@foo.invalid>",
      [{name: "foo", email: "ghj@foo.invalid"}],
      [{name: "foo", email: "ghj@foo.invalid"}]],
     ["abc@foo.invalid, foo <ghj@foo.invalid>",
      [{name: "", email: "abc@foo.invalid"},
--- a/mailnews/mime/test/unit/test_parser.js
+++ b/mailnews/mime/test/unit/test_parser.js
@@ -5,17 +5,17 @@
 // This file is used to test the mime parser implemented in JS, mostly by means
 // of creating custom emitters and verifying that the methods on that emitter
 // are called in the correct order. This also tests that the various
 // HeaderParser methods are run correctly.
 
 const {MimeParser} = ChromeUtils.import("resource:///modules/mimeParser.jsm");
 var {IOUtils} = ChromeUtils.import("resource:///modules/IOUtils.js");
 
-/// Utility method to compare objects
+// Utility method to compare objects
 function compare_objects(real, expected) {
   // real is a Map; convert it into an object for uneval purposes
   if (typeof real == "object") {
     var newreal = {};
     for (let [k, v] of real) {
       newreal[k] = v;
     }
     real = newreal;
@@ -23,42 +23,42 @@ function compare_objects(real, expected)
   var a = uneval(real), b = uneval(expected);
   // Very long strings don't get printed out fully (unless they're wrong)
   if ((a.length > 100 || b.length > 100) && (a == b))
     Assert.ok(a == b);
   else
     Assert.equal(a, b);
 }
 
-/// Returns and deletes object[field] if present, or undefined if not.
+// Returns and deletes object[field] if present, or undefined if not.
 function extract_field(object, field) {
   if (field in object) {
     var result = object[field];
     delete object[field];
     return result;
   }
   return undefined;
 }
 
-/// A file cache for read_file.
+// A file cache for read_file.
 var file_cache = {};
 
 /**
  * Read a file into a string (all line endings become CRLF).
  */
 function read_file(file, start, end) {
   if (!(file in file_cache)) {
     var realFile = do_get_file("../../../data/" + file);
     file_cache[file] = IOUtils.loadFileToString(realFile).split(/\r\n|[\r\n]/);
   }
   var contents = file_cache[file];
   if (start !== undefined) {
     contents = contents.slice(start - 1, end - 1);
   }
-  return contents.join('\r\n');
+  return contents.join("\r\n");
 }
 
 /**
  * Helper for body tests.
  *
  * Some extra options are listed too:
  * _split: The contents of the file will be passed in packets split by this
  *         regex. Be sure to include the split delimiter in a group so that they
@@ -75,166 +75,165 @@ function read_file(file, start, end) {
  *                 of the file from [line start, line end) [1-based lines]
  */
 function make_body_test(test, file, opts, partspec) {
   var results = partspec.map(p => [p[0], read_file(file, p[1], p[2])]);
   var msgcontents = read_file(file);
   return [test, msgcontents, opts, results];
 }
 
-/// This is the expected part specifier for the multipart-complex1 test file,
-/// specified here because it is used in several cases.
-var mpart_complex1 = [['1', 8, 10], ['2', 14, 16], ['3.1', 22, 24],
-    ['4', 29, 31], ['5', 33, 35]];
+// This is the expected part specifier for the multipart-complex1 test file,
+// specified here because it is used in several cases.
+var mpart_complex1 = [["1", 8, 10], ["2", 14, 16], ["3.1", 22, 24],
+    ["4", 29, 31], ["5", 33, 35]];
 
 // Format of tests:
 // entry[0] = name of the test
 // entry[1] = message (a string or an array of packets)
 // entry[2] = options for the MIME parser
 // entry[3] = A checker result:
 //            either a {partnum: header object} (to check headers)
 //            or a [[partnum body], [partnum body], ...] (to check bodies)
 //            (the partnums refer to the expected part numbers of the MIME test)
 // Note that for body tests, unless you're testing decoding, it is preferable to
 // use make_body_test instead of writing the array yourself.
 var parser_tests = [
   // Body tests from data
   // (Note: line numbers are 1-based. Also, to capture trailing EOF, add 2 to
   // the last line number of the file).
-  make_body_test("Basic body", "basic1", {}, [['', 3, 5]]),
-  make_body_test("Basic multipart", "multipart1", {}, [['1', 10, 12]]),
-  make_body_test("Basic multipart", "multipart2", {}, [['1', 8, 11]]),
+  make_body_test("Basic body", "basic1", {}, [["", 3, 5]]),
+  make_body_test("Basic multipart", "multipart1", {}, [["1", 10, 12]]),
+  make_body_test("Basic multipart", "multipart2", {}, [["1", 8, 11]]),
   make_body_test("Complex multipart", "multipart-complex1", {}, mpart_complex1),
   make_body_test("Truncated multipart", "multipart-complex2", {},
-    [['1.1.1.1', 21, 25], ['2', 27, 57], ['3', 60, 62]]),
+    [["1.1.1.1", 21, 25], ["2", 27, 57], ["3", 60, 62]]),
   make_body_test("No LF multipart", "multipartmalt-detach", {},
-    [['1', 20, 21], ['2.1', 27, 38], ['2.2', 42, 43], ['2.3', 47, 48]]),
-  make_body_test("Raw body", "multipart1", {bodyformat: "raw"}, [['', 4, 14]]),
+    [["1", 20, 21], ["2.1", 27, 38], ["2.2", 42, 43], ["2.3", 47, 48]]),
+  make_body_test("Raw body", "multipart1", {bodyformat: "raw"}, [["", 4, 14]]),
   ["Base64 decode 1", read_file("base64-1"), {bodyformat: "decode"},
-    [['', "\r\nHello, world! (Again...)\r\n\r\nLet's see how well base64 text" +
+    [["", "\r\nHello, world! (Again...)\r\n\r\nLet's see how well base64 text" +
           " is handled.                            Yay, lots of spaces! There" +
           "'s even a CRLF at the end and one at the beginning, but the output" +
           " shouldn't have it.\r\n"]]],
   ["Base64 decode 2", read_file("base64-2"), {bodyformat: "decode"},
-    [['', "<html><body>This is base64 encoded HTML text, and the tags shouldn" +
+    [["", "<html><body>This is base64 encoded HTML text, and the tags shouldn" +
           "'t be stripped.\r\n<b>Bold text is bold!</b></body></html>\r\n"]]],
-  make_body_test("Base64 nodecode", "base64-1", {}, [['', 4, 9]]),
-  ["QP decode", read_file("bug505221"), {pruneat: '1', bodyformat: "decode"},
-    [['1', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">\r'  +
+  make_body_test("Base64 nodecode", "base64-1", {}, [["", 4, 9]]),
+  ["QP decode", read_file("bug505221"), {pruneat: "1", bodyformat: "decode"},
+    [["1", '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">\r' +
            '\n<HTML><HEAD>\r\n<META HTTP-EQUIV="Content-Type" CONTENT="text/h' +
            'tml; charset=us-ascii">\r\n\r\n\r\n<META content="MSHTML 6.00.600' +
            '0.16735" name=GENERATOR></HEAD>\r\n<BODY> bbb\r\n</BODY></HTML>']]],
 
   // Comprehensive tests from the torture test
   make_body_test("Torture regular body", "mime-torture", {}, [
-    ['1', 17, 21], ['2$.1', 58, 75], ['2$.2.1', 83, 97], ['2$.3', 102, 130],
-    ['3$', 155, 7742], ['4', 7747, 8213], ['5', 8218, 8242],
-    ['6$.1.1', 8284, 8301], ['6$.1.2', 8306, 8733], ['6$.2.1', 8742, 9095],
-    ['6$.2.2', 9100, 9354], ['6$.2.3', 9357, 11794], ['6$.2.4', 11797, 12155],
-    ['6$.3', 12161, 12809], ['7$.1', 12844, 12845], ['7$.2', 12852, 13286],
-    ['7$.3', 13288, 13297], ['8$.1', 13331, 13358], ['8$.2', 13364, 13734],
-    ['9$', 13757, 20179], ['10', 20184, 21200], ['11$.1', 21223, 22031],
-    ['11$.2', 22036, 22586], ['12$.1', 22607, 23469], ['12$.2', 23474, 23774],
-    ['12$.3$.1', 23787, 23795], ['12$.3$.2.1', 23803, 23820],
-    ['12$.3$.2.2', 23825, 24633], ['12$.3$.3', 24640, 24836],
-    ['12$.3$.4$', 24848, 25872]]),
-  make_body_test("Torture pruneat", "mime-torture", {"pruneat": '4'},
-    [['4', 7747, 8213]]),
+    ["1", 17, 21], ["2$.1", 58, 75], ["2$.2.1", 83, 97], ["2$.3", 102, 130],
+    ["3$", 155, 7742], ["4", 7747, 8213], ["5", 8218, 8242],
+    ["6$.1.1", 8284, 8301], ["6$.1.2", 8306, 8733], ["6$.2.1", 8742, 9095],
+    ["6$.2.2", 9100, 9354], ["6$.2.3", 9357, 11794], ["6$.2.4", 11797, 12155],
+    ["6$.3", 12161, 12809], ["7$.1", 12844, 12845], ["7$.2", 12852, 13286],
+    ["7$.3", 13288, 13297], ["8$.1", 13331, 13358], ["8$.2", 13364, 13734],
+    ["9$", 13757, 20179], ["10", 20184, 21200], ["11$.1", 21223, 22031],
+    ["11$.2", 22036, 22586], ["12$.1", 22607, 23469], ["12$.2", 23474, 23774],
+    ["12$.3$.1", 23787, 23795], ["12$.3$.2.1", 23803, 23820],
+    ["12$.3$.2.2", 23825, 24633], ["12$.3$.3", 24640, 24836],
+    ["12$.3$.4$", 24848, 25872]]),
+  make_body_test("Torture pruneat", "mime-torture", {"pruneat": "4"},
+    [["4", 7747, 8213]]),
 ];
 
 function test_parser(message, opts, results) {
   var checkingHeaders = !(results instanceof Array);
   var calls = 0, dataCalls = 0;
   var fusingParts = extract_field(opts, "_nofuseparts") === undefined;
   var emitter = {
     stack: [],
     startMessage: function emitter_startMsg() {
       Assert.equal(this.stack.length, 0);
       calls++;
-      this.partData = '';
+      this.partData = "";
     },
     endMessage: function emitter_endMsg() {
       Assert.equal(this.stack.length, 0);
       calls++;
     },
     startPart: function emitter_startPart(partNum, headers) {
       this.stack.push(partNum);
       if (checkingHeaders) {
         Assert.ok(partNum in results);
         compare_objects(headers, results[partNum]);
         if (fusingParts)
-          Assert.equal(this.partData, '');
+          Assert.equal(this.partData, "");
       }
     },
     deliverPartData: function emitter_partData(partNum, data) {
       Assert.equal(this.stack[this.stack.length - 1], partNum);
       try {
         if (!checkingHeaders) {
-          if (fusingParts)
+          if (fusingParts) {
             this.partData += data;
-          else {
+          } else {
             Assert.equal(partNum, results[dataCalls][0]);
             compare_objects(data, results[dataCalls][1]);
           }
         }
       } finally {
         if (!fusingParts)
           dataCalls++;
       }
     },
     endPart: function emitter_endPart(partNum) {
-      if (this.partData != '') {
+      if (this.partData != "") {
         Assert.equal(partNum, results[dataCalls][0]);
         compare_objects(this.partData, results[dataCalls][1]);
         dataCalls++;
-        this.partData = '';
+        this.partData = "";
       }
       Assert.equal(this.stack.pop(), partNum);
-    }
+    },
   };
-  opts.onerror = function (e) { throw e; };
+  opts.onerror = function(e) { throw e; };
   MimeParser.parseSync(message, emitter, opts);
   Assert.equal(calls, 2);
   if (!checkingHeaders)
     Assert.equal(dataCalls, results.length);
 }
 
-var ATTACH = MimeParser.HEADER_PARAMETER;
 // Format of tests:
 // entry[0] = header
 // entry[1] = flags
 // entry[2] = result to match
 var header_tests = [
   // Parameter passing
   ["multipart/related", MimeParser.HEADER_PARAMETER, ["multipart/related", {}]],
   ["a ; b=v", MimeParser.HEADER_PARAMETER, ["a", {"b": "v"}]],
   ["a ; b='v'", MimeParser.HEADER_PARAMETER, ["a", {"b": "'v'"}]],
   ['a; b = "v"', MimeParser.HEADER_PARAMETER, ["a", {"b": "v"}]],
   ["a;b=1;b=2", MimeParser.HEADER_PARAMETER, ["a", {"b": "1"}]],
   ["a;b=2;b=1", MimeParser.HEADER_PARAMETER, ["a", {"b": "2"}]],
   ['a;b="a;b"', MimeParser.HEADER_PARAMETER, ["a", {"b": "a;b"}]],
   ['a;b="\\\\"', MimeParser.HEADER_PARAMETER, ["a", {"b": "\\"}]],
   ['a;b="a\\b\\c"', MimeParser.HEADER_PARAMETER, ["a", {"b": "abc"}]],
-  ['a;b=1;c=2', MimeParser.HEADER_PARAMETER, ["a", {"b": "1", "c": "2"}]],
+  ["a;b=1;c=2", MimeParser.HEADER_PARAMETER, ["a", {"b": "1", "c": "2"}]],
   ['a;b="a\\', MimeParser.HEADER_PARAMETER, ["a", {"b": "a"}]],
-  ['a;b', MimeParser.HEADER_PARAMETER, ["a", {}]],
-  ['a;b=";";c=d', MimeParser.HEADER_PARAMETER, ["a", {"b": ';', 'c': "d"}]],
+  ["a;b", MimeParser.HEADER_PARAMETER, ["a", {}]],
+  ['a;b=";";c=d', MimeParser.HEADER_PARAMETER, ["a", {"b": ";", "c": "d"}]],
 ];
 
 function test_header(headerValue, flags, expected) {
   let result = MimeParser.parseHeaderField(headerValue, flags);
   Assert.equal(result.preSemi, expected[0]);
   compare_objects(result, expected[1]);
 }
 
 function run_test() {
   for (let test of parser_tests) {
     dump("Testing message " + test[0]);
     if (test[1] instanceof Array)
       dump(" using " + test[1].length + " packets");
-    dump('\n');
+    dump("\n");
     test_parser(test[1], test[2], test[3]);
   }
   for (let test of header_tests) {
     dump("Testing value ->" + test[0] + "<- with flags " + test[1] + "\n");
     test_header(test[0], test[1], test[2]);
   }
 }
--- a/mailnews/mime/test/unit/test_rfc822_body.js
+++ b/mailnews/mime/test/unit/test_rfc822_body.js
@@ -1,88 +1,95 @@
 /* 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 test verifies that we emit a message/rfc822 body part as an attachment
  * whether or not mail.inline_attachments is true.
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
 var msgGen = gMessageGenerator = new MessageGenerator();
 
 var messages = [
-  // a message whose body is itself a message
-  { bodyPart: msgGen.makeMessage(),
+  {
+    // a message whose body is itself a message
+    bodyPart: msgGen.makeMessage(),
     attachmentCount: inline => 1,
-  },
-  // a message whose body is itself a message, and which has an attachment
-  { bodyPart: msgGen.makeMessage({
-      attachments: [{ body: "I'm an attachment!",
-                      filename: "attachment.txt",
-                      format: "" }]
+  }, {
+    // a message whose body is itself a message, and which has an attachment
+    bodyPart: msgGen.makeMessage({
+      attachments: [{
+        body: "I'm an attachment!",
+        filename: "attachment.txt",
+        format: "",
+      }],
     }),
     attachmentCount: inline => inline ? 2 : 1,
   },
 ];
 
 var gStreamListener = {
   stream: null,
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
   },
-  onStopRequest: function (aRequest, aStatusCode) {
+  onStopRequest(aRequest, aStatusCode) {
     Assert.equal(gMessageHeaderSink.attachmentCount,
                  this.expectedAttachmentCount);
     async_driver();
   },
 
   // nsIStreamListener part
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this.stream === null) {
       this.stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this.stream.init(aInputStream);
     }
-  }
+  },
 };
 
 var gMessageHeaderSink = {
   attachmentCount: 0,
 
-  handleAttachment: function(aContentType, aUrl, aDisplayName, aUri,
-                             aIsExternalAttachment) {
+  handleAttachment(aContentType, aUrl, aDisplayName, aUri, aIsExternalAttachment) {
     this.attachmentCount++;
   },
 
   // stub functions from nsIMsgHeaderSink
-  addAttachmentField: function(aName, aValue) {},
-  onStartHeaders: function() {},
-  onEndHeaders: function() {},
-  processHeaders: function(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
-  onEndAllAttachments: function() {},
-  onEndMsgDownload: function() {},
-  onEndMsgHeaders: function(aUrl) {},
-  onMsgHasRemoteContent: function(aMsgHdr, aContentURI) {},
+  addAttachmentField(aName, aValue) {},
+  onStartHeaders() {},
+  onEndHeaders() {},
+  processHeaders(aHeaderNames, aHeaderValues, dontCollectAddrs) {},
+  onEndAllAttachments() {},
+  onEndMsgDownload() {},
+  onEndMsgHeaders(aUrl) {},
+  onMsgHasRemoteContent(aMsgHdr, aContentURI) {},
   securityInfo: null,
   mDummyMsgHeader: null,
   properties: null,
-  resetProperties: function () {
+  resetProperties() {
     this.attachmentCount = 0;
   },
 };
 
 var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
                   .createInstance(Ci.nsIMsgWindow);
 msgWindow.msgHeaderSink = gMessageHeaderSink;
 
@@ -91,17 +98,17 @@ function* help_test_rfc822_body(info, in
   let synMsg = gMessageGenerator.makeMessage(info);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
   gStreamListener.expectedAttachmentCount = info.attachmentCount(inline);
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
     false);
--- a/mailnews/mime/test/unit/test_smime_decrypt.js
+++ b/mailnews/mime/test/unit/test_smime_decrypt.js
@@ -5,23 +5,26 @@
 /**
  * Tests to ensure signed and/or encrypted S/MIME messages are
  * processed correctly, and the signature status is treated as good
  * or bad as expected.
  */
 
 var {PromiseTestUtils} = ChromeUtils.import("resource://testing-common/mailnews/PromiseTestUtils.jsm");
 var {PromiseUtils } = ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
-var {localAccountUtils} = ChromeUtils.import("resource://testing-common/mailnews/localAccountUtils.js");
-var {IOUtils} = ChromeUtils.import("resource:///modules/IOUtils.js");
 var {SmimeUtils} = ChromeUtils.import("resource://testing-common/mailnews/smimeUtils.jsm");
 
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 let gCertValidityResult = 0;
 
 /**
  * @implements nsICertVerificationCallback
@@ -60,17 +63,17 @@ add_task(async function verifyTestCertsS
   let prom = testCertValidity(cert, now);
   await prom;
 
   if (gCertValidityResult != 0) {
     // Either certs have expired, or something else is going wrong.
     // Let's test if they were valid a week ago, for a better guess.
 
     let oneWeekAgo = now - (7 * 24 * 60 * 60);
-    let prom = testCertValidity(cert, oneWeekAgo);
+    prom = testCertValidity(cert, oneWeekAgo);
     await prom;
 
     if (gCertValidityResult == 0) {
       Assert.ok(false,
        "The S/MIME test certificates are invalid today, but were valid one week ago. " +
        "Most likely they have expired and new certificates need to be generated and committed. " +
        "Follow the instructions in comm/mailnews/test/data/smime/README.md");
     } else {
@@ -85,46 +88,46 @@ add_task(async function verifyTestCertsS
 });
 
 var gInbox;
 
 var smimeDataDirectory = "../../../data/smime/";
 
 let smimeHeaderSink = {
   expectResults(maxLen) {
-    //dump("Restarting for next test\n");
+    // dump("Restarting for next test\n");
     this._deferred = PromiseUtils.defer();
     this._expectedLen = maxLen;
     this._results = [];
     return this._deferred.promise;
   },
   maxWantedNesting() { return 2; },
   signedStatus(aNestingLevel, aSignedStatus, aSignerCert) {
-    //dump("Signed message\n");
+    // dump("Signed message\n");
     Assert.equal(aNestingLevel, 1);
     this._results.push({
       type: "signed",
       status: aSignedStatus,
-      certificate: aSignerCert
+      certificate: aSignerCert,
     });
     if (this._results.length == this._expectedLen)
       this._deferred.resolve(this._results);
   },
   encryptionStatus(aNestingLevel, aEncryptedStatus, aRecipientCert) {
-    //dump("Encrypted message\n");
+    // dump("Encrypted message\n");
     Assert.equal(aNestingLevel, 1);
     this._results.push({
       type: "encrypted",
       status: aEncryptedStatus,
-      certificate: aRecipientCert
+      certificate: aRecipientCert,
     });
     if (this._results.length == this._expectedLen)
       this._deferred.resolve(this._results);
   },
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgSMIMEHeaderSink])
+  QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgSMIMEHeaderSink]),
 };
 
 /**
  * Note on filenames taken from the NSS test suite:
  * - env: CMS enveloped (encrypted)
  * - dsig: CMS detached signature (with multipart MIME)
  * - sig: CMS opaque signature (content embedded inside signature)
  * - bad: message text does not match signature
@@ -204,28 +207,28 @@ add_task(async function copy_messages() 
 add_task(async function check_smime_message() {
   await gCopyWaiter.promise;
 
   let hdrIndex = 0;
 
   for (let msg of gMessages) {
     let numExpected = 1;
     if (msg.enc && msg.sig) {
-      numExpected++
+      numExpected++;
     }
 
     let hdr = mailTestUtils.getMsgHdrN(gInbox, hdrIndex);
     let uri = hdr.folder.getUriForMsg(hdr);
     let sinkPromise = smimeHeaderSink.expectResults(numExpected);
 
     let conversion = apply_mime_conversion(uri, {securityInfo: smimeHeaderSink});
     await conversion.promise;
 
     let contents = conversion._data;
-    //dump("contents: " + contents + "\n");
+    // dump("contents: " + contents + "\n");
 
     if (!msg.sig || msg.sig_good) {
       // Check that the plaintext body is in there.
       Assert.ok(contents.includes("This is a test message from Alice to Bob."));
     }
     // Check that we're also using the display output.
     Assert.ok(contents.includes("<html>"));
 
--- a/mailnews/mime/test/unit/test_structured_headers.js
+++ b/mailnews/mime/test/unit/test_structured_headers.js
@@ -2,17 +2,17 @@
  * 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 tests the msgIStructuredHeaders and msgIWritableStructuredHeaders
 // interfaces.
 
 var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
-/// Verify that a specific XPCOM error code is thrown.
+// Verify that a specific XPCOM error code is thrown.
 function verifyError(block, errorCode) {
   let caught = undefined;
   try {
     block();
   } catch (actual) {
     caught = actual.result;
   }
   Assert.equal(caught, errorCode);
@@ -127,17 +127,17 @@ add_task(async function check_raw() {
   // Check that copying works
   let moreHeaders = new StructuredHeaders();
   moreHeaders.addAllHeaders(headers);
   for (let value of headers.headerNames) {
     Assert.equal(moreHeaders.getHeader(value), headers.getHeader(value));
   }
   headers.deleteHeader("Date");
   Assert.ok(moreHeaders.hasHeader("Date"));
-})
+});
 
 add_task(async function check_nsIMimeHeaders() {
   let headers = Cc["@mozilla.org/messenger/mimeheaders;1"]
                   .createInstance(Ci.nsIMimeHeaders);
   Assert.ok(headers instanceof Ci.msgIStructuredHeaders);
   Assert.equal(false, headers instanceof Ci.msgIWritableStructuredHeaders);
   headers.initialize(mailTestUtils.loadFileToString(
     do_get_file("../../../data/draft1")));
@@ -176,12 +176,8 @@ add_task(async function checkBuildMimeTe
   let utf8Text = mimeText.replace("☃", "\xe2\x98\x83");
   let mimeHeaders = Cc["@mozilla.org/messenger/mimeheaders;1"]
                       .createInstance(Ci.nsIMimeHeaders);
   mimeHeaders.initialize(utf8Text);
   Assert.equal(mimeHeaders.getHeader("To")[0].email, "user@☃.invalid");
   Assert.equal(mimeHeaders.buildMimeText(), mimeText);
   Assert.equal(mimeHeaders.allHeaders, utf8Text);
 });
-
-function run_test() {
-  run_next_test();
-}
--- a/mailnews/mime/test/unit/test_text_attachment.js
+++ b/mailnews/mime/test/unit/test_text_attachment.js
@@ -1,63 +1,71 @@
 /* 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 test verifies that we don't display text attachments inline
  * when mail.inline_attachments is false.
  */
+/* import-globals-from ../../../test/resources/logHelper.js */
+/* import-globals-from ../../../test/resources/asyncTestUtils.js */
+/* import-globals-from ../../../test/resources/messageGenerator.js */
+/* import-globals-from ../../../test/resources/messageModifier.js */
+/* import-globals-from ../../../test/resources/messageInjection.js */
 load("../../../resources/logHelper.js");
 load("../../../resources/asyncTestUtils.js");
 
 load("../../../resources/messageGenerator.js");
 load("../../../resources/messageModifier.js");
 load("../../../resources/messageInjection.js");
 
 var gMessenger = Cc["@mozilla.org/messenger;1"]
                    .createInstance(Ci.nsIMessenger);
 
 // Create a message generator
-var msgGen = gMessageGenerator = new MessageGenerator();
+var gMessageGenerator = new MessageGenerator();
 
 var textAttachment =
   "inline text attachment";
 
 // create a message with a text attachment
 var messages = [
-  // text attachment
-  { attachments: [{ body: textAttachment,
-                    filename: 'test.txt',
-                    format: '' }]},
-  ];
-
+  {
+    // text attachment
+    attachments: [{
+      body: textAttachment,
+      filename: "test.txt",
+      format: "",
+    }],
+  },
+];
 
 var gStreamListener = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIStreamListener]),
 
   _str: "",
   // nsIRequestObserver part
-  onStartRequest: function (aRequest) {
+  onStartRequest(aRequest) {
     this.str = "";
     this._stream = null;
   },
-  onStopRequest: function (aRequest, aStatusCode) {
+  onStopRequest(aRequest, aStatusCode) {
     // check that text attachment contents didn't end up inline.
     Assert.ok(!this._str.includes(textAttachment));
     async_driver();
   },
 
   /* okay, our onDataAvailable should actually never be called.  the stream
      converter is actually eating everything except the start and stop
      notification. */
   // nsIStreamListener part
-  _stream : null,
+  _stream: null,
 
-  onDataAvailable: function (aRequest, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aInputStream, aOffset, aCount) {
     if (this._stream === null) {
       this._stream = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       this._stream.init(aInputStream);
     }
     this._str += this._stream.read(aCount);
   },
 };
@@ -70,17 +78,17 @@ function* test_message_attachments(info,
   Services.prefs.setBoolPref("mail.inline_attachments.text", inline_text);
   let synMsg = gMessageGenerator.makeMessage(info);
   let synSet = new SyntheticMessageSet([synMsg]);
   yield add_sets_to_folder(gInbox, [synSet]);
 
   let msgURI = synSet.getMsgURI(0);
   let msgService = gMessenger.messageServiceFromURI(msgURI);
 
-  let streamURI = msgService.streamMessage(
+  msgService.streamMessage(
     msgURI,
     gStreamListener,
     msgWindow,
     null,
     true, // have them create the converter
     // additional uri payload, note that "header=" is prepended automatically
     "filter",
     false);