Bug 1217077 - Remove for-each from services/. r=gps
authorTooru Fujisawa <arai_a@mac.com>
Mon, 19 Oct 2015 03:52:58 +0900
changeset 271386 1de5ecadcceebb00801baeddabbb76f140a85d66
parent 271385 9aab415d2bd9b8ee29f71e3a7b3bd7616bb006be
child 271387 16d3dd16ef70f798a325b64152aa440c3e1cbd9b
push id29638
push userkwierso@gmail.com
push dateFri, 06 Nov 2015 02:44:30 +0000
treeherdermozilla-central@cc48981c026c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1217077
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1217077 - Remove for-each from services/. r=gps
services/cloudsync/CloudSyncBookmarks.jsm
services/cloudsync/CloudSyncEventSource.jsm
services/cloudsync/CloudSyncPlacesWrapper.jsm
services/cloudsync/CloudSyncTabs.jsm
services/common/async.js
services/common/modules-testing/storageserver.js
services/common/stringbundle.js
services/common/tests/mach_commands.py
services/common/tests/unit/head_global.js
services/common/tests/unit/test_load_modules.js
services/common/tests/unit/test_tokenserverclient.js
services/common/utils.js
services/crypto/modules/utils.js
services/crypto/tests/unit/test_load_modules.js
services/metrics/providermanager.jsm
services/sync/modules/addonsreconciler.js
services/sync/modules/addonutils.js
services/sync/modules/engines.js
services/sync/modules/engines/addons.js
services/sync/modules/engines/bookmarks.js
services/sync/modules/engines/clients.js
services/sync/modules/engines/history.js
services/sync/modules/engines/passwords.js
services/sync/modules/engines/prefs.js
services/sync/modules/engines/tabs.js
services/sync/modules/identity.js
services/sync/modules/jpakeclient.js
services/sync/modules/record.js
services/sync/modules/service.js
services/sync/modules/stages/declined.js
services/sync/modules/stages/enginesync.js
services/sync/tests/unit/head_appinfo.js
services/sync/tests/unit/head_http_server.js
services/sync/tests/unit/test_addons_reconciler.js
services/sync/tests/unit/test_addons_store.js
services/sync/tests/unit/test_bookmark_store.js
services/sync/tests/unit/test_clients_engine.js
services/sync/tests/unit/test_collections_recovery.js
services/sync/tests/unit/test_jpakeclient.js
services/sync/tests/unit/test_resource.js
services/sync/tests/unit/test_resource_async.js
services/sync/tests/unit/test_service_startup.js
services/sync/tests/unit/test_status.js
services/sync/tests/unit/test_tab_tracker.js
services/sync/tps/extensions/mozmill/resource/driver/controller.js
services/sync/tps/extensions/mozmill/resource/driver/elementslib.js
services/sync/tps/extensions/mozmill/resource/modules/frame.js
services/sync/tps/extensions/mozmill/resource/stdlib/os.js
services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
services/sync/tps/extensions/mozmill/resource/stdlib/utils.js
services/sync/tps/extensions/tps/resource/modules/history.jsm
services/sync/tps/extensions/tps/resource/modules/tabs.jsm
services/sync/tps/extensions/tps/resource/tps.jsm
--- a/services/cloudsync/CloudSyncBookmarks.jsm
+++ b/services/cloudsync/CloudSyncBookmarks.jsm
@@ -549,44 +549,44 @@ var RootFolder = function (rootId, rootN
           }
         } else if (item.__exists__ && item.deleted) {
           deletedItems.push(item);
         } else if (item.__exists__) {
           updatedItems.push(item);
         }
       }
 
-      for each (let item in items) {
+      for (let item of items) {
         if (!item || 'object' !== typeof(item)) {
           continue;
         }
 
         let promise = exists(item).then(handleSortedItem, Promise.reject);
         promises.push(promise);
       }
 
       return Promise.all(promises);
     }
 
     let processNewFolders = function () {
       let newFolderGuids = Object.keys(newFolders);
       let newFolderRoots = [];
 
-      for each (let guid in newFolderGuids) {
+      for (let guid of newFolderGuids) {
         let item = newFolders[guid];
         if (item.parent && newFolderGuids.indexOf(item.parent) >= 0) {
           let parent = newFolders[item.parent];
           parent._children.push(item.id);
         } else {
           newFolderRoots.push(guid);
         }
       };
 
       let promises = [];
-      for each (let guid in newFolderRoots) {
+      for (let guid of newFolderRoots) {
         let root = newFolders[guid];
         let promise = Promise.resolve();
         promise = promise.then(
           function () {
             return _createItem(root);
           },
           Promise.reject
         );
@@ -606,25 +606,25 @@ var RootFolder = function (rootId, rootN
       }
 
       return Promise.all(promises);
     }
 
     let processItems = function () {
       let promises = [];
 
-      for each (let item in newItems) {
+      for (let item of newItems) {
         promises.push(_createItem(item));
       }
 
-      for each (let item in updatedItems) {
+      for (let item of updatedItems) {
         promises.push(_updateItem(item));
       }
 
-      for each (let item in deletedItems) {
+      for (let item of deletedItems) {
         _deleteItem(item);
       }
 
       return Promise.all(promises);
     }
 
     sortItems().then(processNewFolders)
                .then(processItems)
--- a/services/cloudsync/CloudSyncEventSource.jsm
+++ b/services/cloudsync/CloudSyncEventSource.jsm
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["EventSource"];
 
 Components.utils.import("resource://services-common/utils.js");
 
 var EventSource = function (types, suspendFunc, resumeFunc) {
   this.listeners = new Map();
-  for each (let type in types) {
+  for (let type of types) {
     this.listeners.set(type, new Set());
   }
 
   this.suspend = suspendFunc || function () {};
   this.resume = resumeFunc || function () {};
 
   this.addEventListener = this.addEventListener.bind(this);
   this.removeEventListener = this.removeEventListener.bind(this);
--- a/services/cloudsync/CloudSyncPlacesWrapper.jsm
+++ b/services/cloudsync/CloudSyncPlacesWrapper.jsm
@@ -135,17 +135,17 @@ PlacesWrapper.prototype = {
 
     query.params.parent_id = folder;
     query.params.item_type = PlacesUtils.bookmarks.TYPE_FOLDER;
 
     this.asyncQuery(query, ["id", "guid"]).then(
       function (items) {
         let previousIds = folderCache.getChildren(folder);
         let currentIds = new Set();
-        for each (let item in items) {
+        for (let item of items) {
           currentIds.add(item.id);
         }
         let newIds = new Set();
         let missingIds = new Set();
 
         for (let currentId of currentIds) {
           if (!previousIds.has(currentId)) {
             newIds.add(currentId);
@@ -183,17 +183,17 @@ PlacesWrapper.prototype = {
                "WHERE n.name = :anno_name";
     let query = this.placesQueries.getQuery(stmt);
 
     query.params.anno_name = anno.toString();
 
     this.asyncQuery(query, ["item_id"])
         .then(function (items) {
                 let results = [];
-                for each(let item in items) {
+                for (let item of items) {
                   results.push(item.item_id);
                 }
                 deferred.resolve(results);
               },
               deferred.reject);
 
     return deferred.promise;
   },
@@ -206,17 +206,17 @@ PlacesWrapper.prototype = {
                "WHERE b.item_id = :item_id";
     let query = this.placesQueries.getQuery(stmt);
 
     query.params.item_id = id;
 
     this.asyncQuery(query, ["name", "content"])
         .then(function (results) {
                 let annos = {};
-                for each(let result in results) {
+                for (let result of results) {
                   annos[result.name] = result.content;
                 }
                 deferred.resolve(annos);
               },
               deferred.reject);
 
     return deferred.promise;
   },
@@ -342,17 +342,17 @@ PlacesWrapper.prototype = {
       handleResult: function (results) {
         if (!names) {
           return;
         }
 
         let row;
         while ((row = results.getNextRow()) != null) {
           let item = {};
-          for each (let name in names) {
+          for (let name of names) {
             item[name] = row.getResultByName(name);
           }
           this.results.push(item);
         }
       },
 
       handleError: function (error) {
         deferred.reject(error);
--- a/services/cloudsync/CloudSyncTabs.jsm
+++ b/services/cloudsync/CloudSyncTabs.jsm
@@ -82,17 +82,17 @@ TabCache.prototype = {
       } catch (e) {
         throw new Error("unable to update client: " + e);
       }
     } else {
       cRecord = new ClientRecord(client);
       this.clients.set(cRecord.id, cRecord);
     }
 
-    for each (let tab in tabs) {
+    for (let tab of tabs) {
       if (!tab || 'object' !== typeof(tab)) {
         continue;
       }
 
       let tRecord;
       if (this.tabs.has(tab.url)) {
         tRecord = this.tabs.get(tab.url);
         try {
@@ -153,25 +153,25 @@ this.Tabs = function () {
         return;
       }
     }
 
     eventSource.emit("change");
   };
 
   let registerListenersForWindow = function (window) {
-    for each (let topic in topics) {
+    for (let topic of topics) {
       window.addEventListener(topic, update, false);
     }
     window.addEventListener("unload", unregisterListeners, false);
   };
 
   let unregisterListenersForWindow = function (window) {
     window.removeEventListener("unload", unregisterListeners, false);
-    for each (let topic in topics) {
+    for (let topic of topics) {
       window.removeEventListener(topic, update, false);
     }
   };
 
   let unregisterListeners = function (event) {
     unregisterListenersForWindow(event.target);
   };
 
--- a/services/common/async.js
+++ b/services/common/async.js
@@ -172,17 +172,17 @@ this.Async = {
         return;
       }
       if (!this.results) {
         this.results = [];
       }
       let row;
       while ((row = results.getNextRow()) != null) {
         let item = {};
-        for each (let name in this.names) {
+        for (let name of this.names) {
           item[name] = row.getResultByName(name);
         }
         this.results.push(item);
       }
     },
     handleError: function handleError(error) {
       this.syncCb.throw(error);
     },
--- a/services/common/modules-testing/storageserver.js
+++ b/services/common/modules-testing/storageserver.js
@@ -97,17 +97,17 @@ ServerBSO.prototype = {
     "payload",
     "ttl",
     "sortindex",
   ],
 
   toJSON: function toJSON() {
     let obj = {};
 
-    for each (let key in this.FIELDS) {
+    for (let key of this.FIELDS) {
       if (this[key] !== undefined) {
         obj[key] = this[key];
       }
     }
 
     return obj;
   },
 
@@ -301,17 +301,17 @@ StorageServerCollection.prototype = {
 
   set timestamp(timestamp) {
     CommonUtils.ensureMillisecondsTimestamp(timestamp);
     this._timestamp = timestamp;
   },
 
   get totalPayloadSize() {
     let size = 0;
-    for each (let bso in this.bsos()) {
+    for (let bso of this.bsos()) {
       size += bso.payload.length;
     }
 
     return size;
   },
 
   /**
    * Convenience accessor for our BSO keys.
@@ -436,17 +436,18 @@ StorageServerCollection.prototype = {
         c++;
       }
     }
     return c;
   },
 
   get: function get(options) {
     let data = [];
-    for each (let bso in this._bsos) {
+    for (let id in this._bsos) {
+      let bso = this._bsos[id];
       if (!bso.modified) {
         continue;
       }
 
       if (!this._inResultSet(bso, options)) {
         continue;
       }
 
@@ -499,17 +500,17 @@ StorageServerCollection.prototype = {
   post: function post(input, timestamp) {
     let success = [];
     let failed = {};
     let count = 0;
     let size = 0;
 
     // This will count records where we have an existing ServerBSO
     // registered with us as successful and all other records as failed.
-    for each (let record in input) {
+    for (let record of input) {
       count += 1;
       if (count > this.BATCH_MAX_COUNT) {
         failed[record.id] = "Max record count exceeded.";
         continue;
       }
 
       if (typeof(record.payload) != "string") {
         failed[record.id] = "Payload is not a string!";
@@ -597,17 +598,17 @@ StorageServerCollection.prototype = {
       }
     }
     return deleted;
   },
 
   parseOptions: function parseOptions(request) {
     let options = {};
 
-    for each (let chunk in request.queryString.split("&")) {
+    for (let chunk of request.queryString.split("&")) {
       if (!chunk) {
         continue;
       }
       chunk = chunk.split("=");
       let key = decodeURIComponent(chunk[0]);
       if (chunk.length == 1) {
         options[key] = "";
       } else {
@@ -651,17 +652,17 @@ StorageServerCollection.prototype = {
   getHandler: function getHandler(request, response) {
     let options = this.parseOptions(request);
     let data = this.get(options);
 
     if (request.hasHeader("x-if-modified-since")) {
       let requestModified = parseInt(request.getHeader("x-if-modified-since"),
                                      10);
       let newestBSO = 0;
-      for each (let bso in data) {
+      for (let bso of data) {
         if (bso.modified > newestBSO) {
           newestBSO = bso.modified;
         }
       }
 
       if (requestModified >= newestBSO) {
         response.setHeader("X-Last-Modified", "" + newestBSO);
         response.setStatusLine(request.httpVersion, 304, "Not Modified");
@@ -741,17 +742,17 @@ StorageServerCollection.prototype = {
         throw HTTP_400;
       }
 
       if (!Array.isArray(input)) {
         this._log.info("Input JSON type not an array!");
         return sendMozSvcError(request, response, "8");
       }
     } else if (inputMediaType == "application/newlines") {
-      for each (let line in inputBody.split("\n")) {
+      for (let line of inputBody.split("\n")) {
         let record;
         try {
           record = JSON.parse(line);
         } catch (ex) {
           this._log.info("JSON parse error on line!");
           return sendMozSvcError(request, response, "8");
         }
 
@@ -1073,17 +1074,18 @@ StorageServer.prototype = {
    * @param username
    *        The name of the affected user.
    */
   deleteCollections: function deleteCollections(username) {
     if (!(username in this.users)) {
       throw new Error("Unknown user.");
     }
     let userCollections = this.users[username].collections;
-    for each (let [name, coll] in Iterator(userCollections)) {
+    for (let name in userCollections) {
+      let coll = userCollections[name];
       this._log.trace("Bulk deleting " + name + " for " + username + "...");
       coll.delete({});
     }
     this.users[username].collections = {};
   },
 
   getQuota: function getQuota(username) {
     if (!(username in this.users)) {
@@ -1094,17 +1096,18 @@ StorageServer.prototype = {
   },
 
   /**
    * Obtain the newest timestamp of all collections for a user.
    */
   newestCollectionTimestamp: function newestCollectionTimestamp(username) {
     let collections = this.users[username].collections;
     let newest = 0;
-    for each (let collection in collections) {
+    for (let name in collections) {
+      let collection = collections[name];
       if (collection.timestamp > newest) {
         newest = collection.timestamp;
       }
     }
 
     return newest;
   },
 
@@ -1144,17 +1147,19 @@ StorageServer.prototype = {
       data[k] = v.totalPayloadSize;
     }
 
     return data;
   },
 
   infoQuota: function infoQuota(username) {
     let total = 0;
-    for each (let value in this.infoUsage(username)) {
+    let usage = this.infoUsage(username);
+    for (let key in usage) {
+      let value = usage[key];
       total += value;
     }
 
     return {
       quota: this.getQuota(username),
       usage: total
     };
   },
@@ -1186,19 +1191,21 @@ StorageServer.prototype = {
       modified:          modified,
       quota:             quota,
     };
   },
 
   _pruneExpired: function _pruneExpired() {
     let now = Date.now();
 
-    for each (let user in this.users) {
-      for each (let collection in user.collections) {
-        for each (let bso in collection.bsos()) {
+    for (let username in this.users) {
+      let user = this.users[username];
+      for (let name in user.collections) {
+        let collection = user.collections[name];
+        for (let bso of collection.bsos()) {
           // ttl === 0 is a special case, so we can't simply !ttl.
           if (typeof(bso.ttl) != "number") {
             continue;
           }
 
           let ttlDate = bso.modified + (bso.ttl * 1000);
           if (ttlDate < now) {
             this._log.info("Deleting BSO because TTL expired: " + bso.id);
@@ -1235,17 +1242,21 @@ StorageServer.prototype = {
   defaultHeaders: {},
 
   /**
    * HTTP response utility.
    */
   respond: function respond(req, resp, code, status, body, headers, timestamp) {
     this._log.info("Response: " + code + " " + status);
     resp.setStatusLine(req.httpVersion, code, status);
-    for each (let [header, value] in Iterator(headers || this.defaultHeaders)) {
+    if (!headers) {
+      headers = this.defaultHeaders;
+    }
+    for (let header in headers) {
+      let value = headers[header];
       resp.setHeader(header, value, false);
     }
 
     if (timestamp) {
       resp.setHeader("X-Timestamp", "" + timestamp, false);
     }
 
     if (body) {
--- a/services/common/stringbundle.js
+++ b/services/common/stringbundle.js
@@ -19,17 +19,17 @@ var {classes: Cc, interfaces: Ci, result
  * To use this module, import it, create a new instance of StringBundle,
  * and then use the instance's |get| and |getAll| methods to retrieve strings
  * (you can get both plain and formatted strings with |get|):
  *
  *   let strings =
  *     new StringBundle("chrome://example/locale/strings.properties");
  *   let foo = strings.get("foo");
  *   let barFormatted = strings.get("bar", [arg1, arg2]);
- *   for each (let string in strings.getAll())
+ *   for (let string of strings.getAll())
  *     dump (string.key + " = " + string.value + "\n");
  *
  * @param url {String}
  *        the URL of the string bundle
  */
 this.StringBundle = function StringBundle(url) {
   this.url = url;
 }
--- a/services/common/tests/mach_commands.py
+++ b/services/common/tests/mach_commands.py
@@ -82,17 +82,17 @@ class SyncTestCommands(MachCommandBase):
             '-m',
             '-s',
             '-e', 'const _TESTING_MODULES_DIR = "%s/_tests/modules";' % topobjdir,
             '-f', '%s/testing/xpcshell/head.js' % topsrcdir,
             '-e', 'const _SERVER_ADDR = "%s";' % hostname,
             '-e', 'const SERVER_PORT = "%s";' % port,
             '-e', 'const INCLUDE_FILES = [%s];' % ', '.join(head_paths),
             '-e', '_register_protocol_handlers();',
-            '-e', 'for each (let name in INCLUDE_FILES) load(name);',
+            '-e', 'for (let name of INCLUDE_FILES) load(name);',
             '-e', '_fakeIdleService.activate();',
             '-f', js_file
             ]
 
         profile_dir = mkdtemp()
         print 'Created profile directory: %s' % profile_dir
 
         try:
--- a/services/common/tests/unit/head_global.js
+++ b/services/common/tests/unit/head_global.js
@@ -37,15 +37,15 @@ registrar.registerFactory(Components.ID(
                           XULAppInfoFactory);
 
 function addResourceAlias() {
   Cu.import("resource://gre/modules/Services.jsm");
   const handler = Services.io.getProtocolHandler("resource")
                   .QueryInterface(Ci.nsIResProtocolHandler);
 
   let modules = ["common", "crypto"];
-  for each (let module in modules) {
+  for (let module of modules) {
     let uri = Services.io.newURI("resource://gre/modules/services-" + module + "/",
                                  null, null);
     handler.setSubstitution("services-" + module, uri);
   }
 }
 addResourceAlias();
--- a/services/common/tests/unit/test_load_modules.js
+++ b/services/common/tests/unit/test_load_modules.js
@@ -29,32 +29,32 @@ const non_android_test_modules = [
   "storageserver.js",
 ];
 
 const non_android_healthreport_test_modules = [
   "bagheeraserver.js",
 ];
 
 function expectImportsToSucceed(mm, base=MODULE_BASE) {
-  for each (let m in mm) {
+  for (let m of mm) {
     let resource = base + m;
     let succeeded = false;
     try {
       Components.utils.import(resource, {});
       succeeded = true;
     } catch (e) {}
 
     if (!succeeded) {
       throw "Importing " + resource + " should have succeeded!";
     }
   }
 }
 
 function expectImportsToFail(mm, base=MODULE_BASE) {
-  for each (let m in mm) {
+  for (let m of mm) {
     let resource = base + m;
     let succeeded = false;
     try {
       Components.utils.import(resource, {});
       succeeded = true;
     } catch (e) {}
 
     if (succeeded) {
--- a/services/common/tests/unit/test_tokenserverclient.js
+++ b/services/common/tests/unit/test_tokenserverclient.js
@@ -55,17 +55,17 @@ add_test(function test_invalid_arguments
   _("Ensure invalid arguments to APIs are rejected.");
 
   let args = [
     [null, "assertion", function() {}],
     ["http://example.com/", null, function() {}],
     ["http://example.com/", "assertion", null]
   ];
 
-  for each (let arg in args) {
+  for (let arg of args) {
     try {
       let client = new TokenServerClient();
       client.getTokenFromBrowserIDAssertion(arg[0], arg[1], arg[2]);
       do_throw("Should never get here.");
     } catch (ex) {
       do_check_true(ex instanceof TokenServerClientError);
     }
   }
--- a/services/common/utils.js
+++ b/services/common/utils.js
@@ -200,26 +200,25 @@ this.CommonUtils = {
       str = this._utf8Converter.ConvertToUnicode(str);
       return str + this._utf8Converter.Finish();
     } catch (ex) {
       return null;
     }
   },
 
   byteArrayToString: function byteArrayToString(bytes) {
-    return [String.fromCharCode(byte) for each (byte in bytes)].join("");
+    return bytes.map(byte => String.fromCharCode(byte)).join("");
   },
 
   stringToByteArray: function stringToByteArray(bytesString) {
-    return [String.charCodeAt(byte) for each (byte in bytesString)];
+    return Array.prototype.slice.call(bytesString).map(c => c.charCodeAt(0));
   },
 
   bytesAsHex: function bytesAsHex(bytes) {
-    return [("0" + bytes.charCodeAt(byte).toString(16)).slice(-2)
-      for (byte in bytes)].join("");
+    return Array.prototype.slice.call(bytes).map(c => ("0" + c.charCodeAt(0).toString(16)).slice(-2)).join("");
   },
 
   stringAsHex: function stringAsHex(str) {
     return CommonUtils.bytesAsHex(CommonUtils.encodeUTF8(str));
   },
 
   stringToBytes: function stringToBytes(str) {
     return CommonUtils.hexToBytes(CommonUtils.stringAsHex(str));
@@ -251,17 +250,17 @@ this.CommonUtils = {
       for (let i = leftover; i < 5; i++)
         bytes += "\0";
     }
 
     // Chop the string into quanta of 5 bytes (40 bits). Each quantum
     // is turned into 8 characters from the 32 character base.
     let ret = "";
     for (let i = 0; i < bytes.length; i += 5) {
-      let c = [byte.charCodeAt() for each (byte in bytes.slice(i, i + 5))];
+      let c = Array.prototype.slice.call(bytes.slice(i, i + 5)).map(byte => byte.charCodeAt(0));
       ret += key[c[0] >> 3]
            + key[((c[0] << 2) & 0x1f) | (c[1] >> 6)]
            + key[(c[1] >> 1) & 0x1f]
            + key[((c[1] << 4) & 0x1f) | (c[2] >> 4)]
            + key[((c[2] << 1) & 0x1f) | (c[3] >> 7)]
            + key[(c[3] >> 2) & 0x1f]
            + key[((c[3] << 3) & 0x1f) | (c[4] >> 5)]
            + key[c[4] & 0x1f];
--- a/services/crypto/modules/utils.js
+++ b/services/crypto/modules/utils.js
@@ -51,17 +51,17 @@ this.CryptoUtils = {
 
   /**
    * Treat the given message as a bytes string and hash it with the given
    * hasher. Returns a string containing bytes. The hasher is reset if it's
    * an HMAC hasher.
    */
   digestBytes: function digestBytes(message, hasher) {
     // No UTF-8 encoding for you, sunshine.
-    let bytes = [b.charCodeAt() for each (b in message)];
+    let bytes = Array.prototype.slice.call(message).map(b => b.charCodeAt(0));
     hasher.update(bytes, bytes.length);
     let result = hasher.finish(false);
     if (hasher instanceof Ci.nsICryptoHMAC) {
       hasher.reset();
     }
     return result;
   },
 
--- a/services/crypto/tests/unit/test_load_modules.js
+++ b/services/crypto/tests/unit/test_load_modules.js
@@ -2,15 +2,15 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const modules = [
   "utils.js",
   "WeaveCrypto.js",
 ];
 
 function run_test() {
-  for each (let m in modules) {
+  for (let m of modules) {
     let resource = "resource://services-crypto/" + m;
     _("Attempting to import: " + resource);
     Components.utils.import(resource, {});
   }
 }
 
--- a/services/metrics/providermanager.jsm
+++ b/services/metrics/providermanager.jsm
@@ -277,17 +277,18 @@ this.ProviderManager.prototype = Object.
         try {
           yield inFlightPromise;
         } catch (ex) {
           this._log.warn("Error when waiting for existing pull-only promise: " +
                          CommonUtils.exceptionStr(ex));
         }
       }
 
-      for each (let providerType in this._pullOnlyProviders) {
+      for (let name in this._pullOnlyProviders) {
+        let providerType = this._pullOnlyProviders[name];
         // Short-circuit if we're no longer registering.
         if (this._pullOnlyProvidersState != this.PULL_ONLY_REGISTERING) {
           this._log.debug("Aborting pull-only provider registration.");
           break;
         }
 
         try {
           let provider = this._initProviderFromType(providerType);
--- a/services/sync/modules/addonsreconciler.js
+++ b/services/sync/modules/addonsreconciler.js
@@ -213,21 +213,22 @@ AddonsReconciler.prototype = {
         if (callback) {
           callback(null, false);
         }
 
         return;
       }
 
       this._addons = json.addons;
-      for each (let record in this._addons) {
+      for (let id in this._addons) {
+        let record = this._addons[id];
         record.modified = new Date(record.modified);
       }
 
-      for each (let [time, change, id] in json.changes) {
+      for (let [time, change, id] of json.changes) {
         this._changes.push([new Date(time), change, id]);
       }
 
       if (callback) {
         callback(null, true);
       }
     });
   },
@@ -253,17 +254,17 @@ AddonsReconciler.prototype = {
           state.addons[id][k] = v.getTime();
         }
         else {
           state.addons[id][k] = v;
         }
       }
     }
 
-    for each (let [time, change, id] in this._changes) {
+    for (let [time, change, id] of this._changes) {
       state.changes.push([time.getTime(), change, id]);
     }
 
     this._log.info("Saving reconciler state to file: " + file);
     Utils.jsonSave(file, this, state, callback);
   },
 
   /**
@@ -345,17 +346,17 @@ AddonsReconciler.prototype = {
     this._log.info("Refreshing global state from AddonManager.");
     this._ensureStateLoaded();
 
     let installs;
 
     AddonManager.getAllAddons(function (addons) {
       let ids = {};
 
-      for each (let addon in addons) {
+      for (let addon of addons) {
         ids[addon.id] = true;
         this.rectifyStateFromAddon(addon);
       }
 
       // Look for locally-defined add-ons that no longer exist and update their
       // record.
       for (let [id, addon] in Iterator(this._addons)) {
         if (id in ids) {
@@ -368,17 +369,17 @@ AddonsReconciler.prototype = {
 
         if (!installs) {
           let cb = Async.makeSyncCallback();
           AddonManager.getAllInstalls(cb);
           installs = Async.waitForSyncCallback(cb);
         }
 
         let installFound = false;
-        for each (let install in installs) {
+        for (let install of installs) {
           if (install.addon && install.addon.id == id &&
               install.state == AddonManager.STATE_INSTALLED) {
 
             installFound = true;
             break;
           }
         }
 
@@ -478,17 +479,17 @@ AddonsReconciler.prototype = {
    *        The type of the change. A CHANGE_* constant.
    * @param state
    *        The new state of the add-on. From this.addons.
    */
   _addChange: function _addChange(date, change, state) {
     this._log.info("Change recorded for " + state.id);
     this._changes.push([date, change, state.id]);
 
-    for each (let listener in this._listeners) {
+    for (let listener of this._listeners) {
       try {
         listener.changeListener.call(listener, date, change, state);
       } catch (ex) {
         this._log.warn("Exception calling change listener: " +
                        Utils.exceptionStr(ex));
       }
     }
   },
@@ -549,17 +550,18 @@ AddonsReconciler.prototype = {
    *
    * If the add-on could not be found, returns null.
    *
    * @param  guid
    *         Sync GUID of add-on to retrieve.
    * @return Object on success on null on failure.
    */
   getAddonStateFromSyncGUID: function getAddonStateFromSyncGUID(guid) {
-    for each (let addon in this.addons) {
+    for (let id in this.addons) {
+      let addon = this.addons[id];
       if (addon.guid == guid) {
         return addon;
       }
     }
 
     return null;
   },
 
--- a/services/sync/modules/addonutils.js
+++ b/services/sync/modules/addonutils.js
@@ -243,17 +243,17 @@ AddonUtilsInternal.prototype = {
    *        Function to be called when all actions are complete.
    */
   installAddons: function installAddons(installs, cb) {
     if (!cb) {
       throw new Error("Invalid argument: cb is not defined.");
     }
 
     let ids = [];
-    for each (let addon in installs) {
+    for (let addon of installs) {
       ids.push(addon.id);
     }
 
     AddonRepository.getAddonsByIDs(ids, {
       searchSucceeded: function searchSucceeded(addons, addonsLength, total) {
         this._log.info("Found " + addonsLength + "/" + ids.length +
                        " add-ons during repository search.");
 
@@ -293,17 +293,17 @@ AddonUtilsInternal.prototype = {
 
         let toInstall = [];
 
         // Rewrite the "src" query string parameter of the source URI to note
         // that the add-on was installed by Sync and not something else so
         // server-side metrics aren't skewed (bug 708134). The server should
         // ideally send proper URLs, but this solution was deemed too
         // complicated at the time the functionality was implemented.
-        for each (let addon in addons) {
+        for (let addon of addons) {
           // sourceURI presence isn't enforced by AddonRepository. So, we skip
           // add-ons without a sourceURI.
           if (!addon.sourceURI) {
             this._log.info("Skipping install of add-on because missing " +
                            "sourceURI: " + addon.id);
             continue;
           }
 
@@ -337,19 +337,19 @@ AddonUtilsInternal.prototype = {
 
         if (!expectedInstallCount) {
           cb(null, ourResult);
           return;
         }
 
         // Start all the installs asynchronously. They will report back to us
         // as they finish, eventually triggering the global callback.
-        for each (let addon in toInstall) {
+        for (let addon of toInstall) {
           let options = {};
-          for each (let install in installs) {
+          for (let install of installs) {
             if (install.id == addon.id) {
               options = install;
               break;
             }
           }
 
           this.installAddonFromSearchResult(addon, options, installCallback);
         }
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -294,17 +294,17 @@ Store.prototype = {
    * applyIncoming(). Store implementations may overwrite this function
    * if desired.
    *
    * @param  records Array of records to apply
    * @return Array of record IDs which did not apply cleanly
    */
   applyIncomingBatch: function (records) {
     let failed = [];
-    for each (let record in records) {
+    for (let record of records) {
       try {
         this.applyIncoming(record);
       } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) {
         // This kind of exception should have a 'cause' attribute, which is an
         // originating exception.
         // ex.cause will carry its stack with it when rethrown.
         throw ex.cause;
       } catch (ex if !Async.isShutdownException(ex)) {
@@ -492,17 +492,17 @@ EngineManager.prototype = {
    */
   getEnabled: function () {
     return this.getAll()
                .filter((engine) => engine.enabled)
                .sort((a, b) => a.syncPriority - b.syncPriority);
   },
 
   get enabledEngineNames() {
-    return [e.name for each (e in this.getEnabled())];
+    return this.getEnabled().map(e => e.name);
   },
 
   persistDeclined: function () {
     Svc.Prefs.set("declinedEngines", [...this._declined].join(","));
   },
 
   /**
    * Returns an array.
@@ -1459,24 +1459,25 @@ SyncEngine.prototype = {
 
         let failed_ids = Object.keys(resp.obj.failed);
         if (failed_ids.length)
           this._log.debug("Records that will be uploaded again because "
                           + "the server couldn't store them: "
                           + failed_ids.join(", "));
 
         // Clear successfully uploaded objects.
-        for each (let id in resp.obj.success) {
+        for (let key in resp.obj.success) {
+          let id = resp.obj.success[key];
           delete this._modified[id];
         }
 
         up.clearRecords();
       });
 
-      for each (let id in modifiedIDs) {
+      for (let id of modifiedIDs) {
         try {
           let out = this._createRecord(id);
           if (this._log.level <= Log.Level.Trace)
             this._log.trace("Outgoing: " + out);
 
           out.encrypt(this.service.collectionKeys.keyForCollection(this.name));
           up.pushData(out);
         } catch (ex if !Async.isShutdownException(ex)) {
--- a/services/sync/modules/engines/addons.js
+++ b/services/sync/modules/engines/addons.js
@@ -155,17 +155,17 @@ AddonsEngine.prototype = {
     }
 
     let lastSyncDate = new Date(this.lastSync * 1000);
 
     // The reconciler should have been refreshed at the beginning of a sync and
     // we assume this function is only called from within a sync.
     let reconcilerChanges = this._reconciler.getChangesSinceDate(lastSyncDate);
     let addons = this._reconciler.addons;
-    for each (let change in reconcilerChanges) {
+    for (let change of reconcilerChanges) {
       let changeTime = change[0];
       let id = change[2];
 
       if (!(id in addons)) {
         continue;
       }
 
       // Keep newest modified time.
@@ -294,17 +294,17 @@ AddonsStore.prototype = {
       requireSecureURI: !Svc.Prefs.get("addons.ignoreRepositoryChecking", false),
     }], cb);
 
     // This will throw if there was an error. This will get caught by the sync
     // engine and the record will try to be applied later.
     let results = cb.wait();
 
     let addon;
-    for each (let a in results.addons) {
+    for (let a of results.addons) {
       if (a.id == record.addonID) {
         addon = a;
         break;
       }
     }
 
     // This should never happen, but is present as a fail-safe.
     if (!addon) {
@@ -438,17 +438,18 @@ AddonsStore.prototype = {
    * Obtain the set of all syncable add-on Sync GUIDs.
    *
    * This implements a core Store API.
    */
   getAllIDs: function getAllIDs() {
     let ids = {};
 
     let addons = this.reconciler.addons;
-    for each (let addon in addons) {
+    for (let id in addons) {
+      let addon = addons[id];
       if (this.isAddonSyncable(addon)) {
         ids[addon.guid] = true;
       }
     }
 
     return ids;
   },
 
--- a/services/sync/modules/engines/bookmarks.js
+++ b/services/sync/modules/engines/bookmarks.js
@@ -174,17 +174,17 @@ var kSpecialIds = {
     if (guid == "mobile") {
       return this.findMobileRoot(create);
     }
     return this[guid];
   },
 
   // Don't bother creating mobile: if it doesn't exist, this ID can't be it!
   specialGUIDForId: function specialGUIDForId(id) {
-    for each (let guid in this.guids)
+    for (let guid of this.guids)
       if (this.specialIdForGUID(guid, false) == id)
         return guid;
     return null;
   },
 
   get menu() {
     return PlacesUtils.bookmarksMenuFolderId;
   },
@@ -502,17 +502,18 @@ BookmarksEngine.prototype = {
   }
 };
 
 function BookmarksStore(name, engine) {
   Store.call(this, name, engine);
 
   // Explicitly nullify our references to our cached services so we don't leak
   Svc.Obs.add("places-shutdown", function() {
-    for each (let [query, stmt] in Iterator(this._stmts)) {
+    for (let query in this._stmts) {
+      let stmt = this._stmts[query];
       stmt.finalize();
     }
     this._stmts = {};
   }, this);
 }
 BookmarksStore.prototype = {
   __proto__: Store.prototype,
 
@@ -559,17 +560,17 @@ BookmarksStore.prototype = {
     try {
       for (let i = 0; i < tags.childCount; i++) {
         let child = tags.getChild(i);
         if (child.title == tag) {
           // Found the tag, so fix up the query to use the right id.
           this._log.debug("Tag query folder: " + tag + " = " + child.itemId);
           
           this._log.trace("Replacing folders in: " + uri);
-          for each (let q in queriesRef.value)
+          for (let q of queriesRef.value)
             q.setFolders([child.itemId], 1);
           
           record.bmkUri = PlacesUtils.history.queriesToQueryString(
             queriesRef.value, queryCountRef.value, optionsRef.value);
           return;
         }
       }
     }
@@ -1356,29 +1357,29 @@ BookmarksStore.prototype = {
                  "unfiled": true,
                 };
     // We also want "mobile" but only if a local mobile folder already exists
     // (otherwise we'll later end up creating it, which we want to avoid until
     // we actually need it.)
     if (kSpecialIds.findMobileRoot(false)) {
       items["mobile"] = true;
     }
-    for each (let guid in kSpecialIds.guids) {
+    for (let guid of kSpecialIds.guids) {
       if (guid != "places" && guid != "tags")
         this._getChildren(guid, items);
     }
     return items;
   },
 
   wipe: function BStore_wipe() {
     let cb = Async.makeSpinningCallback();
     Task.spawn(function() {
       // Save a backup before clearing out all bookmarks.
       yield PlacesBackups.create(null, true);
-      for each (let guid in kSpecialIds.guids)
+      for (let guid of kSpecialIds.guids)
         if (guid != "places") {
           let id = kSpecialIds.specialIdForGUID(guid);
           if (id)
             PlacesUtils.bookmarks.removeFolderChildren(id);
         }
       cb();
     });
     cb.wait();
--- a/services/sync/modules/engines/clients.js
+++ b/services/sync/modules/engines/clients.js
@@ -63,17 +63,18 @@ ClientEngine.prototype = {
   // Aggregate some stats on the composition of clients on this account
   get stats() {
     let stats = {
       hasMobile: this.localType == "mobile",
       names: [this.localName],
       numClients: 1,
     };
 
-    for each (let {name, type} in this._store._remoteClients) {
+    for (let id in this._store._remoteClients) {
+      let {name, type} = this._store._remoteClients[id];
       stats.hasMobile = stats.hasMobile || type == "mobile";
       stats.names.push(name);
       stats.numClients++;
     }
 
     return stats;
   },
 
@@ -82,17 +83,18 @@ ClientEngine.prototype = {
    *
    * Returns a Map of device types to integer counts.
    */
   get deviceTypes() {
     let counts = new Map();
 
     counts.set(this.localType, 1);
 
-    for each (let record in this._store._remoteClients) {
+    for (let id in this._store._remoteClients) {
+      let record = this._store._remoteClients[id];
       let type = record.type;
       if (!counts.has(type)) {
         counts.set(type, 0);
       }
 
       counts.set(type, counts.get(type) + 1);
     }
 
@@ -253,17 +255,21 @@ ClientEngine.prototype = {
   processIncomingCommands: function processIncomingCommands() {
     return this._notify("clients:process-commands", "", function() {
       let commands = this.localCommands;
 
       // Immediately clear out the commands as we've got them locally.
       this.clearCommands();
 
       // Process each command in order.
-      for each (let {command, args} in commands) {
+      if (!commands) {
+        return true;
+      }
+      for (let key in commands) {
+        let {command, args} = commands[key];
         this._log.debug("Processing command: " + command + "(" + args + ")");
 
         let engines = [args[0]];
         switch (command) {
           case "resetAll":
             engines = null;
             // Fallthrough
           case "resetEngine":
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -65,17 +65,18 @@ HistoryEngine.prototype = {
   },
 };
 
 function HistoryStore(name, engine) {
   Store.call(this, name, engine);
 
   // Explicitly nullify our references to our cached services so we don't leak
   Svc.Obs.add("places-shutdown", function() {
-    for each ([query, stmt] in Iterator(this._stmts)) {
+    for (let query in this._stmts) {
+      let stmt = this._stmts;
       stmt.finalize();
     }
     this._stmts = {};
   }, this);
 }
 HistoryStore.prototype = {
   __proto__: Store.prototype,
 
--- a/services/sync/modules/engines/passwords.js
+++ b/services/sync/modules/engines/passwords.js
@@ -80,17 +80,17 @@ PasswordEngine.prototype = {
       return;
     }
 
     let logins = Services.logins.findLogins({}, login.hostname, login.formSubmitURL, login.httpRealm);
 
     this._store._sleep(0); // Yield back to main thread after synchronous operation.
 
     // Look for existing logins that match the hostname, but ignore the password.
-    for each (let local in logins) {
+    for (let local of logins) {
       if (login.matches(local, true) && local instanceof Ci.nsILoginMetaInfo) {
         return local.guid;
       }
     }
   },
 };
 
 function PasswordStore(name, engine) {
--- a/services/sync/modules/engines/prefs.js
+++ b/services/sync/modules/engines/prefs.js
@@ -96,17 +96,17 @@ PrefStore.prototype = {
 
   _isSynced: function (pref) {
     return pref.startsWith(PREF_SYNC_PREFS_PREFIX) ||
            this._prefs.get(PREF_SYNC_PREFS_PREFIX + pref, false);
   },
 
   _getAllPrefs: function () {
     let values = {};
-    for each (let pref in this._getSyncPrefs()) {
+    for (let pref of this._getSyncPrefs()) {
       if (this._isSynced(pref)) {
         // Missing prefs get the null value.
         values[pref] = this._prefs.get(pref, null);
       }
     }
     return values;
   },
 
--- a/services/sync/modules/engines/tabs.js
+++ b/services/sync/modules/engines/tabs.js
@@ -297,30 +297,30 @@ TabTracker.prototype = {
   clearChangedIDs: function () {
     this.modified = false;
   },
 
   _topics: ["pageshow", "TabOpen", "TabClose", "TabSelect"],
 
   _registerListenersForWindow: function (window) {
     this._log.trace("Registering tab listeners in window");
-    for each (let topic in this._topics) {
+    for (let topic of this._topics) {
       window.addEventListener(topic, this.onTab, false);
     }
     window.addEventListener("unload", this._unregisterListeners, false);
   },
 
   _unregisterListeners: function (event) {
     this._unregisterListenersForWindow(event.target);
   },
 
   _unregisterListenersForWindow: function (window) {
     this._log.trace("Removing tab listeners in window");
     window.removeEventListener("unload", this._unregisterListeners, false);
-    for each (let topic in this._topics) {
+    for (let topic of this._topics) {
       window.removeEventListener(topic, this.onTab, false);
     }
   },
 
   startTracking: function () {
     Svc.Obs.add("domwindowopened", this);
     let wins = Services.wm.getEnumerator("navigator:browser");
     while (wins.hasMoreElements()) {
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -190,17 +190,17 @@ IdentityManager.prototype = {
   get basicPassword() {
     if (this._basicPasswordAllowLookup) {
       // We need a username to find the credentials.
       let username = this.username;
       if (!username) {
         return null;
       }
 
-      for each (let login in this._getLogins(PWDMGR_PASSWORD_REALM)) {
+      for (let login of this._getLogins(PWDMGR_PASSWORD_REALM)) {
         if (login.username.toLowerCase() == username) {
           // It should already be UTF-8 encoded, but we don't take any chances.
           this._basicPassword = Utils.encodeUTF8(login.password);
         }
       }
 
       this._basicPasswordAllowLookup = false;
     }
@@ -244,17 +244,17 @@ IdentityManager.prototype = {
    */
   get syncKey() {
     if (this._syncKeyAllowLookup) {
       let username = this.username;
       if (!username) {
         return null;
       }
 
-      for each (let login in this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
+      for (let login of this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
         if (login.username.toLowerCase() == username) {
           this._syncKey = login.password;
         }
       }
 
       this._syncKeyAllowLookup = false;
     }
 
@@ -395,29 +395,29 @@ IdentityManager.prototype = {
    * entered), this could throw an exception.
    */
   persistCredentials: function persistCredentials(force) {
     if (this._basicPasswordUpdated || force) {
       if (this._basicPassword) {
         this._setLogin(PWDMGR_PASSWORD_REALM, this.username,
                        this._basicPassword);
       } else {
-        for each (let login in this._getLogins(PWDMGR_PASSWORD_REALM)) {
+        for (let login of this._getLogins(PWDMGR_PASSWORD_REALM)) {
           Services.logins.removeLogin(login);
         }
       }
 
       this._basicPasswordUpdated = false;
     }
 
     if (this._syncKeyUpdated || force) {
       if (this._syncKey) {
         this._setLogin(PWDMGR_PASSPHRASE_REALM, this.username, this._syncKey);
       } else {
-        for each (let login in this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
+        for (let login of this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
           Services.logins.removeLogin(login);
         }
       }
 
       this._syncKeyUpdated = false;
     }
 
   },
@@ -461,17 +461,17 @@ IdentityManager.prototype = {
   /**
    * Set a login in the password manager.
    *
    * This has the side-effect of deleting any other logins for the specified
    * realm.
    */
   _setLogin: function _setLogin(realm, username, password) {
     let exists = false;
-    for each (let login in this._getLogins(realm)) {
+    for (let login of this._getLogins(realm)) {
       if (login.username == username && login.password == password) {
         exists = true;
       } else {
         this._log.debug("Pruning old login for " + username + " from " + realm);
         Services.logins.removeLogin(login);
       }
     }
 
@@ -497,17 +497,17 @@ IdentityManager.prototype = {
   },
 
   /**
    * Deletes Sync credentials from the password manager.
    */
   deleteSyncCredentials: function deleteSyncCredentials() {
     for (let host of this._getSyncCredentialsHosts()) {
       let logins = Services.logins.findLogins({}, host, "", "");
-      for each (let login in logins) {
+      for (let login of logins) {
         Services.logins.removeLogin(login);
       }
     }
 
     // Wait until after store is updated in case it fails.
     this._basicPassword = null;
     this._basicPasswordAllowLookup = true;
     this._basicPasswordUpdated = false;
--- a/services/sync/modules/jpakeclient.js
+++ b/services/sync/modules/jpakeclient.js
@@ -276,28 +276,26 @@ JPAKEClient.prototype = {
   /*
    * Utilities
    */
 
   _setClientID: function _setClientID() {
     let rng = Cc["@mozilla.org/security/random-generator;1"]
                 .createInstance(Ci.nsIRandomGenerator);
     let bytes = rng.generateRandomBytes(JPAKE_LENGTH_CLIENTID / 2);
-    this._clientID = [("0" + byte.toString(16)).slice(-2)
-                      for each (byte in bytes)].join("");
+    this._clientID = bytes.map(byte => ("0" + byte.toString(16)).slice(-2)).join("");
   },
 
   _createSecret: function _createSecret() {
     // 0-9a-z without 1,l,o,0
     const key = "23456789abcdefghijkmnpqrstuvwxyz";
     let rng = Cc["@mozilla.org/security/random-generator;1"]
                 .createInstance(Ci.nsIRandomGenerator);
     let bytes = rng.generateRandomBytes(JPAKE_LENGTH_SECRET);
-    return [key[Math.floor(byte * key.length / 256)]
-            for each (byte in bytes)].join("");
+    return bytes.map(byte => key[Math.floor(byte * key.length / 256)]).join("");
   },
 
   _newRequest: function _newRequest(uri) {
     let request = new RESTRequest(uri);
     request.setHeader("X-KeyExchange-Id", this._clientID);
     request.timeout = REQUEST_TIMEOUT;
     return request;
   },
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -307,17 +307,17 @@ CollectionKeyManager.prototype = {
 
     // Diffs both ways.
     process(m1, m2);
     process(m2, m1);
 
     // Return a sorted, unique array.
     changed.sort();
     let last;
-    changed = [x for each (x in changed) if ((x != last) && (last = x))];
+    changed = changed.filter(x => (x != last) && (last = x));
     return {same: changed.length == 0,
             changed: changed};
   },
 
   get isClear() {
    return !this._default;
   },
 
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -437,17 +437,17 @@ Sync11Service.prototype = {
     let oldPrefBranch = "extensions.weave.";
     let oldPrefNames = Cc["@mozilla.org/preferences-service;1"].
                        getService(Ci.nsIPrefService).
                        getBranch(oldPrefBranch).
                        getChildList("", {});
 
     // Map each old pref to the current pref branch
     let oldPref = new Preferences(oldPrefBranch);
-    for each (let pref in oldPrefNames)
+    for (let pref of oldPrefNames)
       Svc.Prefs.set(pref, oldPref.get(pref));
 
     // Remove all the old prefs and remember that we've migrated
     oldPref.resetBranch("");
     Svc.Prefs.set("migrated", true);
   },
 
   /**
@@ -896,17 +896,17 @@ Sync11Service.prototype = {
   startOver: function startOver() {
     this._log.trace("Invoking Service.startOver.");
     Svc.Obs.notify("weave:engine:stop-tracking");
     this.status.resetSync();
 
     // Deletion doesn't make sense if we aren't set up yet!
     if (this.clusterURL != "") {
       // Clear client-specific data from the server, including disabled engines.
-      for each (let engine in [this.clientsEngine].concat(this.engineManager.getAll())) {
+      for (let engine of [this.clientsEngine].concat(this.engineManager.getAll())) {
         try {
           engine.removeClientData();
         } catch(ex) {
           this._log.warn("Deleting client data for " + engine.name + " failed:"
                          + Utils.exceptionStr(ex));
         }
       }
       this._log.debug("Finished deleting client data.");
@@ -1506,17 +1506,17 @@ Sync11Service.prototype = {
     // uploadMetaGlobal throws on failure -- including race conditions.
     // If we got into a race condition, we'll abort the sync this way, too.
     // That's fine. We'll just wait till the next sync. The client that we're
     // racing is probably busy uploading stuff right now anyway.
     this.uploadMetaGlobal(meta);
 
     // Wipe everything we know about except meta because we just uploaded it
     let engines = [this.clientsEngine].concat(this.engineManager.getAll());
-    let collections = [engine.name for each (engine in engines)];
+    let collections = engines.map(engine => engine.name);
     // TODO: there's a bug here. We should be calling resetClient, no?
 
     // Generate, upload, and download new keys. Do this last so we don't wipe
     // them...
     this.generateNewSymmetricKeys();
   },
 
   /**
@@ -1588,17 +1588,17 @@ Sync11Service.prototype = {
       engines = [this.clientsEngine].concat(this.engineManager.getAll());
     }
     // Convert the array of names into engines
     else {
       engines = this.engineManager.get(engines);
     }
 
     // Fully wipe each engine if it's able to decrypt data
-    for each (let engine in engines) {
+    for (let engine of engines) {
       if (engine.canDecrypt()) {
         engine.wipeClient();
       }
     }
 
     // Save the password/passphrase just in-case they aren't restored by sync
     this.persistLogin();
   },
@@ -1666,17 +1666,17 @@ Sync11Service.prototype = {
         engines = [this.clientsEngine].concat(this.engineManager.getAll());
       }
       // Convert the array of names into engines
       else {
         engines = this.engineManager.get(engines);
       }
 
       // Have each engine drop any temporary meta data
-      for each (let engine in engines) {
+      for (let engine of engines) {
         engine.resetClient();
       }
     })();
   },
 
   /**
    * Fetch storage info from the server.
    *
--- a/services/sync/modules/stages/declined.js
+++ b/services/sync/modules/stages/declined.js
@@ -24,18 +24,18 @@ Cu.import("resource://gre/modules/Prefer
 this.DeclinedEngines = function (service) {
   this._log = Log.repository.getLogger("Sync.Declined");
   this._log.level = Log.Level[new Preferences(PREFS_BRANCH).get("log.logger.declined")];
 
   this.service = service;
 }
 this.DeclinedEngines.prototype = {
   updateDeclined: function (meta, engineManager=this.service.engineManager) {
-    let enabled = new Set([e.name for each (e in engineManager.getEnabled())]);
-    let known = new Set([e.name for each (e in engineManager.getAll())]);
+    let enabled = new Set(engineManager.getEnabled().map(e => e.name));
+    let known = new Set(engineManager.getAll().map(e => e.name));
     let remoteDeclined = new Set(meta.payload.declined || []);
     let localDeclined = new Set(engineManager.getDeclined());
 
     this._log.debug("Handling remote declined: " + JSON.stringify([...remoteDeclined]));
     this._log.debug("Handling local declined: " + JSON.stringify([...localDeclined]));
 
     // Any engines that are locally enabled should be removed from the remote
     // declined list.
--- a/services/sync/modules/stages/enginesync.js
+++ b/services/sync/modules/stages/enginesync.js
@@ -284,17 +284,17 @@ EngineSynchronizer.prototype = {
           // This will be reflected in meta/global in the next stage.
           this._log.trace("Engine " + engineName + " was disabled locally. Marking as declined.");
           toDecline.add(engineName);
         }
       }
     }
 
     // Any remaining engines were either enabled locally or disabled remotely.
-    for each (let engineName in enabled) {
+    for (let engineName of enabled) {
       let engine = engineManager.get(engineName);
       if (Svc.Prefs.get("engineStatusChanged." + engine.prefName, false)) {
         this._log.trace("The " + engineName + " engine was enabled locally.");
         toUndecline.add(engineName);
       } else {
         this._log.trace("The " + engineName + " engine was disabled remotely.");
 
         // Don't automatically mark it as declined!
--- a/services/sync/tests/unit/head_appinfo.js
+++ b/services/sync/tests/unit/head_appinfo.js
@@ -55,15 +55,15 @@ registrar.registerFactory(Components.ID(
                           "XULAppInfo", "@mozilla.org/xre/app-info;1",
                           XULAppInfoFactory);
 
 
 // Register resource aliases. Normally done in SyncComponents.manifest.
 function addResourceAlias() {
   const resProt = Services.io.getProtocolHandler("resource")
                           .QueryInterface(Ci.nsIResProtocolHandler);
-  for each (let s in ["common", "sync", "crypto"]) {
+  for (let s of ["common", "sync", "crypto"]) {
     let uri = Services.io.newURI("resource://gre/modules/services-" + s + "/", null,
                                  null);
     resProt.setSubstitution("services-" + s, uri);
   }
 }
 addResourceAlias();
--- a/services/sync/tests/unit/head_http_server.js
+++ b/services/sync/tests/unit/head_http_server.js
@@ -304,17 +304,18 @@ ServerCollection.prototype = {
 
   post: function(input) {
     input = JSON.parse(input);
     let success = [];
     let failed = {};
 
     // This will count records where we have an existing ServerWBO
     // registered with us as successful and all other records as failed.
-    for each (let record in input) {
+    for (let key in input) {
+      let record = input[key];
       let wbo = this.wbo(record.id);
       if (!wbo && this.acceptNew) {
         this._log.debug("Creating WBO " + JSON.stringify(record.id) +
                         " on the fly.");
         wbo = new ServerWBO(record.id);
         this.insertWBO(wbo);
       }
       if (wbo) {
@@ -349,17 +350,17 @@ ServerCollection.prototype = {
 
     return function(request, response) {
       var statusCode = 200;
       var status = "OK";
       var body;
 
       // Parse queryString
       let options = {};
-      for each (let chunk in request.queryString.split("&")) {
+      for (let chunk of request.queryString.split("&")) {
         if (!chunk) {
           continue;
         }
         chunk = chunk.split("=");
         if (chunk.length == 1) {
           options[chunk[0]] = "";
         } else {
           options[chunk[0]] = chunk[1];
@@ -699,17 +700,18 @@ SyncServer.prototype = {
    *
    * @return a timestamp.
    */
   deleteCollections: function deleteCollections(username) {
     if (!(username in this.users)) {
       throw new Error("Unknown user.");
     }
     let userCollections = this.users[username].collections;
-    for each (let [name, coll] in Iterator(userCollections)) {
+    for (let name in userCollections) {
+      let coll = userCollections[name];
       this._log.trace("Bulk deleting " + name + " for " + username + "...");
       coll.delete({});
     }
     this.users[username].collections = {};
     return this.timestamp();
   },
 
   /**
@@ -763,17 +765,20 @@ SyncServer.prototype = {
 
   defaultHeaders: {},
 
   /**
    * HTTP response utility.
    */
   respond: function respond(req, resp, code, status, body, headers) {
     resp.setStatusLine(req.httpVersion, code, status);
-    for each (let [header, value] in Iterator(headers || this.defaultHeaders)) {
+    if (!headers)
+      headers = this.defaultHeaders;
+    for (let header in headers) {
+      let value = headers[header];
       resp.setHeader(header, value);
     }
     resp.setHeader("X-Weave-Timestamp", "" + this.timestamp(), false);
     resp.bodyOutputStream.write(body, body.length);
   },
 
   /**
    * This is invoked by the HttpServer. `this` is bound to the SyncServer;
--- a/services/sync/tests/unit/test_addons_reconciler.js
+++ b/services/sync/tests/unit/test_addons_reconciler.js
@@ -66,17 +66,17 @@ add_test(function test_install_detection
   let after = new Date();
 
   do_check_eq(1, Object.keys(reconciler.addons).length);
   do_check_true(addon.id in reconciler.addons);
   let record = reconciler.addons[addon.id];
 
   const KEYS = ["id", "guid", "enabled", "installed", "modified", "type",
                 "scope", "foreignInstall"];
-  for each (let key in KEYS) {
+  for (let key of KEYS) {
     do_check_true(key in record);
     do_check_neq(null, record[key]);
   }
 
   do_check_eq(addon.id, record.id);
   do_check_eq(addon.syncGUID, record.guid);
   do_check_true(record.enabled);
   do_check_true(record.installed);
--- a/services/sync/tests/unit/test_addons_store.js
+++ b/services/sync/tests/unit/test_addons_store.js
@@ -199,17 +199,17 @@ add_test(function test_addon_syncability
 
   do_check_false(store.isAddonSyncable(null));
 
   let addon = installAddon("test_bootstrap1_1");
   do_check_true(store.isAddonSyncable(addon));
 
   let dummy = {};
   const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall"];
-  for each (let k in KEYS) {
+  for (let k of KEYS) {
     dummy[k] = addon[k];
   }
 
   do_check_true(store.isAddonSyncable(dummy));
 
   dummy.type = "UNSUPPORTED";
   do_check_false(store.isAddonSyncable(dummy));
   dummy.type = addon.type;
@@ -238,26 +238,26 @@ add_test(function test_addon_syncability
   ];
 
   let untrusted = [
     "http://addons.mozilla.org/foo",     // non-https
     "ftps://addons.mozilla.org/foo",     // non-https
     "https://untrusted.example.com/foo", // non-trusted hostname`
   ];
 
-  for each (let uri in trusted) {
+  for (let uri of trusted) {
     do_check_true(store.isSourceURITrusted(createURI(uri)));
   }
 
-  for each (let uri in untrusted) {
+  for (let uri of untrusted) {
     do_check_false(store.isSourceURITrusted(createURI(uri)));
   }
 
   Svc.Prefs.set("addons.trustedSourceHostnames", "");
-  for each (let uri in trusted) {
+  for (let uri of trusted) {
     do_check_false(store.isSourceURITrusted(createURI(uri)));
   }
 
   Svc.Prefs.set("addons.trustedSourceHostnames", "addons.mozilla.org");
   do_check_true(store.isSourceURITrusted(createURI("https://addons.mozilla.org/foo")));
 
   Svc.Prefs.reset("addons.trustedSourceHostnames");
 
@@ -273,17 +273,17 @@ add_test(function test_ignore_hotfixes()
   // extensions.hotfix.id pref.
   let prefs = new Preferences("extensions.");
 
   let addon = installAddon("test_bootstrap1_1");
   do_check_true(store.isAddonSyncable(addon));
 
   let dummy = {};
   const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall"];
-  for each (let k in KEYS) {
+  for (let k of KEYS) {
     dummy[k] = addon[k];
   }
 
   // Basic sanity check.
   do_check_true(store.isAddonSyncable(dummy));
 
   prefs.set("hotfix.id", dummy.id);
   do_check_false(store.isAddonSyncable(dummy));
--- a/services/sync/tests/unit/test_bookmark_store.js
+++ b/services/sync/tests/unit/test_bookmark_store.js
@@ -75,18 +75,18 @@ add_test(function test_bookmark_create()
                 fxrecord.description);
     do_check_eq(PlacesUtils.bookmarks.getFolderIdForItem(id),
                 PlacesUtils.bookmarks.toolbarFolder);
     do_check_eq(PlacesUtils.bookmarks.getKeywordForBookmark(id), fxrecord.keyword);
 
     _("Have the store create a new record object. Verify that it has the same data.");
     let newrecord = store.createRecord(fxrecord.id);
     do_check_true(newrecord instanceof Bookmark);
-    for each (let property in ["type", "bmkUri", "description", "title",
-                               "keyword", "parentName", "parentid"]) {
+    for (let property of ["type", "bmkUri", "description", "title",
+                          "keyword", "parentName", "parentid"]) {
       do_check_eq(newrecord[property], fxrecord[property]);
     }
     do_check_true(Utils.deepEquals(newrecord.tags.sort(),
                                    fxrecord.tags.sort()));
 
     _("The calculated sort index is based on frecency data.");
     do_check_true(newrecord.sortindex >= 150);
 
@@ -192,17 +192,17 @@ add_test(function test_folder_create() {
                 PlacesUtils.bookmarks.TYPE_FOLDER);
     do_check_eq(PlacesUtils.bookmarks.getItemTitle(id), folder.title);
     do_check_eq(PlacesUtils.bookmarks.getFolderIdForItem(id),
                 PlacesUtils.bookmarks.toolbarFolder);
 
     _("Have the store create a new record object. Verify that it has the same data.");
     let newrecord = store.createRecord(folder.id);
     do_check_true(newrecord instanceof BookmarkFolder);
-    for each (let property in ["title", "parentName", "parentid"])
+    for (let property of ["title", "parentName", "parentid"])
       do_check_eq(newrecord[property], folder[property]);
 
     _("Folders have high sort index to ensure they're synced first.");
     do_check_eq(newrecord.sortindex, 1000000);
   } finally {
     _("Clean up.");
     store.wipe();
     run_next_test();
--- a/services/sync/tests/unit/test_clients_engine.js
+++ b/services/sync/tests/unit/test_clients_engine.js
@@ -323,17 +323,17 @@ add_test(function test_command_validatio
     ["wipeAll",     ["foo"],  false],
     ["wipeEngine",  ["tabs"], true ],
     ["wipeEngine",  [],       false],
     ["logout",      [],       true ],
     ["logout",      ["foo"],  false],
     ["__UNKNOWN__", [],       false]
   ];
 
-  for each (let [action, args, expectedResult] in testCommands) {
+  for (let [action, args, expectedResult] of testCommands) {
     let remoteId = Utils.makeGUID();
     let rec = new ClientsRec("clients", remoteId);
 
     store.create(rec);
     store.createRecord(remoteId, "clients");
 
     engine.sendCommand(action, args, remoteId);
 
--- a/services/sync/tests/unit/test_collections_recovery.js
+++ b/services/sync/tests/unit/test_collections_recovery.js
@@ -28,17 +28,17 @@ add_identity_test(this, function test_mi
 
   let handlers = {
     "/1.1/johndoe/info/collections": maybe_empty(johnHelper.handler),
     "/1.1/johndoe/storage/crypto/keys": johnU("crypto", new ServerWBO("keys").handler()),
     "/1.1/johndoe/storage/meta/global": johnU("meta",   new ServerWBO("global").handler())
   };
   let collections = ["clients", "bookmarks", "forms", "history",
                      "passwords", "prefs", "tabs"];
-  for each (let coll in collections) {
+  for (let coll of collections) {
     handlers["/1.1/johndoe/storage/" + coll] =
       johnU(coll, new ServerCollection({}, true).handler());
   }
   let server = httpd_setup(handlers);
   Service.serverURL = server.baseURI;
 
   try {
     let fresh = 0;
--- a/services/sync/tests/unit/test_jpakeclient.js
+++ b/services/sync/tests/unit/test_jpakeclient.js
@@ -364,17 +364,17 @@ add_test(function test_wrongPIN() {
   });
 
   let pairingStartCalledOnReceiver = false;
   let rec = new JPAKEClient({
     __proto__: BaseController,
     displayPIN: function displayPIN(pin) {
       this.cid = pin.slice(JPAKE_LENGTH_SECRET);
       let secret = pin.slice(0, JPAKE_LENGTH_SECRET);
-      secret = [char for each (char in secret)].reverse().join("");
+      secret = Array.prototype.slice.call(secret).reverse().join("");
       let new_pin = secret + this.cid;
       _("Received PIN " + pin + ", but I'm entering " + new_pin);
 
       Utils.nextTick(function() { snd.pairWithPIN(new_pin, false); });
     },
     onPairingStart: function onPairingStart() {
       pairingStartCalledOnReceiver = true;
     },
--- a/services/sync/tests/unit/test_resource.js
+++ b/services/sync/tests/unit/test_resource.js
@@ -135,17 +135,17 @@ function server_headers(metadata, respon
     let header = headers.getNext().toString();
     if (ignore_headers.indexOf(header) == -1) {
       header_names.push(header);
     }
   }
   header_names = header_names.sort();
 
   headers = {};
-  for each (let header in header_names) {
+  for (let header of header_names) {
     headers[header] = metadata.getHeader(header);
   }
   let body = JSON.stringify(headers);
   response.setStatusLine(metadata.httpVersion, 200, "OK");
   response.bodyOutputStream.write(body, body.length);
 }
 
 function run_test() {
--- a/services/sync/tests/unit/test_resource_async.js
+++ b/services/sync/tests/unit/test_resource_async.js
@@ -135,17 +135,17 @@ function server_headers(metadata, respon
     let header = headers.getNext().toString();
     if (ignore_headers.indexOf(header) == -1) {
       header_names.push(header);
     }
   }
   header_names = header_names.sort();
 
   headers = {};
-  for each (let header in header_names) {
+  for (let header of header_names) {
     headers[header] = metadata.getHeader(header);
   }
   let body = JSON.stringify(headers);
   response.setStatusLine(metadata.httpVersion, 200, "OK");
   response.bodyOutputStream.write(body, body.length);
 }
 
 var quotaValue;
--- a/services/sync/tests/unit/test_service_startup.js
+++ b/services/sync/tests/unit/test_service_startup.js
@@ -24,17 +24,17 @@ function run_test() {
 
   Cu.import("resource://services-sync/service.js");
 
   _("Service is enabled.");
   do_check_eq(Service.enabled, true);
 
   _("Engines are registered.");
   let engines = Service.engineManager.getAll();
-  do_check_true(Utils.deepEquals([engine.name for each (engine in engines)],
+  do_check_true(Utils.deepEquals(engines.map(engine => engine.name),
                                  ['tabs', 'bookmarks', 'forms', 'history']));
 
   _("Observers are notified of startup");
   do_test_pending();
 
   do_check_false(Service.status.ready);
   do_check_false(xps.ready);
   Observers.add("weave:service:ready", function (subject, data) {
--- a/services/sync/tests/unit/test_status.js
+++ b/services/sync/tests/unit/test_status.js
@@ -13,19 +13,19 @@ function run_test() {
   do_check_eq(Status.login, LOGIN_SUCCEEDED);
   for (let name in Status.engines) {
     do_throw('Status.engines should be empty.');
   }
   do_check_eq(Status.partial, false);
 
 
   // Check login status
-  for each (let code in [LOGIN_FAILED_NO_USERNAME,
-                         LOGIN_FAILED_NO_PASSWORD,
-                         LOGIN_FAILED_NO_PASSPHRASE]) {
+  for (let code of [LOGIN_FAILED_NO_USERNAME,
+                    LOGIN_FAILED_NO_PASSWORD,
+                    LOGIN_FAILED_NO_PASSPHRASE]) {
     Status.login = code;
     do_check_eq(Status.login, code);
     do_check_eq(Status.service, CLIENT_NOT_CONFIGURED);
     Status.resetSync();
   }
 
   Status.login = LOGIN_FAILED;
   do_check_eq(Status.login, LOGIN_FAILED);
--- a/services/sync/tests/unit/test_tab_tracker.js
+++ b/services/sync/tests/unit/test_tab_tracker.js
@@ -48,42 +48,42 @@ function run_test() {
                                  [clientsEngine.localID]));
 
   let logs;
 
   _("Test listeners are registered on windows");
   logs = fakeSvcWinMediator();
   Svc.Obs.notify("weave:engine:start-tracking");
   do_check_eq(logs.length, 2);
-  for each (let log in logs) {
+  for (let log of logs) {
     do_check_eq(log.addTopics.length, 5);
     do_check_true(log.addTopics.indexOf("pageshow") >= 0);
     do_check_true(log.addTopics.indexOf("TabOpen") >= 0);
     do_check_true(log.addTopics.indexOf("TabClose") >= 0);
     do_check_true(log.addTopics.indexOf("TabSelect") >= 0);
     do_check_true(log.addTopics.indexOf("unload") >= 0);
     do_check_eq(log.remTopics.length, 0);
   }
 
   _("Test listeners are unregistered on windows");
   logs = fakeSvcWinMediator();
   Svc.Obs.notify("weave:engine:stop-tracking");
   do_check_eq(logs.length, 2);
-  for each (let log in logs) {
+  for (let log of logs) {
     do_check_eq(log.addTopics.length, 0);
     do_check_eq(log.remTopics.length, 5);
     do_check_true(log.remTopics.indexOf("pageshow") >= 0);
     do_check_true(log.remTopics.indexOf("TabOpen") >= 0);
     do_check_true(log.remTopics.indexOf("TabClose") >= 0);
     do_check_true(log.remTopics.indexOf("TabSelect") >= 0);
     do_check_true(log.remTopics.indexOf("unload") >= 0);
   }
 
   _("Test tab listener");
-  for each (let evttype in ["TabOpen", "TabClose", "TabSelect"]) {
+  for (let evttype of ["TabOpen", "TabClose", "TabSelect"]) {
     // Pretend we just synced.
     tracker.clearChangedIDs();
     do_check_false(tracker.modified);
 
     // Send a fake tab event
     tracker.onTab({type: evttype , originalTarget: evttype});
     do_check_true(tracker.modified);
     do_check_true(Utils.deepEquals(Object.keys(engine.getChangedIDs()),
--- a/services/sync/tps/extensions/mozmill/resource/driver/controller.js
+++ b/services/sync/tps/extensions/mozmill/resource/driver/controller.js
@@ -39,17 +39,21 @@ waitForEvents.prototype = {
     if (node.getNode != undefined)
       node = node.getNode();
 
     this.events = events;
     this.node = node;
     node.firedEvents = {};
     this.registry = {};
 
-    for each (var e in events) {
+    if (!events) {
+      return;
+    }
+    for (var key in events) {
+      var e = events[key];
       var listener = function (event) {
         this.firedEvents[event.type] = true;
       }
 
       this.registry[e] = listener;
       this.registry[e].result = false;
       this.node.addEventListener(e, this.registry[e], true);
     }
--- a/services/sync/tps/extensions/mozmill/resource/driver/elementslib.js
+++ b/services/sync/tps/extensions/mozmill/resource/driver/elementslib.js
@@ -299,31 +299,31 @@ var _returnResult = function (results) {
     return results[0];
   } else {
     return results;
   }
 }
 
 var _forChildren = function (element, name, value) {
   var results = [];
-  var nodes = [e for each (e in element.childNodes) if (e)]
+  var nodes = Array.from(element.childNodes).filter(e => e);
 
   for (var i in nodes) {
     var n = nodes[i];
     if (n[name] == value) {
       results.push(n);
     }
   }
 
   return results;
 }
 
 var _forAnonChildren = function (_document, element, name, value) {
   var results = [];
-  var nodes = [e for each (e in _document.getAnoymousNodes(element)) if (e)];
+  var nodes = Array.from(_document.getAnoymousNodes(element)).filter(e => e);
 
   for (var i in nodes ) {
     var n = nodes[i];
     if (n[name] == value) {
       results.push(n);
     }
   }
 
@@ -376,17 +376,17 @@ var _byAnonAttrib = function (_document,
     }
 
     var result = _document.getAnonymousElementByAttribute(parent, k, v);
     if (result) {
       return result;
     }
   }
 
-  var nodes = [n for each (n in _document.getAnonymousNodes(parent)) if (n.getAttribute)];
+  var nodes = Array.from(_document.getAnonymousNodes(parent)).filter(n => n.getAttribute);
 
   function resultsForNodes (nodes) {
     for (var i in nodes) {
       var n = nodes[i];
       requirementPass = 0;
       requirementLength = 0;
 
       for (var a in attributes) {
@@ -399,17 +399,17 @@ var _byAnonAttrib = function (_document,
       if (requirementPass == requirementLength) {
         results.push(n);
       }
     }
   }
 
   resultsForNodes(nodes);
   if (results.length == 0) {
-    resultsForNodes([n for each (n in parent.childNodes) if (n != undefined && n.getAttribute)])
+    resultsForNodes(Array.from(parent.childNodes).filter(n => n != undefined && n.getAttribute));
   }
 
   return _returnResult(results)
 }
 
 var _byIndex = function (_document, parent, i) {
   if (parent instanceof Array) {
     return parent[i];
@@ -435,17 +435,17 @@ var _anonByIndex = function (_document, 
  *
  * Finds an element by Lookup expression
  */
 function Lookup(_document, expression) {
   if (expression == undefined) {
     throw new Error('Lookup constructor did not recieve enough arguments.');
   }
 
-  var expSplit = [e for each (e in smartSplit(expression) ) if (e != '')];
+  var expSplit = smartSplit(expression).filter(e => e != '');
   expSplit.unshift(_document);
 
   var nCases = {'id':_byID, 'name':_byName, 'attrib':_byAttrib, 'index':_byIndex};
   var aCases = {'name':_anonByName, 'attrib':_anonByAttrib, 'index':_anonByIndex};
 
   /**
    * Reduces the lookup expression
    * @param {Object} parentNode
--- a/services/sync/tps/extensions/mozmill/resource/modules/frame.js
+++ b/services/sync/tps/extensions/mozmill/resource/modules/frame.js
@@ -251,17 +251,17 @@ events.endModule = function (aModule) {
 }
 
 events.pass = function (obj) {
   // a low level event, such as a keystroke, succeeds
   if (events.currentTest) {
     events.currentTest.__passes__.push(obj);
   }
 
-  for each (var timer in timers) {
+  for (var timer of timers) {
     timer.actions.push(
       {"currentTest": events.currentModule.__file__ + "::" + events.currentTest.__name__,
        "obj": obj,
        "result": "pass"}
     );
   }
 
   events.fireEvent('pass', obj);
@@ -281,17 +281,17 @@ events.fail = function (obj) {
     };
   }
 
   // a low level event, such as a keystroke, fails
   if (events.currentTest) {
     events.currentTest.__fails__.push(obj);
   }
 
-  for each (var time in timers) {
+  for (var time of timers) {
     timer.actions.push(
       {"currentTest": events.currentModule.__file__ + "::" + events.currentTest.__name__,
        "obj": obj,
        "result": "fail"}
     );
   }
 
   events.fireEvent('fail', obj);
@@ -320,17 +320,17 @@ events.fireEvent = function (name, obj) 
   }
 
   if (this.listeners[name]) {
     for (var i in this.listeners[name]) {
       this.listeners[name][i](obj);
     }
   }
 
-  for each(var listener in this.globalListeners) {
+  for (var listener of this.globalListeners) {
     listener(name, obj);
   }
 }
 
 events.addListener = function (name, listener) {
   if (this.listeners[name]) {
     this.listeners[name].push(listener);
   } else if (name == '') {
--- a/services/sync/tps/extensions/mozmill/resource/stdlib/os.js
+++ b/services/sync/tps/extensions/mozmill/resource/stdlib/os.js
@@ -32,17 +32,17 @@ function getFileForPath(path) {
 
 function abspath(rel, file) {
   var relSplit = rel.split('/');
 
   if (relSplit[0] == '..' && !file.isDirectory()) {
     file = file.parent;
   }
 
-  for each(var p in relSplit) {
+  for (var p of relSplit) {
     if (p == '..') {
       file = file.parent;
     } else if (p == '.') {
       if (!file.isDirectory()) {
         file = file.parent;
       }
     } else {
       file.append(p);
--- a/services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
+++ b/services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
@@ -163,18 +163,17 @@
 
    exports.Loader = function Loader(options) {
      options = {__proto__: options};
      if (options.fs === undefined) {
        var rootPaths = options.rootPath || options.rootPaths;
        if (rootPaths) {
          if (rootPaths.constructor.name != "Array")
            rootPaths = [rootPaths];
-         var fses = [new exports.LocalFileSystem(path)
-                     for each (path in rootPaths)];
+         var fses = rootPaths.map(path => new exports.LocalFileSystem(path));
          options.fs = new exports.CompositeFileSystem(fses);
        } else
          options.fs = new exports.LocalFileSystem();
      }
      if (options.sandboxFactory === undefined)
        options.sandboxFactory = new exports.SandboxFactory(
          options.defaultPrincipal
        );
--- a/services/sync/tps/extensions/mozmill/resource/stdlib/utils.js
+++ b/services/sync/tps/extensions/mozmill/resource/stdlib/utils.js
@@ -78,27 +78,27 @@ function getWindows(type) {
   if (type == "") {
     windows.push(hwindow);
   }
 
   return windows;
 }
 
 function getMethodInWindows(methodName) {
-  for each (var w in getWindows()) {
+  for (var w of getWindows()) {
     if (w[methodName] != undefined) {
       return w[methodName];
     }
   }
 
   throw new Error("Method with name: '" + methodName + "' is not in any open window.");
 }
 
 function getWindowByTitle(title) {
-  for each (var w in getWindows()) {
+  for (var w of getWindows()) {
     if (w.document.title && w.document.title == title) {
       return w;
     }
   }
 
   throw new Error("Window with title: '" + title + "' not found.");
 }
 
--- a/services/sync/tps/extensions/tps/resource/modules/history.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/history.jsm
@@ -28,17 +28,17 @@ var DumpHistory = function TPS_History__
   let options = PlacesUtils.history.getNewQueryOptions();
   let root = PlacesUtils.history.executeQuery(query, options).root;
   root.containerOpen = true;
   Logger.logInfo("\n\ndumping history\n", true);
   for (var i = 0; i < root.childCount; i++) {
     let node = root.getChild(i);
     let uri = node.uri;
     let curvisits = HistoryEntry._getVisits(uri);
-    for each (var visit in curvisits) {
+    for (var visit of curvisits) {
       Logger.logInfo("URI: " + uri + ", type=" + visit.type + ", date=" + visit.date, true);
     }
   }
   root.containerOpen = false;
   Logger.logInfo("\nend history dump\n", true);
 };
 
 /**
@@ -105,17 +105,17 @@ var HistoryEntry = {
     Logger.AssertTrue("visits" in item && "uri" in item,
       "History entry in test file must have both 'visits' " +
       "and 'uri' properties");
     let uri = Services.io.newURI(item.uri, null, null);
     let place = {
       uri: uri,
       visits: []
     };
-    for each (visit in item.visits) {
+    for (let visit of item.visits) {
       place.visits.push({
         visitDate: usSinceEpoch + (visit.date * 60 * 60 * 1000 * 1000),
         transitionType: visit.type
       });
     }
     if ("title" in item) {
       place.title = item.title;
     }
@@ -145,28 +145,28 @@ var HistoryEntry = {
    *        the time the current Crossweave run was started
    * @return true if all the visits for the uri are found, otherwise false
    */
   Find: function(item, usSinceEpoch) {
     Logger.AssertTrue("visits" in item && "uri" in item,
       "History entry in test file must have both 'visits' " +
       "and 'uri' properties");
     let curvisits = this._getVisits(item.uri);
-    for each (visit in curvisits) {
-      for each (itemvisit in item.visits) {
+    for (let visit of curvisits) {
+      for (let itemvisit of item.visits) {
         let expectedDate = itemvisit.date * 60 * 60 * 1000 * 1000
             + usSinceEpoch;
         if (visit.type == itemvisit.type && visit.date == expectedDate) {
           itemvisit.found = true;
         }
       }
     }
 
     let all_items_found = true;
-    for each (itemvisit in item.visits) {
+    for (let itemvisit in item.visits) {
       all_items_found = all_items_found && "found" in itemvisit;
       Logger.logInfo("History entry for " + item.uri + ", type:" +
               itemvisit.type + ", date:" + itemvisit.date +
               ("found" in itemvisit ? " is present" : " is not present"));
     }
     return all_items_found;
   },
 
--- a/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
@@ -45,17 +45,21 @@ var BrowserTabs = {
    * @param title The page title of the tab to find
    * @param profile The profile to search for tabs
    * @return true if the specified tab could be found, otherwise false
    */
   Find: function(uri, title, profile) {
     // Find the uri in Weave's list of tabs for the given profile.
     let engine = Weave.Service.engineManager.get("tabs");
     for (let [guid, client] in Iterator(engine.getAllClients())) {
-      for each (tab in client.tabs) {
+      if (!client.tabs) {
+        continue;
+      }
+      for (let key in client.tabs) {
+        let tab = client.tabs[key];
         let weaveTabUrl = tab.urlHistory[0];
         if (uri == weaveTabUrl && profile == client.clientName)
           if (title == undefined || title == tab.title)
             return true;
       }
     }
     return false;
   },
--- a/services/sync/tps/extensions/tps/resource/tps.jsm
+++ b/services/sync/tps/extensions/tps/resource/tps.jsm
@@ -280,17 +280,17 @@ var TPS = {
         break;
     }
     Logger.logPass("executing action " + action.toUpperCase() + " on windows");
   },
 
   HandleTabs: function (tabs, action) {
     this._tabsAdded = tabs.length;
     this._tabsFinished = 0;
-    for each (let tab in tabs) {
+    for (let tab of tabs) {
       Logger.logInfo("executing action " + action.toUpperCase() +
                      " on tab " + JSON.stringify(tab));
       switch(action) {
         case ACTION_ADD:
           // When adding tabs, we keep track of how many tabs we're adding,
           // and wait until we've received that many onload events from our
           // new tabs before continuing
           let that = this;
@@ -325,17 +325,17 @@ var TPS = {
         default:
           Logger.AssertTrue(false, "invalid action: " + action);
       }
     }
     Logger.logPass("executing action " + action.toUpperCase() + " on tabs");
   },
 
   HandlePrefs: function (prefs, action) {
-    for each (pref in prefs) {
+    for (let pref of prefs) {
       Logger.logInfo("executing action " + action.toUpperCase() +
                      " on pref " + JSON.stringify(pref));
       let preference = new Preference(pref);
       switch(action) {
         case ACTION_MODIFY:
           preference.Modify();
           break;
         case ACTION_VERIFY:
@@ -344,17 +344,17 @@ var TPS = {
         default:
           Logger.AssertTrue(false, "invalid action: " + action);
       }
     }
     Logger.logPass("executing action " + action.toUpperCase() + " on pref");
   },
 
   HandleForms: function (data, action) {
-    for each (datum in data) {
+    for (let datum of data) {
       Logger.logInfo("executing action " + action.toUpperCase() +
                      " on form entry " + JSON.stringify(datum));
       let formdata = new FormData(datum, this._usSinceEpoch);
       switch(action) {
         case ACTION_ADD:
           formdata.Create();
           break;
         case ACTION_DELETE:
@@ -372,17 +372,17 @@ var TPS = {
       }
     }
     Logger.logPass("executing action " + action.toUpperCase() +
                    " on formdata");
   },
 
   HandleHistory: function (entries, action) {
     try {
-      for each (entry in entries) {
+      for (let entry of entries) {
         Logger.logInfo("executing action " + action.toUpperCase() +
                        " on history entry " + JSON.stringify(entry));
         switch(action) {
           case ACTION_ADD:
             HistoryEntry.Add(entry, this._usSinceEpoch);
             break;
           case ACTION_DELETE:
             HistoryEntry.Delete(entry, this._usSinceEpoch);
@@ -405,17 +405,17 @@ var TPS = {
     catch(e) {
       DumpHistory();
       throw(e);
     }
   },
 
   HandlePasswords: function (passwords, action) {
     try {
-      for each (password in passwords) {
+      for (let password of passwords) {
         let password_id = -1;
         Logger.logInfo("executing action " + action.toUpperCase() +
                       " on password " + JSON.stringify(password));
         var password = new Password(password);
         switch (action) {
           case ACTION_ADD:
             Logger.AssertTrue(password.Create() > -1, "error adding password");
             break;
@@ -445,17 +445,17 @@ var TPS = {
     }
     catch(e) {
       DumpPasswords();
       throw(e);
     }
   },
 
   HandleAddons: function (addons, action, state) {
-    for each (let entry in addons) {
+    for (let entry of addons) {
       Logger.logInfo("executing action " + action.toUpperCase() +
                      " on addon " + JSON.stringify(entry));
       let addon = new Addon(this, entry);
       switch(action) {
         case ACTION_ADD:
           addon.install();
           break;
         case ACTION_DELETE:
@@ -476,19 +476,19 @@ var TPS = {
     }
     Logger.logPass("executing action " + action.toUpperCase() +
                    " on addons");
   },
 
   HandleBookmarks: function (bookmarks, action) {
     try {
       let items = [];
-      for (folder in bookmarks) {
+      for (let folder in bookmarks) {
         let last_item_pos = -1;
-        for each (bookmark in bookmarks[folder]) {
+        for (let bookmark of bookmarks[folder]) {
           Logger.clearPotentialError();
           let placesItem;
           bookmark['location'] = folder;
 
           if (last_item_pos != -1)
             bookmark['last_item_pos'] = last_item_pos;
           let item_id = -1;
 
@@ -520,17 +520,17 @@ var TPS = {
           }
 
           last_item_pos = placesItem.GetItemIndex();
           items.push(placesItem);
         }
       }
 
       if (action == ACTION_DELETE || action == ACTION_MODIFY) {
-        for each (item in items) {
+        for (let item of items) {
           Logger.logInfo("executing action " + action.toUpperCase() +
                          " on bookmark " + JSON.stringify(item));
           switch(action) {
             case ACTION_DELETE:
               item.Remove();
               break;
             case ACTION_MODIFY:
               if (item.updateProps != null)
@@ -684,17 +684,17 @@ var TPS = {
         this.DumpError("no profile defined for phase " + this._currentPhase);
         return;
       }
 
       // If we have restricted the active engines, unregister engines we don't
       // care about.
       if (settings.ignoreUnusedEngines && Array.isArray(this._enabledEngines)) {
         let names = {};
-        for each (let name in this._enabledEngines) {
+        for (let name of this._enabledEngines) {
           names[name] = true;
         }
 
         for (let engine of Weave.Service.engineManager.getEnabled()) {
           if (!(engine.name in names)) {
             Logger.logInfo("Unregistering unused engine: " + engine.name);
             Weave.Service.engineManager.unregister(engine);
           }