Bug 702300 (part 1) - Use |let| instead of |var| in aboutMemory.js and its tests. r=jschoenick.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 16 Feb 2012 22:09:13 -0800
changeset 88771 a22548d04fc3cd10c339a39243a66060c554b08b
parent 88770 dec32ab636c6bf0d9afaaa89ee3581d8b7044181
child 88772 49bae78a33a79c03928903a2d4c9db0dbec91191
push id975
push userffxbld
push dateTue, 13 Mar 2012 21:39:16 +0000
treeherdermozilla-aurora@99faebf9dc36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjschoenick
bugs702300
milestone13.0a1
Bug 702300 (part 1) - Use |let| instead of |var| in aboutMemory.js and its tests. r=jschoenick.
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/components/aboutmemory/content/aboutMemory.xhtml
toolkit/components/aboutmemory/tests/test_aboutmemory.xul
toolkit/components/aboutmemory/tests/test_aboutmemory2.xul
toolkit/components/aboutmemory/tests/test_sqliteMultiReporter.xul
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -39,17 +39,17 @@
 "use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const gVerbose = location.href === "about:memory?verbose";
 
-var gAddedObserver = false;
+let gAddedObserver = false;
 
 const KIND_NONHEAP           = Ci.nsIMemoryReporter.KIND_NONHEAP;
 const KIND_HEAP              = Ci.nsIMemoryReporter.KIND_HEAP;
 const KIND_OTHER             = Ci.nsIMemoryReporter.KIND_OTHER;
 const UNITS_BYTES            = Ci.nsIMemoryReporter.UNITS_BYTES;
 const UNITS_COUNT            = Ci.nsIMemoryReporter.UNITS_COUNT;
 const UNITS_COUNT_CUMULATIVE = Ci.nsIMemoryReporter.UNITS_COUNT_CUMULATIVE;
 const UNITS_PERCENTAGE       = Ci.nsIMemoryReporter.UNITS_PERCENTAGE;
@@ -121,89 +121,89 @@ const kTreeNames = {
   'other':    'Other Measurements'
 };
 
 const kMapTreePaths =
   ['smaps/resident', 'smaps/pss', 'smaps/vsize', 'smaps/swap'];
 
 function onLoad()
 {
-  var os = Cc["@mozilla.org/observer-service;1"].
+  let os = Cc["@mozilla.org/observer-service;1"].
       getService(Ci.nsIObserverService);
   os.notifyObservers(null, "child-memory-reporter-request", null);
 
   os.addObserver(ChildMemoryListener, "child-memory-reporter-update", false);
   gAddedObserver = true;
 
   update();
 }
 
 function onUnload()
 {
   // We need to check if the observer has been added before removing; in some
   // circumstances (eg. reloading the page quickly) it might not have because
   // onLoad might not fire.
   if (gAddedObserver) {
-    var os = Cc["@mozilla.org/observer-service;1"].
+    let os = Cc["@mozilla.org/observer-service;1"].
         getService(Ci.nsIObserverService);
     os.removeObserver(ChildMemoryListener, "child-memory-reporter-update");
   }
 }
 
 function ChildMemoryListener(aSubject, aTopic, aData)
 {
   update();
 }
 
 function doGlobalGC()
 {
   Cu.forceGC();
-  var os = Cc["@mozilla.org/observer-service;1"]
+  let os = Cc["@mozilla.org/observer-service;1"]
             .getService(Ci.nsIObserverService);
   os.notifyObservers(null, "child-gc-request", null);
   update();
 }
 
 function doCC()
 {
   window.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsIDOMWindowUtils)
         .cycleCollect();
-  var os = Cc["@mozilla.org/observer-service;1"]
+  let os = Cc["@mozilla.org/observer-service;1"]
             .getService(Ci.nsIObserverService);
   os.notifyObservers(null, "child-cc-request", null);
   update();
 }
 
 // For maximum effect, this returns to the event loop between each
 // notification.  See bug 610166 comment 12 for an explanation.
 // Ideally a single notification would be enough.
 function sendHeapMinNotifications()
 {
   function runSoon(f)
   {
-    var tm = Cc["@mozilla.org/thread-manager;1"]
+    let tm = Cc["@mozilla.org/thread-manager;1"]
               .getService(Ci.nsIThreadManager);
 
     tm.mainThread.dispatch({ run: f }, Ci.nsIThread.DISPATCH_NORMAL);
   }
 
   function sendHeapMinNotificationsInner()
   {
-    var os = Cc["@mozilla.org/observer-service;1"]
+    let os = Cc["@mozilla.org/observer-service;1"]
              .getService(Ci.nsIObserverService);
     os.notifyObservers(null, "memory-pressure", "heap-minimize");
 
     if (++j < 3)
       runSoon(sendHeapMinNotificationsInner);
     else
       runSoon(update);
   }
 
-  var j = 0;
+  let j = 0;
   sendHeapMinNotificationsInner();
 }
 
 function Reporter(aUnsafePath, aKind, aUnits, aAmount, aUnsafeDesc)
 {
   this._unsafePath  = aUnsafePath;
   this._kind        = aKind;
   this._units       = aUnits;
@@ -242,53 +242,53 @@ function getReportersByProcess(aMgr)
   //   is a Reporter object.  After this point we never use the original memory
   //   reporter again.
   //
   // - Note that copying rOrig.amount (which calls a C++ function under the
   //   IDL covers) to r._amount for every reporter now means that the
   //   results as consistent as possible -- measurements are made all at
   //   once before most of the memory required to generate this page is
   //   allocated.
-  var reportersByProcess = {};
+  let reportersByProcess = {};
 
   function addReporter(aProcess, aUnsafePath, aKind, aUnits, aAmount,
                        aUnsafeDesc)
   {
-    var process = aProcess === "" ? "Main" : aProcess;
-    var r = new Reporter(aUnsafePath, aKind, aUnits, aAmount, aUnsafeDesc);
+    let process = aProcess === "" ? "Main" : aProcess;
+    let r = new Reporter(aUnsafePath, aKind, aUnits, aAmount, aUnsafeDesc);
     if (!reportersByProcess[process]) {
       reportersByProcess[process] = {};
     }
-    var reporters = reportersByProcess[process];
-    var reporter = reporters[r._unsafePath];
+    let reporters = reportersByProcess[process];
+    let reporter = reporters[r._unsafePath];
     if (reporter) {
       // Already an entry;  must be a duplicated reporter.  This can happen
       // legitimately.  Merge them.
       reporter.merge(r);
     } else {
       reporters[r._unsafePath] = r;
     }
   }
 
   // Process vanilla reporters first, then multi-reporters.
-  var e = aMgr.enumerateReporters();
+  let e = aMgr.enumerateReporters();
   while (e.hasMoreElements()) {
-    var rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
+    let rOrig = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
     try {
       addReporter(rOrig.process, rOrig.path, rOrig.kind, rOrig.units,
                   rOrig.amount, rOrig.description);
     }
     catch(e) {
       debug("An error occurred when collecting results from the memory reporter " +
             rOrig.path + ": " + e);
     }
   }
-  var e = aMgr.enumerateMultiReporters();
+  let e = aMgr.enumerateMultiReporters();
   while (e.hasMoreElements()) {
-    var mrOrig = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
+    let mrOrig = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
     // Ignore the "smaps" reporters in non-verbose mode.
     if (!gVerbose && mrOrig.name === "smaps") {
       continue;
     }
 
     try {
       mrOrig.collectReports(addReporter, null);
     }
@@ -297,60 +297,60 @@ function getReportersByProcess(aMgr)
     }
   }
 
   return reportersByProcess;
 }
 
 function appendTextNode(aP, aText)
 {
-  var e = document.createTextNode(aText);
+  let e = document.createTextNode(aText);
   aP.appendChild(e);
   return e;
 }
 
 function appendElement(aP, aTagName, aClassName)
 {
-  var e = document.createElement(aTagName);
+  let e = document.createElement(aTagName);
   if (aClassName) {
     e.className = aClassName;
   }
   aP.appendChild(e);
   return e;
 }
 
 function appendElementWithText(aP, aTagName, aClassName, aText)
 {
-  var e = appendElement(aP, aTagName, aClassName);
+  let e = appendElement(aP, aTagName, aClassName);
   appendTextNode(e, aText);
   return e;
 }
 
 /**
  * Top-level function that does the work of generating the page.
  */
 function update()
 {
   // First, clear the page contents.  Necessary because update() might be
   // called more than once due to ChildMemoryListener.
-  var oldContent = document.getElementById("content");
-  var content = oldContent.cloneNode(false);
+  let oldContent = document.getElementById("content");
+  let content = oldContent.cloneNode(false);
   oldContent.parentNode.replaceChild(content, oldContent);
   content.classList.add(gVerbose ? 'verbose' : 'non-verbose');
 
-  var mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
+  let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
       getService(Ci.nsIMemoryReporterManager);
 
   // Generate output for one process at a time.  Always start with the
   // Main process.
-  var reportersByProcess = getReportersByProcess(mgr);
-  var hasMozMallocUsableSize = mgr.hasMozMallocUsableSize;
+  let reportersByProcess = getReportersByProcess(mgr);
+  let hasMozMallocUsableSize = mgr.hasMozMallocUsableSize;
   appendProcessElements(content, "Main", reportersByProcess["Main"],
                         hasMozMallocUsableSize);
-  for (var process in reportersByProcess) {
+  for (let process in reportersByProcess) {
     if (process !== "Main") {
       appendProcessElements(content, process, reportersByProcess[process],
                             hasMozMallocUsableSize);
     }
   }
 
   appendElement(content, "hr");
 
@@ -361,47 +361,47 @@ function update()
   const MPDesc = "Send three \"heap-minimize\" notifications in a " +
                  "row.  Each notification triggers a global garbage " +
                  "collection followed by a cycle collection, and causes the " +
                  "process to reduce memory usage in other ways, e.g. by " +
                  "flushing various caches.";
 
   function appendButton(aTitle, aOnClick, aText, aId)
   {
-    var b = appendElementWithText(content, "button", "", aText);
+    let b = appendElementWithText(content, "button", "", aText);
     b.title = aTitle;
     b.onclick = aOnClick
     if (aId) {
       b.id = aId;
     }
   }
 
   // The "Update" button has an id so it can be clicked in a test.
   appendButton(UpDesc, update,                   "Update", "updateButton");
   appendButton(GCDesc, doGlobalGC,               "GC");
   appendButton(CCDesc, doCC,                     "CC");
   appendButton(MPDesc, sendHeapMinNotifications, "Minimize memory usage");
 
-  var div1 = appendElement(content, "div");
-  var a;
+  let div1 = appendElement(content, "div");
   if (gVerbose) {
-    var a = appendElementWithText(div1, "a", "option", "Less verbose");
+    let a = appendElementWithText(div1, "a", "option", "Less verbose");
     a.href = "about:memory";
   } else {
-    var a = appendElementWithText(div1, "a", "option", "More verbose");
+    let a = appendElementWithText(div1, "a", "option", "More verbose");
     a.href = "about:memory?verbose";
   }
 
-  var div2 = appendElement(content, "div");
-  a = appendElementWithText(div2, "a", "option", "Troubleshooting information");
+  let div2 = appendElement(content, "div");
+  let a = appendElementWithText(div2, "a", "option",
+                                "Troubleshooting information");
   a.href = "about:support";
 
-  var legendText1 = "Click on a non-leaf node in a tree to expand ('++') " +
+  let legendText1 = "Click on a non-leaf node in a tree to expand ('++') " +
                     "or collapse ('--') its children.";
-  var legendText2 = "Hover the pointer over the name of a memory reporter " +
+  let legendText2 = "Hover the pointer over the name of a memory reporter " +
                     "to see a description of what it measures.";
 
   appendElementWithText(content, "div", "legend", legendText1);
   appendElementWithText(content, "div", "legend", legendText2);
 }
 
 // There are two kinds of TreeNode.
 // - Leaf TreeNodes correspond to Reporters and have more properties.
@@ -422,17 +422,17 @@ function TreeNode(aUnsafeName)
   // Non-leaf TreeNodes have these properties added later:
   // - _amount (which is never |kUnknown|)
   // - _unsafeDescription
   // - _hideKids (only defined if true)
 }
 
 TreeNode.prototype = {
   findKid: function(aUnsafeName) {
-    for (var i = 0; i < this._kids.length; i++) {
+    for (let i = 0; i < this._kids.length; i++) {
       if (this._kids[i]._unsafeName === aUnsafeName) {
         return this._kids[i];
       }
     }
     return undefined;
   },
 
   toString: function() {
@@ -458,45 +458,45 @@ function buildTree(aReporters, aTreeName
 {
   // We want to process all reporters that begin with |aTreeName|.  First we
   // build the tree but only fill the properties that we can with a top-down
   // traversal.
 
   // There should always be at least one matching reporter when |aTreeName| is
   // "explicit".  But there may be zero for "smaps" trees;  if that happens,
   // bail.
-  var foundReporter = false;
-  for (var unsafePath in aReporters) {
+  let foundReporter = false;
+  for (let unsafePath in aReporters) {
     if (aReporters[unsafePath].treeNameMatches(aTreeName)) {
       foundReporter = true;
       break;
     }
   }
   if (!foundReporter) {
     assert(aTreeName !== 'explicit');
     return null;
   }
 
-  var t = new TreeNode("falseRoot");
-  for (var unsafePath in aReporters) {
+  let t = new TreeNode("falseRoot");
+  for (let unsafePath in aReporters) {
     // Add any missing nodes in the tree implied by the unsafePath.
-    var r = aReporters[unsafePath];
+    let r = aReporters[unsafePath];
     if (r.treeNameMatches(aTreeName)) {
       assert(r._kind === KIND_HEAP || r._kind === KIND_NONHEAP,
              "reporters in the tree must have KIND_HEAP or KIND_NONHEAP");
       assert(r._units === UNITS_BYTES, "r._units === UNITS_BYTES");
-      var unsafeNames = r._unsafePath.split('/');
-      var u = t;
-      for (var i = 0; i < unsafeNames.length; i++) {
-        var unsafeName = unsafeNames[i];
-        var uMatch = u.findKid(unsafeName);
+      let unsafeNames = r._unsafePath.split('/');
+      let u = t;
+      for (let i = 0; i < unsafeNames.length; i++) {
+        let unsafeName = unsafeNames[i];
+        let uMatch = u.findKid(unsafeName);
         if (uMatch) {
           u = uMatch;
         } else {
-          var v = new TreeNode(unsafeName);
+          let v = new TreeNode(unsafeName);
           u._kids.push(v);
           u = v;
         }
       }
       // Fill in extra details in the leaf node from the Reporter.
       if (r._amount !== kUnknown) {
         u._amount = r._amount;
       } else {
@@ -522,34 +522,34 @@ function buildTree(aReporters, aTreeName
   {
     if (aT._kids.length === 0) {
       // Leaf node.  Has already been filled in.
       assert(aT._kind !== undefined, "aT._kind is undefined for leaf node");
     } else {
       // Non-leaf node.  Derive its _amount and _unsafeDescription entirely
       // from its children.
       assert(aT._kind === undefined, "aT._kind is defined for non-leaf node");
-      var childrenBytes = 0;
-      for (var i = 0; i < aT._kids.length; i++) {
+      let childrenBytes = 0;
+      for (let i = 0; i < aT._kids.length; i++) {
         childrenBytes += fillInNonLeafNodes(aT._kids[i]);
       }
       aT._amount = childrenBytes;
       aT._unsafeDescription =
         "The sum of all entries below '" + aT._unsafeName + "'.";
     }
     assert(aT._amount !== kUnknown, "aT._amount !== kUnknown");
     return aT._amount;
   }
 
   fillInNonLeafNodes(t);
 
   // Reduce the depth of the tree by the number of occurrences of '/' in
   // aTreeName.  (Thus the tree named 'foo/bar/baz' will be rooted at 'baz'.)
-  var slashCount = 0;
-  for (var i = 0; i < aTreeName.length; i++) {
+  let slashCount = 0;
+  for (let i = 0; i < aTreeName.length; i++) {
     if (aTreeName[i] == '/') {
       assert(t._kids.length == 1, "Not expecting multiple kids here.");
       t = t._kids[0];
     }
   }
 
   // Set the (unsafe) description on the root node.
   t._unsafeDescription = kTreeUnsafeDescriptions[t._unsafeName];
@@ -561,18 +561,18 @@ function buildTree(aReporters, aTreeName
  * Ignore all the memory reports that belong to a "smaps" tree;  this involves
  * explicitly marking them as done.
  *
  * @param aReporters
  *        The table of Reporters, indexed by _unsafePath.
  */
 function ignoreSmapsTrees(aReporters)
 {
-  for (var unsafePath in aReporters) {
-    var r = aReporters[unsafePath];
+  for (let unsafePath in aReporters) {
+    let r = aReporters[unsafePath];
     if (r.treeNameMatches("smaps")) {
       r._done = true;
     }
   }
 }
 
 /**
  * Do some work which only makes sense for the 'explicit' tree.
@@ -583,37 +583,37 @@ function ignoreSmapsTrees(aReporters)
  *        Table of Reporters for this process, indexed by _unsafePath.
  * @return A boolean indicating if "heap-allocated" is known for the process.
  */
 function fixUpExplicitTree(aT, aReporters)
 {
   // Determine how many bytes are reported by heap reporters.
   function getKnownHeapUsedBytes(aT)
   {
-    var n = 0;
+    let n = 0;
     if (aT._kids.length === 0) {
       // Leaf node.
       assert(aT._kind !== undefined, "aT._kind is undefined for leaf node");
       n = aT._kind === KIND_HEAP ? aT._amount : 0;
     } else {
-      for (var i = 0; i < aT._kids.length; i++) {
+      for (let i = 0; i < aT._kids.length; i++) {
         n += getKnownHeapUsedBytes(aT._kids[i]);
       }
     }
     return n;
   }
 
   // A special case:  compute the derived "heap-unclassified" value.  Don't
   // mark "heap-allocated" when we get its size because we want it to appear
   // in the "Other Measurements" list.
-  var heapAllocatedReporter = aReporters["heap-allocated"];
+  let heapAllocatedReporter = aReporters["heap-allocated"];
   assert(heapAllocatedReporter, "no 'heap-allocated' reporter");
-  var heapAllocatedBytes = heapAllocatedReporter._amount;
-  var heapUnclassifiedT = new TreeNode("heap-unclassified");
-  var hasKnownHeapAllocated = heapAllocatedBytes !== kUnknown;
+  let heapAllocatedBytes = heapAllocatedReporter._amount;
+  let heapUnclassifiedT = new TreeNode("heap-unclassified");
+  let hasKnownHeapAllocated = heapAllocatedBytes !== kUnknown;
   if (hasKnownHeapAllocated) {
     heapUnclassifiedT._amount =
       heapAllocatedBytes - getKnownHeapUsedBytes(aT);
   } else {
     heapUnclassifiedT._amount = 0;
     heapUnclassifiedT._isUnknown = true;
   }
   // This kindToString() ensures the "(Heap)" prefix is set without having to
@@ -656,32 +656,33 @@ function sortTreeAndInsertAggregateNodes
 
   aT._kids.sort(TreeNode.compare);
 
   // If the first child is insignificant, they all are, and there's no point
   // creating an aggregate node that lacks siblings.  Just set the parent's
   // _hideKids property and process all children.
   if (isInsignificant(aT._kids[0])) {
     aT._hideKids = true;
-    for (var i = 0; i < aT._kids.length; i++) {
+    for (let i = 0; i < aT._kids.length; i++) {
       sortTreeAndInsertAggregateNodes(aTotalBytes, aT._kids[i]);
     }
     return;
   }
 
   // Look at all children except the last one.
-  for (var i = 0; i < aT._kids.length - 1; i++) {
+  let i;
+  for (i = 0; i < aT._kids.length - 1; i++) {
     if (isInsignificant(aT._kids[i])) {
       // This child is below the significance threshold.  If there are other
       // (smaller) children remaining, move them under an aggregate node.
-      var i0 = i;
-      var nAgg = aT._kids.length - i0;
+      let i0 = i;
+      let nAgg = aT._kids.length - i0;
       // Create an aggregate node.
-      var aggT = new TreeNode("(" + nAgg + " tiny)");
-      var aggBytes = 0;
+      let aggT = new TreeNode("(" + nAgg + " tiny)");
+      let aggBytes = 0;
       for ( ; i < aT._kids.length; i++) {
         aggBytes += aT._kids[i]._amount;
         aggT._kids.push(aT._kids[i]);
       }
       aggT._hideKids = true;
       aggT._amount = aggBytes;
       aggT._unsafeDescription =
         nAgg + " sub-trees that are below the " + kSignificanceThresholdPerc +
@@ -703,17 +704,17 @@ function sortTreeAndInsertAggregateNodes
   // is significant;  there's no point creating an aggregate node that only has
   // one child.  Just process it.
   sortTreeAndInsertAggregateNodes(aTotalBytes, aT._kids[i]);
 }
 
 // Global variable indicating if we've seen any invalid values for this
 // process;  it holds the unsafePaths of any such reporters.  It is reset for
 // each new process.
-var gUnsafePathsWithInvalidValuesForThisProcess = [];
+let gUnsafePathsWithInvalidValuesForThisProcess = [];
 
 function appendWarningElements(aP, aHasKnownHeapAllocated,
                                aHasMozMallocUsableSize)
 {
   if (!aHasKnownHeapAllocated && !aHasMozMallocUsableSize) {
     appendElementWithText(aP, "p", "", 
       "WARNING: the 'heap-allocated' memory reporter and the " +
       "moz_malloc_usable_size() function do not work for this platform " +
@@ -733,23 +734,23 @@ function appendWarningElements(aP, aHasK
       "WARNING: the moz_malloc_usable_size() function does not work for " +
       "this platform and/or configuration.  This means that much of the " +
       "heap-allocated memory is not measured by individual memory reporters " +
       "and so will fall under 'heap-unclassified'.");
     appendTextNode(aP, "\n\n");
   }
 
   if (gUnsafePathsWithInvalidValuesForThisProcess.length > 0) {
-    var div = appendElement(aP, "div");
+    let div = appendElement(aP, "div");
     appendElementWithText(div, "p", "", 
       "WARNING: the following values are negative or unreasonably large.");
     appendTextNode(div, "\n");  
 
-    var ul = appendElement(div, "ul");
-    for (var i = 0;
+    let ul = appendElement(div, "ul");
+    for (let i = 0;
          i < gUnsafePathsWithInvalidValuesForThisProcess.length;
          i++)
     {
       appendTextNode(ul, " ");
       appendElementWithText(ul, "li", "", 
         makeSafe(gUnsafePathsWithInvalidValuesForThisProcess[i]));
       appendTextNode(ul, "\n");
     }
@@ -777,27 +778,27 @@ function appendWarningElements(aP, aHasK
  */
 function appendProcessElements(aP, aProcess, aReporters,
                                aHasMozMallocUsableSize)
 {
   appendElementWithText(aP, "h1", "", aProcess + " Process");
   appendTextNode(aP, "\n\n");   // gives nice spacing when we cut and paste
 
   // We'll fill this in later.
-  var warningsDiv = appendElement(aP, "div", "accuracyWarning");
+  let warningsDiv = appendElement(aP, "div", "accuracyWarning");
 
-  var explicitTree = buildTree(aReporters, 'explicit');
-  var hasKnownHeapAllocated = fixUpExplicitTree(explicitTree, aReporters);
+  let explicitTree = buildTree(aReporters, 'explicit');
+  let hasKnownHeapAllocated = fixUpExplicitTree(explicitTree, aReporters);
   sortTreeAndInsertAggregateNodes(explicitTree._amount, explicitTree);
   appendTreeElements(aP, explicitTree, aProcess);
 
   // We only show these breakdown trees in verbose mode.
   if (gVerbose) {
     kMapTreePaths.forEach(function(t) {
-      var tree = buildTree(aReporters, t);
+      let tree = buildTree(aReporters, t);
 
       // |tree| will be null if we don't have any reporters for the given
       // unsafePath.
       if (tree) {
         sortTreeAndInsertAggregateNodes(tree._amount, tree);
         tree._hideKids = true;   // smaps trees are always initially collapsed
         appendTreeElements(aP, tree, aProcess);
       }
@@ -846,24 +847,24 @@ function hasNegativeSign(aN)
  * @return A human-readable string representing the int.
  *
  * Note: building an array of chars and converting that to a string with
  * Array.join at the end is more memory efficient than using string
  * concatenation.  See bug 722972 for details.
  */
 function formatInt(aN, aExtra)
 {
-  var neg = false;
+  let neg = false;
   if (hasNegativeSign(aN)) {
     neg = true;
     aN = -aN;
   }
-  var s = [];
+  let s = [];
   while (true) {
-    var k = aN % 1000;
+    let k = aN % 1000;
     aN = Math.floor(aN / 1000);
     if (aN > 0) {
       if (k < 10) {
         s.unshift(",00", k);
       } else if (k < 100) {
         s.unshift(",0", k);
       } else {
         s.unshift(",", k);
@@ -886,24 +887,24 @@ function formatInt(aN, aExtra)
  * Converts a byte count to an appropriate string representation.
  *
  * @param aBytes
  *        The byte count.
  * @return The string representation.
  */
 function formatBytes(aBytes)
 {
-  var unit = gVerbose ? " B" : " MB";
+  let unit = gVerbose ? " B" : " MB";
 
-  var s;
+  let s;
   if (gVerbose) {
     s = formatInt(aBytes, unit);
   } else {
-    var mbytes = (aBytes / (1024 * 1024)).toFixed(2);
-    var a = String(mbytes).split(".");
+    let mbytes = (aBytes / (1024 * 1024)).toFixed(2);
+    let a = String(mbytes).split(".");
     // If the argument to formatInt() is -0, it will print the negative sign.
     s = formatInt(Number(a[0])) + "." + a[1] + unit;
   }
   return s;
 }
 
 /**
  * Converts a percentage to an appropriate string representation.
@@ -925,19 +926,19 @@ function formatPercentage(aPerc100x)
  * @param aN
  *        The field width.
  * @param aC
  *        The char used to pad.
  * @return The string representation.
  */
 function pad(aS, aN, aC)
 {
-  var padding = "";
-  var n2 = aN - aS.length;
-  for (var i = 0; i < n2; i++) {
+  let padding = "";
+  let n2 = aN - aS.length;
+  for (let i = 0; i < n2; i++) {
     padding += aC;
   }
   return padding + aS;
 }
 
 // There's a subset of the Unicode "light" box-drawing chars that are widely
 // implemented in terminals, and this code sticks to that subset to maximize
 // the chance that cutting and pasting about:memory output to a terminal will
@@ -968,111 +969,111 @@ function kindToString(aKind)
 // Possible states for kids.
 const kNoKids   = 0;
 const kHideKids = 1;
 const kShowKids = 2;
 
 function appendMrNameSpan(aP, aKind, aKidsState, aUnsafeDesc, aUnsafeName,
                           aIsUnknown, aIsInvalid, aNMerged)
 {
-  var text = "";
+  let text = "";
   if (aKidsState === kNoKids) {
     appendElementWithText(aP, "span", "mrSep", kDoubleHorizontalSep);
   } else if (aKidsState === kHideKids) {
     appendElementWithText(aP, "span", "mrSep",        " ++ ");
     appendElementWithText(aP, "span", "mrSep hidden", " -- ");
   } else if (aKidsState === kShowKids) {
     appendElementWithText(aP, "span", "mrSep hidden", " ++ ");
     appendElementWithText(aP, "span", "mrSep",        " -- ");
   } else {
     assert(false, "bad aKidsState");
   }
 
-  var nameSpan = appendElementWithText(aP, "span", "mrName",
+  let nameSpan = appendElementWithText(aP, "span", "mrName",
                                        makeSafe(aUnsafeName));
   nameSpan.title = kindToString(aKind) + makeSafe(aUnsafeDesc);
 
   if (aIsUnknown) {
-    var noteSpan = appendElementWithText(aP, "span", "mrNote", " [*]");
+    let noteSpan = appendElementWithText(aP, "span", "mrNote", " [*]");
     noteSpan.title =
       "Warning: this memory reporter was unable to compute a useful value. ";
   }
   if (aIsInvalid) {
-    var noteSpan = appendElementWithText(aP, "span", "mrNote", " [?!]");
+    let noteSpan = appendElementWithText(aP, "span", "mrNote", " [?!]");
     noteSpan.title =
       "Warning: this value is invalid and indicates a bug in one or more " +
       "memory reporters. ";
   }
   if (aNMerged) {
-    var noteSpan = appendElementWithText(aP, "span", "mrNote",
+    let noteSpan = appendElementWithText(aP, "span", "mrNote",
                                          " [" + aNMerged + "]");
     noteSpan.title =
       "This value is the sum of " + aNMerged +
       " memory reporters that all have the same path.";
   }
 }
 
 // This is used to record the (safe) IDs of which sub-trees have been toggled,
 // so the collapsed/expanded state can be replicated when the page is
 // regenerated.  It can end up holding IDs of nodes that no longer exist, e.g.
 // for compartments that have been closed.  This doesn't seem like a big deal,
 // because the number is limited by the number of entries the user has changed
 // from their original state.
-var gTogglesBySafeTreeId = {};
+let gTogglesBySafeTreeId = {};
 
 function assertClassListContains(e, className) {
   assert(e, "undefined " + className);
   assert(e.classList.contains(className), "classname isn't " + className);
 }
 
 function toggle(aEvent)
 {
   // This relies on each line being a span that contains at least five spans:
   // mrValue, mrPerc, mrSep ('++'), mrSep ('--'), mrName, and then zero or more
   // mrNotes.  All whitespace must be within one of these spans for this
   // function to find the right nodes.  And the span containing the children of
   // this line must immediately follow.  Assertions check this.
 
   // |aEvent.target| will be one of the five spans.  Get the outer span.
-  var outerSpan = aEvent.target.parentNode;
+  let outerSpan = aEvent.target.parentNode;
   assertClassListContains(outerSpan, "hasKids");
 
   // Toggle visibility of the '++' and '--' separators.
-  var plusSpan  = outerSpan.childNodes[2];
-  var minusSpan = outerSpan.childNodes[3];
+  let plusSpan  = outerSpan.childNodes[2];
+  let minusSpan = outerSpan.childNodes[3];
   assertClassListContains(plusSpan,  "mrSep");
   assertClassListContains(minusSpan, "mrSep");
   plusSpan .classList.toggle("hidden");
   minusSpan.classList.toggle("hidden");
 
   // Toggle visibility of the span containing this node's children.
-  var subTreeSpan = outerSpan.nextSibling;
+  let subTreeSpan = outerSpan.nextSibling;
   assertClassListContains(subTreeSpan, "kids");
   subTreeSpan.classList.toggle("hidden");
 
   // Record/unrecord that this sub-tree was toggled.
-  var safeTreeId = outerSpan.id;
+  let safeTreeId = outerSpan.id;
   if (gTogglesBySafeTreeId[safeTreeId]) {
     delete gTogglesBySafeTreeId[safeTreeId];
   } else {
     gTogglesBySafeTreeId[safeTreeId] = true;
   }
 }
 
 function expandPathToThisElement(aElement)
 {
   if (aElement.classList.contains("kids")) {
     // Unhide the kids.
     aElement.classList.remove("hidden");
     expandPathToThisElement(aElement.previousSibling);  // hasKids
 
   } else if (aElement.classList.contains("hasKids")) {
     // Unhide the '--' separator and hide the '++' separator.
-    var  plusSpan = aElement.childNodes[2];
-    var minusSpan = aElement.childNodes[3];
+    let  plusSpan = aElement.childNodes[2];
+    let minusSpan = aElement.childNodes[3];
     assertClassListContains(plusSpan,  "mrSep");
     assertClassListContains(minusSpan, "mrSep");
     plusSpan.classList.add("hidden");
     minusSpan.classList.remove("hidden");
     expandPathToThisElement(aElement.parentNode);       // kids or pre.tree
 
   } else {
     assertClassListContains(aElement, "tree");
@@ -1087,19 +1088,19 @@ function expandPathToThisElement(aElemen
  * @param aT
  *        The tree.
  * @param aProcess
  *        The process the tree corresponds to.
  * @return The generated text.
  */
 function appendTreeElements(aPOuter, aT, aProcess)
 {
-  var treeBytes = aT._amount;
-  var rootStringLength = aT.toString().length;
-  var isExplicitTree = aT._unsafeName == 'explicit';
+  let treeBytes = aT._amount;
+  let rootStringLength = aT.toString().length;
+  let isExplicitTree = aT._unsafeName == 'explicit';
 
   /**
    * Appends the elements for a particular tree, without a heading.
    *
    * @param aP
    *        The parent DOM node.
    * @param aUnsafePrePath
    *        The partial unsafePath leading up to this node.
@@ -1117,62 +1118,63 @@ function appendTreeElements(aPOuter, aT,
    *        The length of the formatted byte count of the top node in the tree.
    * @return The generated text.
    */
   function appendTreeElements2(aP, aUnsafePrePath, aT, aIndentGuide,
                                aBaseIndentText, aParentStringLength)
   {
     function repeatStr(aA, aC, aN)
     {
-      for (var i = 0; i < aN; i++) {
+      for (let i = 0; i < aN; i++) {
         aA.push(aC);
       }
     }
 
-    var unsafePath = aUnsafePrePath + aT._unsafeName;
+    let unsafePath = aUnsafePrePath + aT._unsafeName;
 
     // Indent more if this entry is narrower than its parent, and update
     // aIndentGuide accordingly.
-    var tString = aT.toString();
-    var extraIndentArray = [];
-    var extraIndentLength = Math.max(aParentStringLength - tString.length, 0);
+    let tString = aT.toString();
+    let extraIndentArray = [];
+    let extraIndentLength = Math.max(aParentStringLength - tString.length, 0);
     if (extraIndentLength > 0) {
       repeatStr(extraIndentArray, kHorizontal, extraIndentLength);
       aIndentGuide[aIndentGuide.length - 1]._depth += extraIndentLength;
     }
-    var indentText = aBaseIndentText + extraIndentArray.join("");
+    let indentText = aBaseIndentText + extraIndentArray.join("");
     appendElementWithText(aP, "span", "treeLine", indentText);
 
     // Generate the percentage;  detect and record invalid values at the same
     // time.
-    var percText = "";
-    var tIsInvalid = false;
+    let percText = "";
+    let tIsInvalid = false;
     if (aT._amount === treeBytes) {
       percText = "100.0";
     } else {
-      var perc = (100 * aT._amount / treeBytes);
+      let perc = (100 * aT._amount / treeBytes);
       if (!(0 <= perc && perc <= 100)) {
         tIsInvalid = true;
         gUnsafePathsWithInvalidValuesForThisProcess.push(unsafePath);
       }
       percText = (100 * aT._amount / treeBytes).toFixed(2);
       percText = pad(percText, 5, '0');
     }
     percText = " (" + percText + "%)";
 
     // For non-leaf nodes, the entire sub-tree is put within a span so it can
     // be collapsed if the node is clicked on.
-    var d;
-    var hasKids = aT._kids.length > 0;
-    var kidsState;
+    let d;
+    let hasKids = aT._kids.length > 0;
+    let kidsState;
+    let showSubtrees;
     if (hasKids) {
       // Determine if we should show the sub-tree below this entry;  this
       // involves reinstating any previous toggling of the sub-tree.
-      var safeTreeId = makeSafe(aProcess + ":" + unsafePath);
-      var showSubtrees = !aT._hideKids;
+      let safeTreeId = makeSafe(aProcess + ":" + unsafePath);
+      showSubtrees = !aT._hideKids;
       if (gTogglesBySafeTreeId[safeTreeId]) {
         showSubtrees = !showSubtrees;
       }
       d = appendElement(aP, "span", "hasKids");
       d.id = safeTreeId;
       d.onclick = toggle;
       kidsState = showSubtrees ? kShowKids : kHideKids;
     } else {
@@ -1181,58 +1183,59 @@ function appendTreeElements(aPOuter, aT,
       d = aP;
     }
 
     appendMrValueSpan(d, tString, tIsInvalid);
     appendElementWithText(d, "span", "mrPerc", percText);
 
     // We don't want to show '(nonheap)' on a tree like 'map/vsize', since the
     // whole tree is non-heap.
-    var kind = isExplicitTree ? aT._kind : undefined;
+    let kind = isExplicitTree ? aT._kind : undefined;
     appendMrNameSpan(d, kind, kidsState, aT._unsafeDescription, aT._unsafeName,
                      aT._isUnknown, tIsInvalid, aT._nMerged);
     appendTextNode(d, "\n");
 
     // In non-verbose mode, invalid nodes can be hidden in collapsed sub-trees.
     // But it's good to always see them, so force this.
     if (!gVerbose && tIsInvalid) {
       expandPathToThisElement(d);
     }
 
     if (hasKids) {
       // The 'kids' class is just used for sanity checking in toggle().
       d = appendElement(aP, "span", showSubtrees ? "kids" : "kids hidden");
 
-      for (var i = 0; i < aT._kids.length; i++) {
+      for (let i = 0; i < aT._kids.length; i++) {
         // 3 is the standard depth, the callee adjusts it if necessary.
         aIndentGuide.push({ _isLastKid: (i === aT._kids.length - 1), _depth: 3 });
 
         // Generate the base indent.
-        var baseIndentArray = [];
+        let baseIndentArray = [];
         if (aIndentGuide.length > 0) {
-          for (var j = 0; j < aIndentGuide.length - 1; j++) {
+          let j;
+          for (j = 0; j < aIndentGuide.length - 1; j++) {
             baseIndentArray.push(aIndentGuide[j]._isLastKid ? " " : kVertical);
             repeatStr(baseIndentArray, " ", aIndentGuide[j]._depth - 1);
           }
           baseIndentArray.push(aIndentGuide[j]._isLastKid ?
                                kUpAndRight : kVerticalAndRight);
           repeatStr(baseIndentArray, kHorizontal, aIndentGuide[j]._depth - 1);
         }
 
-        var baseIndentText = baseIndentArray.join("");
+        let baseIndentText = baseIndentArray.join("");
         appendTreeElements2(d, unsafePath + "/", aT._kids[i], aIndentGuide,
                             baseIndentText, tString.length);
         aIndentGuide.pop();
       }
     }
   }
 
   appendSectionHeader(aPOuter, kTreeNames[aT._unsafeName]);
  
-  var pre = appendElement(aPOuter, "pre", "tree");
+  let pre = appendElement(aPOuter, "pre", "tree");
   appendTreeElements2(pre, /* prePath = */"", aT, [], "", rootStringLength);
   appendTextNode(aPOuter, "\n");  // gives nice spacing when we cut and paste
 }
 
 function OtherReporter(aUnsafePath, aUnits, aAmount, aUnsafeDesc, aNMerged)
 {
   // Nb: _kind is not needed, it's always KIND_OTHER.
   this._unsafePath = aUnsafePath;
@@ -1255,17 +1258,17 @@ OtherReporter.prototype = {
       case UNITS_COUNT_CUMULATIVE: return formatInt(this._amount);
       case UNITS_PERCENTAGE:       return formatPercentage(this._amount);
       default:
         assert(false, "bad units in OtherReporter.toString");
     }
   },
 
   isInvalid: function() {
-    var n = this._amount;
+    let n = this._amount;
     switch (this._units) {
       case UNITS_BYTES:
       case UNITS_COUNT:
       case UNITS_COUNT_CUMULATIVE: return (n !== kUnknown && n < 0);
       case UNITS_PERCENTAGE:       return (n !== kUnknown &&
                                            !(0 <= n && n <= 10000));
       default:
         assert(false, "bad units in OtherReporter.isInvalid");
@@ -1289,44 +1292,44 @@ OtherReporter.compare = function(a, b) {
  * @param aProcess
  *        The process these reporters correspond to.
  * @return The generated text.
  */
 function appendOtherElements(aP, aReportersByProcess)
 {
   appendSectionHeader(aP, kTreeNames['other']);
 
-  var pre = appendElement(aP, "pre", "tree");
+  let pre = appendElement(aP, "pre", "tree");
 
   // Generate an array of Reporter-like elements, stripping out all the
   // Reporters that have already been handled.  Also find the width of the
   // widest element, so we can format things nicely.
-  var maxStringLength = 0;
-  var otherReporters = [];
-  for (var unsafePath in aReportersByProcess) {
-    var r = aReportersByProcess[unsafePath];
+  let maxStringLength = 0;
+  let otherReporters = [];
+  for (let unsafePath in aReportersByProcess) {
+    let r = aReportersByProcess[unsafePath];
     if (!r._done) {
       assert(r._kind === KIND_OTHER,
              "_kind !== KIND_OTHER for " + makeSafe(r._unsafePath));
       assert(r._nMerged === undefined);  // we don't allow dup'd OTHER reporters
-      var o = new OtherReporter(r._unsafePath, r._units, r._amount,
+      let o = new OtherReporter(r._unsafePath, r._units, r._amount,
                                 r._unsafeDescription);
       otherReporters.push(o);
       if (o._asString.length > maxStringLength) {
         maxStringLength = o._asString.length;
       }
     }
   }
   otherReporters.sort(OtherReporter.compare);
 
   // Generate text for the not-yet-printed values.
-  var text = "";
-  for (var i = 0; i < otherReporters.length; i++) {
-    var o = otherReporters[i];
-    var oIsInvalid = o.isInvalid();
+  let text = "";
+  for (let i = 0; i < otherReporters.length; i++) {
+    let o = otherReporters[i];
+    let oIsInvalid = o.isInvalid();
     if (oIsInvalid) {
       gUnsafePathsWithInvalidValuesForThisProcess.push(o._unsafePath);
     }
     appendMrValueSpan(pre, pad(o._asString, maxStringLength, ' '), oIsInvalid);
     appendMrNameSpan(pre, KIND_OTHER, kNoKids, o._unsafeDescription,
                      o._unsafePath, o._isUnknown, oIsInvalid);
     appendTextNode(pre, "\n");
   }
@@ -1344,11 +1347,11 @@ function assert(aCond, aMsg)
 {
   if (!aCond) {
     throw("assertion failed: " + aMsg);
   }
 }
 
 function debug(x)
 {
-  var content = document.getElementById("content");
+  let content = document.getElementById("content");
   appendElementWithText(content, "div", "legend", JSON.stringify(x));
 }
--- a/toolkit/components/aboutmemory/content/aboutMemory.xhtml
+++ b/toolkit/components/aboutmemory/content/aboutMemory.xhtml
@@ -37,13 +37,13 @@
    -
    - ***** END LICENSE BLOCK ***** -->
 
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>about:memory</title>
     <link rel="stylesheet" href="chrome://global/skin/aboutMemory.css" type="text/css"/>
     <link rel="stylesheet" href="chrome://global/skin/about.css" type="text/css"/>
-    <script type="text/javascript" src="chrome://global/content/aboutMemory.js"/>
+    <script type="text/javascript;version=1.8" src="chrome://global/content/aboutMemory.js"/>
   </head>
 
   <body id="content" onload="onLoad()" onunload="onUnload()"></body>
 </html>
--- a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul
+++ b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul
@@ -9,42 +9,42 @@
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml"></body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   const Cc = Components.classes;
   const Ci = Components.interfaces;
-  var mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
+  let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
 
   // Access mgr.explicit and mgr.resident just to make sure they don't crash.
   // We can't check their actual values because they're non-deterministic.
-  var dummy = mgr.explicit;
+  let dummy = mgr.explicit;
   dummy = mgr.resident;
 
   // Remove all the real reporters and multi-reporters;  save them to
   // restore at the end.
-  var e = mgr.enumerateReporters();
-  var realReporters = [];
+  let e = mgr.enumerateReporters();
+  let realReporters = [];
   dummy = 0;
   while (e.hasMoreElements()) {
-    var r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
+    let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
     // Get the |amount| field, even though we don't use it, just to test
     // that the reporter doesn't crash or anything.
     dummy += r.amount;
     mgr.unregisterReporter(r);
     realReporters.push(r);
   }
   e = mgr.enumerateMultiReporters();
-  var realMultiReporters = [];
-  var dummy = 0;
+  let realMultiReporters = [];
+  let dummy = 0;
   while (e.hasMoreElements()) {
-    var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
+    let r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
     // Call collectReports, even though we don't use its results, just to
     // test that the multi-reporter doesn't crash or anything.  And likewise
     // for the |explicitNonHeap| field.
     r.collectReports(function(){}, null);
     dummy += r.explicitNonHeap;
     mgr.unregisterMultiReporter(r);
     realMultiReporters.push(r);
   }
@@ -72,31 +72,31 @@
       amount:      aAmount 
     };
   }
 
   function f(aProcess, aPath, aKind, aAmount) {
     return f2(aProcess, aPath, aKind, BYTES, aAmount);
   }
 
-  var fakeReporters = [
+  let fakeReporters = [
     f("", "heap-allocated",     OTHER,   500 * MB),
     f("", "heap-unallocated",   OTHER,   100 * MB),
     f("", "explicit/a",         HEAP,    222 * MB),
     f("", "explicit/b/a",       HEAP,     85 * MB),
     f("", "explicit/b/b",       HEAP,     75 * MB),
     f("", "explicit/b/c/a",     HEAP,     70 * MB),
     f("", "explicit/b/c/b",     HEAP,      2 * MB), // omitted
     f("", "explicit/g/a",       HEAP,      6 * MB),
     f("", "explicit/g/b",       HEAP,      5 * MB),
     f("", "explicit/g/other",   HEAP,      4 * MB),
     f("", "other1",             OTHER,   111 * MB),
     f2("", "other4",            OTHER,   COUNT_CUMULATIVE, 888)
   ];
-  var fakeMultiReporters = [
+  let fakeMultiReporters = [
      { name: "fake1",
        collectReports: function(cbObj, closure) {
           function f(p, k, u, a) { cbObj.callback("", p, k, u, a, "(desc)", closure); }
           f("explicit/c/d",     NONHEAP, BYTES,  13 * MB),
           f("explicit/c/d",     NONHEAP, BYTES,  10 * MB), // dup
           f("explicit/c/other", NONHEAP, BYTES,  77 * MB),
           f("explicit/cc",      NONHEAP, BYTES,  13 * MB);
           f("explicit/cc",      NONHEAP, BYTES,  10 * MB); // dup
@@ -126,31 +126,31 @@
           f("smaps/vsize/a",      19);
           f("smaps/swap/b/c",     10);
           f("smaps/resident/a",   42);
           f("smaps/pss/a",        43);
        },
        explicitNonHeap: 0
      }
   ];
-  for (var i = 0; i < fakeReporters.length; i++) {
+  for (let i = 0; i < fakeReporters.length; i++) {
     mgr.registerReporter(fakeReporters[i]);
   }
-  for (var i = 0; i < fakeMultiReporters.length; i++) {
+  for (let i = 0; i < fakeMultiReporters.length; i++) {
     mgr.registerMultiReporter(fakeMultiReporters[i]);
   }
 
   // mgr.explicit sums "heap-allocated" and all the appropriate NONHEAP ones:
   // - "explicit/c", "explicit/cc" x 2, "explicit/d", "explicit/e"
   // - but *not* "explicit/c/d" x 2
   // Check explicit now before we add the fake reporters for the fake 2nd
   // and subsequent processes.
   is(mgr.explicit, 500*MB + (100 + 13 + 10)*MB + 599*KB, "mgr.explicit");
  
-  var fakeReporters2 = [
+  let fakeReporters2 = [
     f("2nd", "heap-allocated",  OTHER,  1000 * MB),
     f("2nd", "heap-unallocated",OTHER,   100 * MB),
     f("2nd", "explicit/a/b/c",  HEAP,    497 * MB),
     f("2nd", "explicit/a/b/c",  HEAP,      1 * MB), // dup: merge
     f("2nd", "explicit/a/b/c",  HEAP,      1 * MB), // dup: merge
     f("2nd", "explicit/flip\\the\\backslashes",
                                 HEAP,    200 * MB),
     f("2nd", "explicit/compartment(compartment-url)",
@@ -200,47 +200,47 @@
     f("5th", "explicit/a/pos",   HEAP,     40 * KB),
     f("5th", "explicit/a/neg1",  NONHEAP, -20 * KB),
     f("5th", "explicit/a/neg2",  NONHEAP, -10 * KB),
     f("5th", "explicit/b/c/d/e", NONHEAP,  20 * KB),
     f("5th", "explicit/b/c/d/f", NONHEAP, -60 * KB),
     f("5th", "explicit/b/c/g/h", NONHEAP,  10 * KB),
     f("5th", "explicit/b/c/i/j", NONHEAP,   5 * KB)
   ];
-  var fakeMultiReporters2 = [
+  let fakeMultiReporters2 = [
      // Because this multi-reporter is in a child process, the fact that we
      // skip the "smaps" multi-reporter in the parent process won't cause
      // these to be skipped;  the fall-back skipping will be hit instead.
      { name: "smaps",
        collectReports: function(cbObj, closure) {
           // The amounts are given in pages, so multiply here by 4kb.
           function f(p, a) { cbObj.callback("2nd", p, NONHEAP, BYTES, a * 4 * KB, "(desc)", closure); }
           f("smaps/vsize/a",     24);
           f("smaps/vsize/b",     24);
        },
        explicitNonHeap: 0
      }
   ];
-  for (var i = 0; i < fakeReporters2.length; i++) {
+  for (let i = 0; i < fakeReporters2.length; i++) {
     mgr.registerReporter(fakeReporters2[i]);
   }
-  for (var i = 0; i < fakeMultiReporters2.length; i++) {
+  for (let i = 0; i < fakeMultiReporters2.length; i++) {
     mgr.registerMultiReporter(fakeMultiReporters2[i]);
   }
   fakeReporters = fakeReporters.concat(fakeReporters2);
   fakeMultiReporters = fakeMultiReporters.concat(fakeMultiReporters2);
   ]]>
   </script>
 
   <iframe id="amFrame"  height="400" src="about:memory"></iframe>
   <iframe id="amvFrame" height="400" src="about:memory?verbose"></iframe>
 
   <script type="application/javascript">
   <![CDATA[
-  var amExpectedText =
+  let amExpectedText =
 "\
 Main Process\n\
 \n\
 Explicit Allocations\n\
 623.58 MB (100.0%) -- explicit\n\
 ├──232.00 MB (37.20%) -- b\n\
 │  ├───85.00 MB (13.63%) ── a\n\
 │  ├───75.00 MB (12.03%) ── b\n\
@@ -370,17 +370,17 @@ 99.95 MB (100.0%) -- explicit\n\
              ├───0.02 MB (00.02%) ── e\n\
              └──-0.06 MB (-0.06%) ── f [?!]\n\
 \n\
 Other Measurements\n\
 100.00 MB ── heap-allocated\n\
 \n\
 ";
 
-  var amvExpectedText =
+  let amvExpectedText =
 "\
 Main Process\n\
 \n\
 Explicit Allocations\n\
 653,876,224 B (100.0%) -- explicit\n\
 ├──243,269,632 B (37.20%) -- b\n\
 │  ├───89,128,960 B (13.63%) ── a\n\
 │  ├───78,643,200 B (12.03%) ── b\n\
@@ -534,32 +534,32 @@ 104,857,600 B ── heap-allocated\n\
 \n\
 "
 
   function finish()
   {
     // Unregister fake reporters and multi-reporters, re-register the real
     // reporters and multi-reporters, just in case subsequent tests rely on
     // them.
-    for (var i = 0; i < fakeReporters.length; i++) {
+    for (let i = 0; i < fakeReporters.length; i++) {
       mgr.unregisterReporter(fakeReporters[i]);
     }
-    for (var i = 0; i < fakeMultiReporters.length; i++) {
+    for (let i = 0; i < fakeMultiReporters.length; i++) {
       mgr.unregisterMultiReporter(fakeMultiReporters[i]);
     }
-    for (var i = 0; i < realReporters.length; i++) {
+    for (let i = 0; i < realReporters.length; i++) {
       mgr.registerReporter(realReporters[i]);
     }
-    for (var i = 0; i < realMultiReporters.length; i++) {
+    for (let i = 0; i < realMultiReporters.length; i++) {
       mgr.registerMultiReporter(realMultiReporters[i]);
     }
     SimpleTest.finish();
   }
 
-  var gHaveDumped = false;
+  let gHaveDumped = false;
 
   function checkClipboard(actual, expected) {
     if (actual != expected) {
       if (!gHaveDumped) {
         dump("******EXPECTED******\n");
         dump(expected);
         dump("*******ACTUAL*******\n");
         dump(actual);
--- a/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul
+++ b/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul
@@ -12,32 +12,32 @@
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml"></body>
 
   <!-- test code goes here -->
   <script type="application/javascript">
   <![CDATA[
   const Cc = Components.classes;
   const Ci = Components.interfaces;
-  var mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
+  let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
 
   // Remove all the real reporters and multi-reporters;  save them to
   // restore at the end.
-  var e = mgr.enumerateReporters();
-  var realReporters = [];
+  let e = mgr.enumerateReporters();
+  let realReporters = [];
   while (e.hasMoreElements()) {
-    var r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
+    let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
     mgr.unregisterReporter(r);
     realReporters.push(r);
   }
   e = mgr.enumerateMultiReporters();
-  var realMultiReporters = [];
+  let realMultiReporters = [];
   while (e.hasMoreElements()) {
-    var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
+    let r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
     mgr.unregisterMultiReporter(r);
     realMultiReporters.push(r);
   }
 
   // Setup various fake-but-deterministic reporters.
   const KB = 1024;
   const MB = KB * KB;
   const HEAP  = Ci.nsIMemoryReporter.KIND_HEAP;
@@ -50,54 +50,54 @@
       path:        aPath,
       kind:        aKind,
       units:       BYTES,
       description: "(description)",
       amount:      aAmount
     };
   }
 
-  var fakeReporters = [
+  let fakeReporters = [
     f("heap-allocated",     OTHER,   250 * MB),
     f("explicit/a/b",       HEAP,     50 * MB),
     f("explicit/a/c/d",     HEAP,     30 * MB),
     f("explicit/a/c/e",     HEAP,     20 * MB),
     f("explicit/a/f",       HEAP,     40 * MB),
     f("explicit/g",         HEAP,    100 * MB)
   ];
 
-  for (var i = 0; i < fakeReporters.length; i++) {
+  for (let i = 0; i < fakeReporters.length; i++) {
     mgr.registerReporter(fakeReporters[i]);
   }
 
   ]]>
   </script>
 
   <iframe id="amFrame"  height="500" src="about:memory"></iframe>
 
   <script type="application/javascript">
   <![CDATA[
   function finish()
   {
     // Unregister fake reporters and multi-reporters, re-register the real
     // reporters and multi-reporters, just in case subsequent tests rely on
     // them.
-    for (var i = 0; i < fakeReporters.length; i++) {
+    for (let i = 0; i < fakeReporters.length; i++) {
       mgr.unregisterReporter(fakeReporters[i]);
     }
-    for (var i = 0; i < realReporters.length; i++) {
+    for (let i = 0; i < realReporters.length; i++) {
       mgr.registerReporter(realReporters[i]);
     }
-    for (var i = 0; i < realMultiReporters.length; i++) {
+    for (let i = 0; i < realMultiReporters.length; i++) {
       mgr.registerMultiReporter(realMultiReporters[i]);
     }
     SimpleTest.finish();
   }
 
-  var gHaveDumped = false;
+  let gHaveDumped = false;
 
   function checkClipboard(actual, expected) {
     if (actual != expected) {
       if (!gHaveDumped) {
         dump("******EXPECTED******\n");
         dump(expected);
         dump("*******ACTUAL*******\n");
         dump(actual);
@@ -107,18 +107,18 @@
       return false;
     }
     return true;
   }
 
   // Click on the identified element, then cut+paste the entire page and
   // check that the cut text matches what we expect.
   function test(aId, aExpectedText, aNext) {
-    var win = document.getElementById("amFrame").contentWindow;
-    var node = win.document.getElementById(aId);
+    let win = document.getElementById("amFrame").contentWindow;
+    let node = win.document.getElementById(aId);
 
     // Yuk:  clicking a button is easy;  but for tree entries we need to
     // click on a child of the span identified via |id|.
     if (node.nodeName === "button") {
       node.click();
     } else {
       node.childNodes[0].click();
     }
@@ -137,25 +137,25 @@
           finish();
         }
       );
     });
   }
 
   // Returns a function that chains together one test() call per id.
   function chain(ids) {
-    var x = ids.shift();
+    let x = ids.shift();
     if (x) {
       return function() { test(x.id, x.expected, chain(ids)); }
     } else {
       return function() { finish(); };
     }
   }
 
-  var openExpected =
+  let openExpected =
 "\
 Main Process\n\
 \n\
 Explicit Allocations\n\
 250.00 MB (100.0%) -- explicit\n\
 ├──140.00 MB (56.00%) -- a\n\
 │  ├───50.00 MB (20.00%) ── b\n\
 │  ├───50.00 MB (20.00%) -- c\n\
@@ -165,17 +165,17 @@ 250.00 MB (100.0%) -- explicit\n\
 ├──100.00 MB (40.00%) ── g\n\
 └───10.00 MB (04.00%) ── heap-unclassified\n\
 \n\
 Other Measurements\n\
 250.00 MB ── heap-allocated\n\
 \n\
 ";
 
-  var cClosedExpected =
+  let cClosedExpected =
 "\
 Main Process\n\
 \n\
 Explicit Allocations\n\
 250.00 MB (100.0%) -- explicit\n\
 ├──140.00 MB (56.00%) -- a\n\
 │  ├───50.00 MB (20.00%) ── b\n\
 │  ├───50.00 MB (20.00%) ++ c\n\
@@ -183,34 +183,34 @@ 250.00 MB (100.0%) -- explicit\n\
 ├──100.00 MB (40.00%) ── g\n\
 └───10.00 MB (04.00%) ── heap-unclassified\n\
 \n\
 Other Measurements\n\
 250.00 MB ── heap-allocated\n\
 \n\
 ";
 
-  var aClosedExpected =
+  let aClosedExpected =
 "\
 Main Process\n\
 \n\
 Explicit Allocations\n\
 250.00 MB (100.0%) -- explicit\n\
 ├──140.00 MB (56.00%) ++ a\n\
 ├──100.00 MB (40.00%) ── g\n\
 └───10.00 MB (04.00%) ── heap-unclassified\n\
 \n\
 Other Measurements\n\
 250.00 MB ── heap-allocated\n\
 \n\
 ";
 
   // We close two sub-trees, hit the "Update" button, then reopen the two
   // sub-trees in reverse order.  After each step, we check the output.
-  var idsToClick = [
+  let idsToClick = [
     { id: "Main:explicit/a/c", expected: cClosedExpected },
     { id: "Main:explicit/a",   expected: aClosedExpected },
     { id: "updateButton",      expected: aClosedExpected },
     { id: "Main:explicit/a",   expected: cClosedExpected },
     { id: "Main:explicit/a/c", expected: openExpected }
   ];
 
   addLoadEvent(chain(idsToClick));
--- a/toolkit/components/aboutmemory/tests/test_sqliteMultiReporter.xul
+++ b/toolkit/components/aboutmemory/tests/test_sqliteMultiReporter.xul
@@ -20,34 +20,34 @@
   // but bug 671753 is preventing the memory-reporter-manager from being
   // accessed from xpcshell.
 
   const Cc = Components.classes;
   const Ci = Components.interfaces;
   const Cu = Components.utils;
 
   // Make a fake DB file.
-  var file = Cc["@mozilla.org/file/directory_service;1"].
+  let file = Cc["@mozilla.org/file/directory_service;1"].
              getService(Ci.nsIProperties).
              get("ProfD", Ci.nsIFile);
   file.append("test_sqliteMultiReporter-fake-DB-tmp.sqlite");
 
   // Open and close the DB.
-  var storage = Cc["@mozilla.org/storage/service;1"].
+  let storage = Cc["@mozilla.org/storage/service;1"].
                 getService(Ci.mozIStorageService);
-  var db = storage.openDatabase(file);
+  let db = storage.openDatabase(file);
   db.close();
 
   // Invoke all the multi-reporters.  The SQLite multi-reporter is among
   // them.  It shouldn't crash.
-  var mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
+  let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
             getService(Ci.nsIMemoryReporterManager);
   e = mgr.enumerateMultiReporters();
   while (e.hasMoreElements()) {
-    var r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
+    let r = e.getNext().QueryInterface(Ci.nsIMemoryMultiReporter);
     r.collectReports(function(){}, null);
   }
 
   // If we haven't crashed, we've passed, but the test harness requires that
   // we explicitly check something.
   ok(true);
 
   ]]>