Bug 1221634 - Remove for-each from calendar/. r=Fallen
authorTooru Fujisawa <arai_a@mac.com>
Wed, 16 Dec 2015 04:53:38 +0900
changeset 23972 ef3eebaf957dd3d48b9da69c75d288eb6882b6bf
parent 23971 f102a2d706b32b09812bada1b84e0f4267abffe6
child 23973 55858ec8f8ffed66fbb090724f807916eed1bc14
push id1591
push userclokep@gmail.com
push dateMon, 07 Mar 2016 14:58:27 +0000
treeherdercomm-beta@3b5f8d26497f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFallen
bugs1221634
Bug 1221634 - Remove for-each from calendar/. r=Fallen
calendar/base/backend/icaljs/calICSService.js
calendar/base/content/agenda-listbox.js
calendar/base/content/calendar-base-view.xml
calendar/base/content/calendar-clipboard.js
calendar/base/content/calendar-common-sets.js
calendar/base/content/calendar-dnd-listener.js
calendar/base/content/calendar-invitations-manager.js
calendar/base/content/calendar-item-editing.js
calendar/base/content/calendar-month-view.xml
calendar/base/content/calendar-multiday-view.xml
calendar/base/content/calendar-task-tree.xml
calendar/base/content/calendar-task-view.js
calendar/base/content/calendar-ui-utils.js
calendar/base/content/calendar-unifinder.js
calendar/base/content/calendar-views.js
calendar/base/content/dialogs/calendar-alarm-dialog.js
calendar/base/content/dialogs/calendar-dialog-utils.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
calendar/base/content/dialogs/calendar-event-dialog-reminder.js
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/dialogs/calendar-invitations-dialog.js
calendar/base/content/dialogs/calendar-migration-dialog.js
calendar/base/content/dialogs/calendar-print-dialog.js
calendar/base/content/dialogs/calendar-properties-dialog.js
calendar/base/content/dialogs/calendar-subscriptions-dialog.js
calendar/base/content/import-export.js
calendar/base/content/widgets/calendar-list-tree.xml
calendar/base/content/widgets/calendar-widgets.xml
calendar/base/content/widgets/minimonth.xml
calendar/base/modules/calAuthUtils.jsm
calendar/base/modules/calItemUtils.jsm
calendar/base/modules/calIteratorUtils.jsm
calendar/base/modules/calItipUtils.jsm
calendar/base/modules/calPrintUtils.jsm
calendar/base/modules/calRecurrenceUtils.jsm
calendar/base/modules/calUtils.jsm
calendar/base/src/calAlarm.js
calendar/base/src/calAlarmMonitor.js
calendar/base/src/calAlarmService.js
calendar/base/src/calAttachment.js
calendar/base/src/calAttendee.js
calendar/base/src/calCachedCalendar.js
calendar/base/src/calCalendarManager.js
calendar/base/src/calDefaultACLManager.js
calendar/base/src/calFilter.js
calendar/base/src/calIcsParser.js
calendar/base/src/calIcsSerializer.js
calendar/base/src/calItemBase.js
calendar/base/src/calItipItem.js
calendar/base/src/calRecurrenceInfo.js
calendar/base/src/calRelation.js
calendar/base/src/calTimezoneService.js
calendar/base/src/calUtils.js
calendar/import-export/calHtmlExport.js
calendar/import-export/calMonthGridPrinter.js
calendar/import-export/calOutlookCSVImportExport.js
calendar/import-export/calWeekPrinter.js
calendar/providers/caldav/calDavCalendar.js
calendar/providers/composite/calCompositeCalendar.js
calendar/providers/ics/calICSCalendar.js
calendar/providers/storage/calStorageCalendar.js
calendar/providers/storage/calStorageUpgrade.jsm
calendar/providers/wcap/calWcapCalendar.js
calendar/providers/wcap/calWcapCalendarItems.js
calendar/providers/wcap/calWcapRequest.js
calendar/providers/wcap/calWcapSession.js
calendar/resources/content/datetimepickers/datetimepickers.xml
calendar/test/mozmill/shared-modules/timezone-utils.js
calendar/test/unit/test_alarmservice.js
calendar/test/unit/test_ics.js
calendar/test/unit/test_ics_service.js
calendar/test/unit/test_providers.js
calendar/test/unit/test_storage.js
--- a/calendar/base/backend/icaljs/calICSService.js
+++ b/calendar/base/backend/icaljs/calICSService.js
@@ -174,17 +174,17 @@ calIcalProperty.prototype = {
                     details.defaultType != innerObject.type) {
                     // Default type doesn't match object type, so we have a VALUE
                     // parameter
                     yield "VALUE";
                 }
             }
 
             let paramNames = Object.keys(innerObject.jCal[1] || {});
-            for each (let name in paramNames) {
+            for (let name of paramNames) {
                 yield name.toUpperCase();
             }
         })();
         return this.getNextParameterName();
     },
 
     getNextParameterName: function() {
         if (this.paramIterator) {
@@ -231,18 +231,20 @@ calIcalComponent.prototype = {
         if (kind == "ANY") {
             kind = null;
         } else if (kind) {
             kind = kind.toLowerCase();
         }
         let innerObject = this.innerObject;
         this.componentIterator = (function() {
             let comps = innerObject.getAllSubcomponents(kind);
-            for each (let comp in comps) {
-                yield new calIcalComponent(comp);
+            if (comps) {
+                for (let comp of comps) {
+                    yield new calIcalComponent(comp);
+                }
             }
         })();
         return this.getNextSubcomponent(kind)
     },
     getNextSubcomponent: function(kind) {
         if (this.componentIterator) {
             try {
                 return this.componentIterator.next();
@@ -349,22 +351,25 @@ calIcalComponent.prototype = {
         if (kind == "ANY") {
             kind = null;
         } else if (kind) {
             kind = kind.toLowerCase();
         }
         let innerObject = this.innerObject;
         this.propertyIterator = (function() {
             let props = innerObject.getAllProperties(kind);
-            for each (var prop in props) {
+            if (!props) {
+                return;
+            }
+            for (var prop of props) {
                 let hell = prop.getValues();
                 if (hell.length > 1) {
                     // Uh oh, multiple property values. Our code expects each as one
                     // property. I hate API incompatibility!
-                    for each (var devil in hell) {
+                    for (var devil of hell) {
                         var thisprop = new ICAL.Property(prop.toJSON(),
                                                          prop.parent);
                         thisprop.removeAllValues();
                         thisprop.setValue(devil);
                         yield new calIcalProperty(thisprop);
                     }
                 } else {
                     yield new calIcalProperty(prop);
@@ -418,17 +423,17 @@ calIcalComponent.prototype = {
                 }
             }
 
             this.mReferencedZones[tz.tzid] = tz;
         }
     },
 
     getReferencedTimezones: function(aCount) {
-        let vals = [ tz for each (tz in this.mReferencedZones) ];
+        let vals = Object.keys(this.mReferencedZones).map(tz => this.mReferencedZones[tz]);
         aCount.value = vals.length;
         return vals;
     },
 
     serializeToICSStream: function() {
         let unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
                                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
         unicodeConverter.charset = "UTF-8";
--- a/calendar/base/content/agenda-listbox.js
+++ b/calendar/base/content/agenda-listbox.js
@@ -63,17 +63,17 @@ function initAgendaListbox() {
  * Clean up the agenda listbox, used on window unload.
  */
 agendaListbox.uninit =
 function uninit() {
     if (this.calendar) {
         this.calendar.removeObserver(this.calendarObserver);
     }
 
-    for each (var period in this.periods) {
+    for (var period of this.periods) {
         if (period.listItem) {
             period.listItem.getCheckbox()
                   .removeEventListener("CheckboxStateChange",
                                        this.onCheckboxChange,
                                        true);
         }
     }
 };
@@ -510,18 +510,18 @@ function deleteItem(aItem, aMoveSelectio
 
 /**
  * Remove all items belonging to the specified calendar.
  *
  * @param aCalendar         The item to compare.
  */
 agendaListbox.deleteItemsFromCalendar =
 function deleteItemsFromCalendar(aCalendar) {
-    let childNodes = Array.slice(this.agendaListboxControl.childNodes);
-    for each (let childNode in childNodes) {
+    let childNodes = Array.from(this.agendaListboxControl.childNodes);
+    for (let childNode of childNodes) {
         if (childNode && childNode.occurrence
             && childNode.occurrence.calendar.id == aCalendar.id) {
             childNode.remove();
         }
     }
 }
 
 /**
--- a/calendar/base/content/calendar-base-view.xml
+++ b/calendar/base/content/calendar-base-view.xml
@@ -90,17 +90,17 @@
                     if (aItem.isCompleted && !this.calView.mShowCompleted) {
                         return;
                     }
                 }
 
                 let occs = aItem.getOccurrencesBetween(this.calView.startDate,
                                                        this.calView.queryEndDate,
                                                        {});
-                for each (let occ in occs) {
+                for (let occ of occs) {
                     this.calView.doAddItem(occ);
                 }
                 return;
             },
 
             onModifyItem: function onModifyItem(aNewItem, aOldItem) {
 
                 if (cal.isToDo(aNewItem) && cal.isToDo(aOldItem) &&
@@ -108,33 +108,33 @@
                     return;
                 }
                 let occs;
 
                 if (!cal.isToDo(aOldItem) || aOldItem.entryDate || aOldItem.dueDate) {
                     occs = aOldItem.getOccurrencesBetween(this.calView.startDate,
                                                           this.calView.queryEndDate,
                                                           {});
-                    for each (let occ in occs) {
+                    for (let occ of occs) {
                         this.calView.doDeleteItem(occ);
                     }
                 }
                 if (cal.isToDo(aNewItem)) {
                     if (!aNewItem.entryDate && !aNewItem.dueDate || !this.calView.mTasksInView) {
                         return;
                     }
                     if (aNewItem.isCompleted && !this.calView.mShowCompleted) {
                         return;
                     }
                 }
 
                 occs = aNewItem.getOccurrencesBetween(this.calView.startDate,
                                                       this.calView.queryEndDate,
                                                       {});
-                for each (let occ in occs) {
+                for (let occ of occs) {
                     this.calView.doAddItem(occ);
                 }
             },
 
             onDeleteItem: function onDeleteItem(aItem) {
 
                 if (cal.isToDo(aItem)) {
                     if (!this.calView.mTasksInView) {
@@ -146,17 +146,17 @@
                     if (aItem.isCompleted && !this.calView.mShowCompleted) {
                         return;
                     }
                 }
 
                 let occs = aItem.getOccurrencesBetween(this.calView.startDate,
                                                        this.calView.queryEndDate,
                                                        {});
-                for each (let occ in occs) {
+                for (let occ of occs) {
                     this.calView.doDeleteItem(occ);
                 }
             },
 
             onError: function onError(aCalendar, aErrNo, aMessage) { },
 
             onPropertyChanged: function(aCalendar, aName, aValue, aOldValue) {
                 switch (aName) {
@@ -188,17 +188,18 @@
 
             onRemoveAlarmsByItem: function onRemoveAlarmsByItem(aItem) {
                 // Stop the flashing for the item.
                 this.calView.flashAlarm(aItem, true);
             },
 
             onRemoveAlarmsByCalendar: function onRemoveAlarmsByCalendar(aCalendar) {
                 // Stop the flashing for all items of this calendar
-                for each (let item in this.calView.mFlashingEvents) {
+                for (let key in this.calView.mFlashingEvents) {
+                    let item = this.calView.mFlashingEvents[key];
                     if (item.calendar.id == aCalendar.id) {
                         this.calView.flashAlarm(item, true);
                     }
                 }
             },
 
             onAlarmsLoaded: function _onAlarmsLoaded(aCalendar) {},
 
@@ -592,17 +593,17 @@
             }
         ]]></body>
       </method>
 
       <method name="getLongWeekdayTotalPixels">
         <body><![CDATA[
           if (this.mLongWeekdayTotalPixels <= 0) {
               let maxDayWidth = 0;
-              for each (let label in this.labeldaybox.childNodes) {
+              for (let label of this.labeldaybox.childNodes) {
                   if (label.localName && label.localName == "calendar-day-label") {
                       label.shortWeekNames = false;
                       let curPixelLength = label.getLongWeekdayPixels();
                       maxDayWidth = Math.max(maxDayWidth, curPixelLength);
                   }
               }
               if (maxDayWidth > 0) {
                   this.mLongWeekdayTotalPixels = (maxDayWidth * this.labeldaybox.childNodes.length) + 10;
--- a/calendar/base/content/calendar-clipboard.js
+++ b/calendar/base/content/calendar-clipboard.js
@@ -139,17 +139,17 @@ function pasteFromClipboard() {
             let items = icsParser.getItems({});
             if (items.length == 0) {
                 return;
             }
 
             // If there are multiple items on the clipboard, the earliest
             // should be set to the selected day and the rest adjusted.
             let earliestDate = null;
-            for each (let item in items) {
+            for (let item of items) {
                 let date = null;
                 if (item.startDate) {
                     date = item.startDate.clone();
                 } else if (item.entryDate) {
                     date = item.entryDate.clone();
                 } else if (item.dueDate) {
                     date = item.dueDate.clone();
                 }
@@ -172,17 +172,17 @@ function pasteFromClipboard() {
                 earliestDate = earliestDate.getInTimezone(calendarDefaultTimezone());
                 earliestDate.isDate = true;
                 offset = firstDate.subtractDate(earliestDate);
                 let deltaDST = firstDate.timezoneOffset - earliestDate.timezoneOffset;
                 offset.inSeconds += deltaDST;
             }
 
             startBatchTransaction();
-            for each (let item in items) {
+            for (let item of items) {
                 let newItem = item.clone();
                 // Set new UID to allow multiple paste actions of the same
                 // clipboard content.
                 newItem.id = cal.getUUID();
                 if (offset) {
                     cal.shiftItem(newItem, offset);
                 }
                 doTransaction('add', newItem, destCal, null, null);
--- a/calendar/base/content/calendar-common-sets.js
+++ b/calendar/base/content/calendar-common-sets.js
@@ -449,17 +449,17 @@ var calendarController = {
         calendarController.item_selected = selectedItems && (selectedItems.length > 0);
 
         let selLength = (selectedItems === undefined ? 0 : selectedItems.length);
         let selected_events_readonly = 0;
         let selected_events_requires_network = 0;
         let selected_events_invitation = 0;
 
         if (selLength > 0) {
-            for each (var item in selectedItems) {
+            for (var item of selectedItems) {
                 if (item.calendar.readOnly) {
                     selected_events_readonly++;
                 }
                 if (item.calendar.getProperty("requiresNetwork") &&
                     !item.calendar.getProperty("cache.enabled") &&
                     !item.calendar.getProperty("cache.always")) {
                     selected_events_requires_network++;
                 }
@@ -542,17 +542,17 @@ var calendarController = {
 
     /**
      * Returns a boolean indicating if there are cached calendars and thus that don't require
      * network access.
      */
     get has_cached_calendars() {
         let calMgr = getCalendarManager();
         let calendars = calMgr.getCalendars({});
-        for each (let calendar in calendars) {
+        for (let calendar of calendars) {
             if (calendar.getProperty("cache.enabled") || calendar.getProperty("cache.always")) {
                 return true;
             }
         }
         return false;
     },
 
     /**
@@ -565,17 +565,17 @@ var calendarController = {
     /**
      * Returns a boolean indicating that all local calendars are readonly
      */
     get all_local_calendars_readonly() {
         // We might want to speed this part up by keeping track of this in the
         // calendar manager.
         var calendars = getCalendarManager().getCalendars({});
         var count = calendars.length;
-        for each (var calendar in calendars) {
+        for (var calendar of calendars) {
             if (!isCalendarWritable(calendar)) {
                 count--;
             }
         }
         return (count == 0);
     },
 
     /**
@@ -597,17 +597,17 @@ var calendarController = {
         return (selectedTasks.length > 0);
     },
 
 
     get todo_items_invitation() {
         let selectedTasks = getSelectedTasks();
         let selected_tasks_invitation = 0;
 
-        for each (let item in selectedTasks) {
+        for (let item of selectedTasks) {
             if (cal.isInvitation(item)) {
                 selected_tasks_invitation++;
             } else if (item.organizer) {
                 // If we are the organizer and there are attendees, then
                 // this is likely also an invitation.
                 let calOrgId = item.calendar.getProperty("organizerId");
                 if (item.organizer.id == calOrgId && item.getAttendees({}).length) {
                     selected_tasks_invitation++;
@@ -619,17 +619,17 @@ var calendarController = {
     },
 
     /**
      * Returns a boolean indicating that at least one task in the selection is
      * on a calendar that is writable.
      */
     get todo_items_writable() {
         var selectedTasks = getSelectedTasks();
-        for each (var task in selectedTasks) {
+        for (var task of selectedTasks) {
             if (isCalendarWritable(task.calendar)) {
                 return true;
             }
         }
         return false;
     }
 };
 
@@ -902,26 +902,26 @@ function calendarUpdateNewItemsCommand()
         taskCommands.forEach(goUpdateCommand);
 }
 
 function calendarUpdateDeleteCommand(selectedItems) {
     let oldValue = CalendarDeleteCommandEnabled;
     CalendarDeleteCommandEnabled = (selectedItems.length > 0);
 
     /* we must disable "delete" when at least one item cannot be deleted */
-    for each (let item in selectedItems) {
+    for (let item of selectedItems) {
         if (!userCanDeleteItemsFromCalendar(item.calendar)) {
             CalendarDeleteCommandEnabled = false;
             break;
         }
     }
 
     if (CalendarDeleteCommandEnabled != oldValue) {
         let commands = ["calendar_delete_event_command",
                         "calendar_delete_todo_command",
                         "calendar_delete_focused_item_command",
                         "button_delete",
                         "cmd_delete"];
-        for each (let command in commands) {
+        for (let command of commands) {
             goUpdateCommand(command);
         }
     }
 }
--- a/calendar/base/content/calendar-dnd-listener.js
+++ b/calendar/base/content/calendar-dnd-listener.js
@@ -56,23 +56,23 @@ var itemConversion = {
      *
      * @param aItem     The item to copy from.
      * @param aTarget   the item to copy to.
      */
     copyItemBase: function iC_copyItemBase(aItem, aTarget) {
         const copyProps = ["SUMMARY", "LOCATION", "DESCRIPTION",
                            "URL", "CLASS", "PRIORITY"];
 
-        for each (var prop in copyProps) {
+        for (var prop of copyProps) {
             aTarget.setProperty(prop, aItem.getProperty(prop));
         }
 
         // Attendees
         var attendees = aItem.getAttendees({});
-        for each (var attendee in attendees) {
+        for (var attendee of attendees) {
             aTarget.addAttendee(attendee.clone());
         }
 
         // Categories
         var categories = aItem.getCategories({});
         aTarget.setCategories(categories.length, categories);
 
         // Organizer
@@ -102,17 +102,17 @@ var itemConversion = {
 
         // Dates and alarms
         if (!aEvent.startDate.isDate && !aEvent.endDate.isDate) {
             // Dates
             item.entryDate = aEvent.startDate.clone();
             item.dueDate = aEvent.endDate.clone();
 
             // Alarms
-            for each (let alarm in aEvent.getAlarms({})) {
+            for (let alarm of aEvent.getAlarms({})) {
                 item.addAlarm(alarm.clone());
             }
             item.alarmLastAck = (aEvent.alarmLastAck ?
                                  aEvent.alarmLastAck.clone() :
                                  null);
         }
 
         // Map Status values
@@ -155,17 +155,17 @@ var itemConversion = {
         if (!item.endDate) {
             // Make the event be the default event length if no due date was
             // specified.
             item.endDate = item.startDate.clone();
             item.endDate.minute += Preferences.get("calendar.event.defaultlength", 60);
         }
 
         // Alarms
-        for each (let alarm in aTask.getAlarms({})) {
+        for (let alarm of aTask.getAlarms({})) {
             item.addAlarm(alarm.clone());
         }
         item.alarmLastAck = (aTask.alarmLastAck ?
                              aTask.alarmLastAck.clone() :
                              null);
 
         // Map Status values
         let statusMap = {
@@ -377,17 +377,17 @@ calViewDNDObserver.prototype = {
      * Gets called in case we're dropping an array of items
      * on one of the calendar views. In this case we just
      * try to add these items to the currently selected calendar.
      */
     onDropItems: function(aItems) {
         var destCal = getSelectedCalendar();
         startBatchTransaction();
         try {
-            for each (var item in aItems) {
+            for (var item of aItems) {
                 doTransaction('add', item, destCal, null, null);
             }
         }
         finally {
             endBatchTransaction();
         }
     }
 };
@@ -453,17 +453,17 @@ calCalendarButtonDNDObserver.prototype =
      * calCalendarButtonDNDObserver::onDropItems
      *
      * Gets called in case we're dropping an array of items
      * on the 'calendar mode'-button.
      *
      * @param aItems        An array of items to handle.
      */
     onDropItems: function(aItems) {
-        for each (var item in aItems) {
+        for (var item of aItems) {
             var newItem = item;
             if (isToDo(item)) {
                 newItem = itemConversion.eventFromTask(item);
             }
             createEventWithDialog(null, null, null, null, newItem);
         }
     },
 
@@ -502,17 +502,17 @@ calTaskButtonDNDObserver.prototype = {
      * calTaskButtonDNDObserver::onDropItems
      *
      * Gets called in case we're dropping an array of items
      * on the 'task mode'-button.
      *
      * @param aItems        An array of items to handle.
      */
     onDropItems: function(aItems) {
-        for each (var item in aItems) {
+        for (var item of aItems) {
             var newItem = item;
             if (isEvent(item)) {
                 newItem = itemConversion.taskFromEvent(item);
             }
             createTodoWithDialog(null, null, null, newItem);
         }
     },
 
--- a/calendar/base/content/calendar-invitations-manager.js
+++ b/calendar/base/content/calendar-invitations-manager.js
@@ -24,17 +24,18 @@ var gInvitationsRequestManager = {
             this.mRequestStatusList[calendar.id] = op;
         }
     },
 
     /**
      * Cancel all pending requests
      */
     cancelPendingRequests: function IRM_cancelPendingRequests() {
-        for each (var request in this.mRequestStatusList) {
+        for (var id in this.mRequestStatusList) {
+            let request = this.mRequestStatusList[id];
             if (request && request.isPending) {
                 request.cancel(null);
             }
         }
         this.mRequestStatusList = {};
     }
 };
 
@@ -143,17 +144,17 @@ InvitationsManager.prototype = {
                                           aOperationType,
                                           aId,
                                           aDetail) {
                 if (--this.mCount == 0) {
                     this.mInvitationsManager.mItemList.sort(
                         function (a, b) {
                             return a.startDate.compare(b.startDate);
                         });
-                    for each (var listener in listeners) {
+                    for (var listener of listeners) {
                         try {
                             if (this.mInvitationsManager.mItemList.length) {
                                 // Only call if there are actually items
                                 listener.onGetResult(null,
                                                      Components.results.NS_OK,
                                                      Components.interfaces.calIItemBase,
                                                      null,
                                                      this.mInvitationsManager.mItemList.length,
@@ -173,31 +174,31 @@ InvitationsManager.prototype = {
 
             onGetResult: function(aCalendar,
                                   aStatus,
                                   aItemType,
                                   aDetail,
                                   aCount,
                                   aItems) {
                 if (Components.isSuccessCode(aStatus)) {
-                    for each (var item in aItems) {
+                    for (var item of aItems) {
                         // we need to retrieve by occurrence to properly filter exceptions,
                         // should be fixed with bug 416975
                         item = item.parentItem;
                         var hid = item.hashId;
                         if (!this.mHandledItems[hid]) {
                             this.mHandledItems[hid] = true;
                             this.mInvitationsManager.addItem(item);
                         }
                     }
                 }
             }
         };
 
-        for each (var calendar in cals) {
+        for (var calendar of cals) {
             if (!isCalendarWritable(calendar) || calendar.getProperty("disabled")) {
                 opListener.onOperationComplete();
                 continue;
             }
 
             // temporary hack unless calCachedCalendar supports REQUEST_NEEDS_ACTION filter:
             calendar = calendar.getProperty("cache.uncachedCalendar");
             if (!calendar) {
@@ -344,17 +345,17 @@ InvitationsManager.prototype = {
      *
      * @param item      The item to add.
      */
     addItem: function IM_addItem(item) {
         var recInfo = item.recurrenceInfo;
         if (recInfo && !cal.isOpenInvitation(item)) {
             // scan exceptions:
             var ids = recInfo.getExceptionIds({});
-            for each (var id in ids) {
+            for (var id of ids) {
                 var ex = recInfo.getExceptionFor(id);
                 if (ex && this.validateItem(ex) && !this.hasItem(ex)) {
                     this.mItemList.push(ex);
                 }
             }
         } else if (this.validateItem(item) && !this.hasItem(item)) {
             this.mItemList.push(item);
         }
--- a/calendar/base/content/calendar-item-editing.js
+++ b/calendar/base/content/calendar-item-editing.js
@@ -667,17 +667,17 @@ function canRedo() {
 function updateUndoRedoMenu() {
     goUpdateCommand("cmd_undo");
     goUpdateCommand("cmd_redo");
 }
 
 function setContextPartstat(value, scope, items) {
     startBatchTransaction();
     try {
-        for each (let oldItem in items) {
+        for (let oldItem of items) {
             // Skip this item if its calendar is read only.
             if (oldItem.calendar.readOnly) {
                 continue;
             }
             if (scope == "all-occurrences") {
                 oldItem = oldItem.parentItem;
             }
             let attendee = null;
--- a/calendar/base/content/calendar-month-view.xml
+++ b/calendar/base/content/calendar-month-view.xml
@@ -548,30 +548,30 @@
       </method>
 
       <method name="setSelectedItems">
         <parameter name="aCount"/>
         <parameter name="aItems"/>
         <parameter name="aSuppressEvent"/>
         <body><![CDATA[
           if (this.mSelectedItems.length) {
-              for each (var item in this.mSelectedItems) {
+              for (var item of this.mSelectedItems) {
                   let oldboxes = this.findDayBoxesForItem(item);
-                  for each (let oldbox in oldboxes) {
+                  for (let oldbox of oldboxes) {
                       oldbox.unselectItem(item);
                   }
               }
           }
 
           this.mSelectedItems = aItems || [];
 
           if (this.mSelectedItems.length) {
-              for each (var item in this.mSelectedItems) {
+              for (var item of this.mSelectedItems) {
                   let newboxes = this.findDayBoxesForItem(item);
-                  for each (let newbox in newboxes) {
+                  for (let newbox of newboxes) {
                       newbox.selectItem(item);
                   }
               }
           }
 
           if (!aSuppressEvent) {
               this.fireEvent("itemselect", this.mSelectedItems);
           }
@@ -933,17 +933,20 @@
             headerkids[i].collapsed = dayOff && !this.mDisplayDaysOff;
           }
         ]]></body>
       </method>
 
       <method name="findDayBoxForDate">
         <parameter name="aDate"/>
         <body><![CDATA[
-          for each (let box in this.mDateBoxes) {
+          if (!this.mDateBoxes) {
+            return null;
+          }
+          for (let box of this.mDateBoxes) {
             if (box.mDate.compare(aDate) == 0)
               return box;
           }
           return null;
         ]]></body>
       </method>
 
       <method name="findDayBoxesForItem">
@@ -1009,17 +1012,17 @@
       <method name="doAddItem">
         <parameter name="aItem"/>
         <body><![CDATA[
           let boxes = this.findDayBoxesForItem(aItem);
 
           if (!boxes.length)
             return;
 
-          for each (let box in boxes) {
+          for (let box of boxes) {
             box.addItem(aItem);
           }
         ]]></body>
       </method>
 
       <method name="doDeleteItem">
         <parameter name="aItem"/>
         <body><![CDATA[
@@ -1029,33 +1032,37 @@
             return;
 
           function isNotItem(a) {
               return (a.hashId != aItem.hashId);
           }
           var oldLength = this.mSelectedItems.length;
           this.mSelectedItems = this.mSelectedItems.filter(isNotItem);
 
-          for each (let box in boxes) {
+          for (let box of boxes) {
             box.deleteItem(aItem);
           }
 
           // If a deleted event was selected, we need to announce that the
           // selection changed.
           if (oldLength != this.mSelectedItems.length) {
               this.fireEvent("itemselect", this.mSelectedItems);
           }
         ]]></body>
       </method>
 
       <method name="deleteItemsFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
-          for each (let box in this.mDateBoxes) {
-            for each (let node in box.mItemHash) {
+          if (!this.mDateBoxes) {
+            return;
+          }
+          for (let box of this.mDateBoxes) {
+            for (let id in box.mItemHash) {
+              let node = box.mItemHash[id];
               let item = node.item;
               if (item.calendar.id == aCalendar.id) {
                 box.deleteItem(item);
               }
             }
           }
         ]]></body>
       </method>
@@ -1070,18 +1077,19 @@
           if (!aStop && (!showIndicator || totaltime < 1)) {
             // No need to animate if the indicator should not be shown.
             return;
           }
 
           // Make sure the flashing attribute is set or reset on all visible
           // boxes.
           let boxes = this.findDayBoxesForItem(aAlarmItem);
-          for each (var box in boxes) {
-            for each (var itemData in box.mItemHash) {
+          for (var box of boxes) {
+            for (var id in box.mItemHash) {
+              let itemData = box.mItemHash[id];
               if (itemData.item.hasSameIds(aAlarmItem)) {
                 if (aStop) {
                   itemData.removeAttribute("flashing");
                 } else {
                   itemData.setAttribute("flashing", "true");
                 }
               }
             }
--- a/calendar/base/content/calendar-multiday-view.xml
+++ b/calendar/base/content/calendar-multiday-view.xml
@@ -438,17 +438,17 @@
               this.mSelectedChunks.splice(index, 1);
           }
         ]]></body>
       </method>
 
       <method name="findChunkForOccurrence">
         <parameter name="aOccurrence"/>
         <body><![CDATA[
-          for each (var chunk in this.mEventBoxes) {
+          for (var chunk of this.mEventBoxes) {
               if (chunk.occurrence.hashId == aOccurrence.hashId) {
                   return chunk;
               }
           }
 
           return null;
         ]]></body>
       </method>
@@ -504,17 +504,17 @@
            } else {
                return false;
            }
         ]]></body>
       </method>
 
       <method name="recalculateStartEndMinutes">
         <body><![CDATA[
-          for each (var chunk in this.mEventInfos) {
+          for (var chunk of this.mEventInfos) {
               var mins = this.getStartEndMinutesForOccurrence(chunk.event);
               chunk.startMinute = mins.start;
               chunk.endMinute = mins.end;
           }
 
           this.relayout();
         ]]></body>
       </method>
@@ -615,17 +615,17 @@
       <method name="clear">
         <body><![CDATA[
           while (this.bgbox && this.bgbox.hasChildNodes()) {
               this.bgbox.lastChild.remove();
           }
           while (this.topbox && this.topbox.hasChildNodes()) {
               this.topbox.lastChild.remove();
           }
-          for each (let handler in this.mHandlersToRemove) {
+          for (let handler of this.mHandlersToRemove) {
               this.calendarView.viewBroadcaster.removeEventListener(this.calendarView.getAttribute("type") + "viewresized", handler, true);
           }
           this.mHandlersToRemove = [];
           this.mSelectedChunks = [];
         ]]></body>
       </method>
 
       <method name="relayout">
@@ -711,17 +711,17 @@
           let stack = createXULElement("stack");
           stack.setAttribute("flex", "1");
           this.topbox.appendChild(stack);
 
           let boxToEdit;
           let columnCount = 1;
           let spanTotal = 0;
 
-          for each (let layer in this.mEventMap) {
+          for (let layer of this.mEventMap) {
 
               // The event-map (this.mEventMap) contains an array of layers.
               // For each layer we create a box below the stack just created above.
               // So each different layer lives in a box that's contained in the stack.
               let xulColumn = createXULElement("box");
               xulColumn.setAttribute("orient", otherorient);
               xulColumn.setAttribute("flex", "1");
               xulColumn.setAttribute("style", "min-width: 1px; min-height: 1px;");
@@ -732,32 +732,32 @@
               // column count determined by layer with no special span columns
               if (layer.every(e => !e.specialSpan)) {
                   columnCount = layer.length;
               }
               spanTotal = 0;
 
               // Each layer contains a list of the columns that
               // need to be created for a span.
-              for each (let column in layer) {
+              for (let column of layer) {
                   let innerColumn = createXULElement("box");
                   innerColumn.setAttribute("orient", orient);
 
                   let colFlex = column.specialSpan ? (columnCount * column.specialSpan) : 1;
                   innerColumn.setAttribute("flex", colFlex);
                   spanTotal += colFlex;
 
                   innerColumn.style.minWidth = "1px";
                   innerColumn.style.minHeight = "1px";
                   innerColumn.style.width = colFlex + "px";
                   innerColumn.style.height = colFlex + "px";
 
                   xulColumn.appendChild(innerColumn);
                   let curTime = 0;
-                  for each (let chunk in column) {
+                  for (let chunk of column) {
                       var duration = chunk.duration;
                       if (!duration) {
                           continue;
                       }
 
                       if (chunk.event) {
                           let chunkBox = createXULElement("calendar-event-box");
                           let durMinutes = duration.inSeconds / 60;
@@ -1106,22 +1106,22 @@
           //   not columns).  What's more, in the 'specialSpan' case, the
           //   columns won't actually have the same size, but will only all
           //   be multiples of a common size.  See the note in the relayout
           //   function for more info on this (fairly rare) case.
           var layers = [];
 
           // When we start a new blob, move to a new set of layers
           var layerOffset = 0;
-          for each (var glob in aBlobs) {
+          for (var glob of aBlobs) {
 
               var layerArray = [];
               var layerCounter = 1;
 
-              for each (var data in glob.blob) {
+              for (var data of glob.blob) {
 
                   // from the item at hand we need to figure out on which
                   // layer and on which column it should go.
                   var layerIndex;
                   var specialSpan = null;
 
                   // each blob receives its own layer, that's the first part of the story. within
                   // a given blob we need to distribute the items on different layers depending on
@@ -2106,17 +2106,17 @@
         <setter><![CDATA[
           this.mDate = val;
           return val;
         ]]></setter>
       </property>
       <method name="findBoxForItem">
         <parameter name="aItem"/>
         <body><![CDATA[
-          for each (var item in this.mItemBoxes) {
+          for (var item of this.mItemBoxes) {
               if (aItem && item.occurrence.hasSameIds(aItem)) {
                   // We can return directly, since there will only be one box per
                   // item in the header.
                   return item;
               }
           }
           return null;
         ]]></body>
@@ -2169,28 +2169,28 @@
          newItem = cal.setItemToAllDay(newItem, true);
          return newItem;
         ]]></body>
       </method>
 
       <method name="selectOccurrence">
         <parameter name="aItem"/>
         <body><![CDATA[
-          for each (let itemBox in this.mItemBoxes) {
+          for (let itemBox of this.mItemBoxes) {
             if (aItem && (itemBox.occurrence.hashId == aItem.hashId)) {
               itemBox.selected = true;
             }
 
           }
         ]]></body>
       </method>
       <method name="unselectOccurrence">
         <parameter name="aItem"/>
         <body><![CDATA[
-          for each (let itemBox in this.mItemBoxes) {
+          for (let itemBox of this.mItemBoxes) {
             if (aItem && (itemBox.occurrence.hashId == aItem.hashId)) {
               itemBox.selected = false;
             }
           }
         ]]></body>
       </method>
 
     </implementation>
@@ -2752,17 +2752,17 @@
             } else {
               aBox.setAttribute("flashing", "true");
             }
           }
 
           // Make sure the flashing attribute is set or reset on all visible
           // boxes.
           var columns = this.findColumnsForItem(aAlarmItem);
-          for each (var col in columns) {
+          for (var col of columns) {
             var box = col.column.findChunkForOccurrence(aAlarmItem);
             if (box && box.eventbox) {
               setFlashingAttribute(box.eventbox);
             }
             box = col.header.findBoxForItem(aAlarmItem);
             if (box) {
               setFlashingAttribute(box);
             }
@@ -2808,17 +2808,17 @@
           var targetDate = aDate.getInTimezone(this.mTimezone);
           targetDate.isDate = true;
 
           if (this.mStartDate && this.mEndDate) {
               if (this.mStartDate.compare(targetDate) <= 0 &&
                   this.mEndDate.compare(targetDate) >= 0)
                   return;
           } else if (this.mDateList) {
-              for each (var d in this.mDateList) {
+              for (var d of this.mDateList) {
                   // if date is already visible, nothing to do
                   if (d.compare(targetDate) == 0)
                       return;
               }
           }
 
           // if we're only showing one date, then continue
           // to only show one date; otherwise, show the week.
@@ -2894,17 +2894,17 @@
            var dates = new Array();
            if (this.mStartDate && this.mEndDate) {
                var d = this.mStartDate.clone();
                while (d.compare(this.mEndDate) <= 0) {
                    dates.push(d.clone());
                    d.day += 1;
                }
            } else if (this.mDateList) {
-               for each (var d in this.mDateList)
+               for (var d of this.mDateList)
                    dates.push(d.clone());
            }
 
            aCount.value = dates.length;
            return dates;
         ]]></body>
       </method>
 
@@ -2968,33 +2968,35 @@
           return this.mSelectedItems;
         ]]></body>
       </method>
       <method name="setSelectedItems">
         <parameter name="aCount"/>
         <parameter name="aItems"/>
         <parameter name="aSuppressEvent"/>
         <body><![CDATA[
-          for each (var item in this.mSelectedItems) {
-              for each (var occ in this.getItemOccurrencesInView(item)) {
-                  var cols = this.findColumnsForItem(occ);
-                  for each (let col in cols) {
-                      col.header.unselectOccurrence(occ);
-                      col.column.unselectOccurrence(occ);
+          if (this.mSelectedItems) {
+              for (var item of this.mSelectedItems) {
+                  for (var occ of this.getItemOccurrencesInView(item)) {
+                      var cols = this.findColumnsForItem(occ);
+                      for (let col of cols) {
+                          col.header.unselectOccurrence(occ);
+                          col.column.unselectOccurrence(occ);
+                      }
                   }
               }
           }
           this.mSelectedItems = aItems || [];
 
-          for each (var item in this.mSelectedItems) {
-              for each (var occ in this.getItemOccurrencesInView(item)) {
+          for (var item of this.mSelectedItems) {
+              for (var occ of this.getItemOccurrencesInView(item)) {
                   let cols = this.findColumnsForItem(occ);
                   if (cols.length > 0) {
                       let start = item.startDate || item.entryDate || item.dueDate;
-                      for each (let col in cols) {
+                      for (let col of cols) {
                           if (start.isDate) {
                               col.header.selectOccurrence(occ);
                           } else {
                               col.column.selectOccurrence(occ);
                           }
                       }
                   }
               }
@@ -3021,29 +3023,29 @@
       </method>
 
       <method name="centerSelectedItems">
         <body><![CDATA[
           var displayTZ = calendarDefaultTimezone();
           var lowMinute = 24 * 60;
           var highMinute = 0;
 
-          for each (var item in this.mSelectedItems) {
+          for (var item of this.mSelectedItems) {
               var startDateProperty = calGetStartDateProp(item);
               var endDateProperty = calGetEndDateProp(item);
 
               var occs = [];
               if (item.recurrenceInfo) {
                   // if selected a parent item, show occurrence(s) in view range
                   occs = item.getOccurrencesBetween(this.startDate, this.queryEndDate, {}, 0);
               } else {
                   occs = [item];
               }
 
-              for each (var occ in occs) {
+              for (var occ of occs) {
                   var occStart = occ[startDateProperty];
                   var occEnd = occ[endDateProperty];
                   // must have at least one of start or end
                   if (!occStart && !occEnd) {
                       continue; // task with no dates
                   }
 
                   // if just has single datetime, treat as zero duration item
@@ -3112,17 +3114,20 @@
           return this.mPixPerMin
         ]]></getter>
         <setter><![CDATA[
           this.mPixPerMin = val;
 
           let timebar = document.getAnonymousElementByAttribute(this, "anonid", "timebar");
           timebar.pixelsPerMinute = val;
 
-          for each (let col in this.mDateColumns) {
+          if (!this.mDateColumns) {
+              return;
+          }
+          for (let col of this.mDateColumns) {
               col.column.pixelsPerMinute = val;
           }
           return val;
         ]]></setter>
       </property>
 
       <!-- private -->
 
@@ -3199,20 +3204,20 @@
           } else {
               this.pixelsPerMinute = 0.6;
           }
 
           var normalelems = ['mainbox', 'timebar'];
           var otherelems = ['labelbox', 'labeldaybox', 'headertimespacer',
                             'headerbox', 'headerdaybox', 'scrollbox', 'daybox'];
 
-          for each (var id in normalelems) {
+          for (var id of normalelems) {
               document.getAnonymousElementByAttribute(this, "anonid", id).setAttribute("orient", orient);
           }
-          for each (var id in otherelems) {
+          for (var id of otherelems) {
               document.getAnonymousElementByAttribute(this, "anonid", id).setAttribute("orient", otherorient);
           }
 
           var scrollbox = document.getAnonymousElementByAttribute(
                          this, "anonid", "scrollbox");
           var mainbox = document.getAnonymousElementByAttribute(
                         this, "anonid", "mainbox");
 
@@ -3224,17 +3229,17 @@
           } else {
               scrollbox.setAttribute(
                   "style", "overflow-x: auto; overflow-y: hidden;");
               mainbox.setAttribute(
                   "style", "overflow-x: hidden; overflow-y: auto;");
           }
 
           var boxes = ["daybox", "headerdaybox"];
-          for each (var boxname in boxes) {
+          for (var boxname of boxes) {
               var box = document.getAnonymousElementByAttribute(this, "anonid", boxname);
               setAttributeToChildren(box, "orient", orient);
           }
           var box = document.getAnonymousElementByAttribute(this, "anonid", "labeldaybox");
           setAttributeToChildren(this.labeldaybox, "orient", otherorient);
 
           // Refresh
           this.refresh();
@@ -3303,17 +3308,17 @@
           // get today's date
           var today = this.today();
           var counter = 0;
           var dayboxkids = daybox.childNodes;
           var headerboxkids = headerdaybox.childNodes;
           let labelboxkids = this.labeldaybox.childNodes;
           let updateTimeIndicator = false;
 
-          for each (var d in computedDateList) {
+          for (var d of computedDateList) {
               var dayEventsBox;
               if (counter < dayboxkids.length) {
                   dayEventsBox = dayboxkids[counter];
                   dayEventsBox.removeAttribute("relation");
                   dayEventsBox.mEventInfos = new Array();
               } else {
                   dayEventsBox = createXULElement("calendar-event-column");
                   dayEventsBox.setAttribute("flex", "1");
@@ -3409,18 +3414,20 @@
           removeExtraKids(this.labeldaybox);
 
           if (updateTimeIndicator) {
               this.updateTimeIndicatorPosition();
           }
 
           // fix pixels-per-minute
           this.onResize();
-          for each (let col in this.mDateColumns) {
-               col.column.endLayoutBatchChange();
+          if (this.mDateColumns) {
+              for (let col of this.mDateColumns) {
+                  col.column.endLayoutBatchChange();
+              }
           }
 
           // Adjust scrollbar spacers
           this.adjustScrollBarSpacers();
 
           // Store the start and end of current view. Next time when
           // setDateRange is called, it will use mViewStart and mViewEnd to
           // check if view range has been changed.
@@ -3441,17 +3448,20 @@
 
           this.mToggleStatus = toggleStatus;
         ]]></body>
       </method>
 
       <method name="findColumnForDate">
         <parameter name="aDate"/>
         <body><![CDATA[
-          for each (var col in this.mDateColumns) {
+          if (!this.mDateColumns) {
+              return;
+          }
+          for (var col of this.mDateColumns) {
               if (col.date.compare(aDate) == 0)
                   return col;
           }
           return null;
         ]]></body>
       </method>
 
       <method name="findDayBoxForDate">
@@ -3480,17 +3490,17 @@
       <method name="findColumnsForOccurrences">
         <parameter name="aOccurrences"/>
         <body><![CDATA[
           if (!this.mDateColumns || !this.mDateColumns.length) {
             return [];
           }
 
           var occMap = {};
-          for each (var occ in aOccurrences) {
+          for (var occ of aOccurrences) {
               var startDate = occ[calGetStartDateProp(occ)]
                               .getInTimezone(this.mStartDate.timezone);
               var endDate = occ[calGetEndDateProp(occ)]
                               .getInTimezone(this.mEndDate.timezone) || startDate;
               if (startDate.compare(this.mStartDate) >= 0 &&
                   endDate.compare(this.mEndDate) <= 0) {
                   for (var i = startDate.day; i <= endDate.day; i++) {
                       occMap[i] = true;
@@ -3556,17 +3566,20 @@
       <!-- for the given client-coord-system point, return
          - the calendar-event-column that contains it.  If
          - no column contains it, return null.
         -->
       <method name="findColumnForClientPoint">
         <parameter name="aClientX"/>
         <parameter name="aClientY"/>
         <body><![CDATA[
-          for each (var col in this.mDateColumns) {
+          if (!this.mDateColumns) {
+              return null;
+          }
+          for (var col of this.mDateColumns) {
               let bo = document.getAnonymousElementByAttribute(col.column, "anonid", "boxstack").boxObject;
               if ((aClientX >= bo.screenX) && (aClientX <= (bo.screenX + bo.width)) &&
                   (aClientY >= bo.screenY) && (aClientY <= (bo.screenY + bo.height)))
               {
                   return col.column;
               }
           }
           return null;
@@ -3589,17 +3602,17 @@
 
       <method name="doAddItem">
         <parameter name="aEvent"/>
         <body><![CDATA[
           var cols = this.findColumnsForItem(aEvent);
           if (!cols.length)
               return;
 
-          for each (let col in cols) {
+          for (let col of cols) {
               let column = col.column;
               let header = col.header;
 
               let estart = aEvent.startDate || aEvent.entryDate || aEvent.dueDate;
               if (estart.isDate) {
                   header.addEvent(aEvent);
               } else {
                   column.addEvent(aEvent);
@@ -3617,17 +3630,17 @@
           if (!cols.length)
               return;
 
           var oldLength = this.mSelectedItems.length;
           this.mSelectedItems = this.mSelectedItems.filter((item) => {
               return item.hashId != aEvent.hashId;
           });
 
-          for each (let col in cols) {
+          for (let col of cols) {
               let column = col.column;
               let header = col.header;
 
               let estart = aEvent.startDate || aEvent.entryDate || aEvent.dueDate;
               if (estart.isDate) {
                   header.deleteEvent(aEvent);
               } else {
                   column.deleteEvent(aEvent);
@@ -3642,22 +3655,25 @@
 
           this.adjustScrollbarSpacersForAlldayEvents(aEvent);
         ]]></body>
       </method>
 
       <method name="deleteItemsFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
-          for each (let col in this.mDateColumns) {
+          if (!this.mDateColumns) {
+              return;
+          }
+          for (let col of this.mDateColumns) {
               // get all-day events in column header and events within the column
-              let colEvents = [ box.occurrence for each (box in col.header.mItemBoxes) ]
-                              .concat([ info.event for each (info in col.column.mEventInfos) ]);
-
-              for each (let event in colEvents) {
+              let colEvents = col.header.mItemBoxes.map(box => box.occurrence)
+                .concat(col.column.mEventInfos.map(info => info.event));
+
+              for (let event of colEvents) {
                   if (event.calendar.id == aCalendar.id) {
                       this.doDeleteItem(event);
                   }
               }
           }
         ]]></body>
       </method>
 
--- a/calendar/base/content/calendar-task-tree.xml
+++ b/calendar/base/content/calendar-task-tree.xml
@@ -403,40 +403,40 @@
               idiff.load(aOldItems);
               idiff.difference(aNewItems);
               idiff.complete();
               let delItems = idiff.deletedItems;
               let addItems = idiff.addedItems;
               let modItems = idiff.modifiedItems;
 
               // find the indexes of the old items that need to be removed
-              for each (let item in delItems.mArray) {
+              for (let item of delItems.mArray) {
                   if (item.hashId in this.binding.mHash2Index) {
                       // the old item needs to be removed
                       remIndexes.push(this.binding.mHash2Index[item.hashId]);
                       delete this.binding.mHash2Index[item.hashId];
                   }
               }
 
               // modified items need to be updated
-              for each (let item in modItems.mArray) {
+              for (let item of modItems.mArray) {
                   if (item.hashId in this.binding.mHash2Index) {
                       // make sure we're using the new version of a modified item
                       this.binding.mTaskArray[this.binding.mHash2Index[item.hashId]] = item;
                   }
               }
 
               // remove the old items working backward from the end so the indexes stay valid
               remIndexes.sort(function(a, b) {return b - a;}).forEach(function(index) {
                   this.binding.mTaskArray.splice(index, 1);
                   this.treebox.rowCountChanged(index, -1);
               }, this);
 
               // add the new items
-              for each (let item in addItems.mArray) {
+              for (let item of addItems.mArray) {
                   if (!(item.hashId in this.binding.mHash2Index)) {
                       let index = this.binding.mTaskArray.length;
                       this.binding.mTaskArray.push(item);
                       this.binding.mHash2Index[item.hashId] = index;
                       this.treebox.rowCountChanged(index, 1);
                       firstHash = firstHash || item.hashId;
                   }
               }
@@ -570,17 +570,17 @@
                       this.sortDirection = "descending";
                   }
               }
               this.selectedColumn = aCol.element;
               let selectedItems = this.binding.selectedTasks;
               this.binding.sortItems();
               if (selectedItems != undefined) {
                   this.tree.view.selection.clearSelection();
-                  for each (let item in selectedItems){
+                  for (let item of selectedItems){
                       let index = this.binding.mHash2Index[item.hashId];
                       this.tree.view.selection.toggleSelect(index);
                   }
               }
           },
 
           // The text for a given cell. If a column consists only of an
           // image, then the empty string is returned.
@@ -976,17 +976,17 @@
         ]]></body>
       </method>
 
       <!-- Called by event observers to update the display -->
       <method name="refresh">
         <parameter name="aFilter"/>
         <body><![CDATA[
           let cals = getCompositeCalendar().getCalendars({}) || [];
-          for each (let calendar in cals) {
+          for (let calendar of cals) {
               if (!calendar.getProperty("disabled")) {
                   this.refreshFromCalendar(calendar, aFilter);
               }
           }
         ]]></body>
       </method>
 
       <method name="onCalendarAdded">
--- a/calendar/base/content/calendar-task-view.js
+++ b/calendar/base/content/calendar-task-view.js
@@ -125,17 +125,17 @@ var taskDetailsView = {
             var description = item.hasProperty("DESCRIPTION") ? item.getProperty("DESCRIPTION") : null;
             textbox.value = description;
             textbox.inputField.readOnly = true;
             let attachmentRows = document.getElementById("calendar-task-details-attachment-rows");
             removeChildren(attachmentRows);
             let attachments = item.getAttachments({});
             if (displayElement("calendar-task-details-attachment-row", attachments.length > 0)) {
                 displayElement("calendar-task-details-attachment-rows", true);
-                for each (let attachment in attachments) {
+                for (let attachment of attachments) {
                     let url = attachment.calIAttachment.uri.spec
                     let urlLabel = createXULElement("label");
                     urlLabel.setAttribute("value", url);
                     urlLabel.setAttribute("tooltiptext", url);
                     urlLabel.setAttribute("class", "text-link");
                     urlLabel.setAttribute("crop", "end");
                     urlLabel.setAttribute("onclick",
                                           "if (event.button != 2) launchBrowser(this.value);");
@@ -152,21 +152,21 @@ var taskDetailsView = {
         panel.loadItem(item);
     },
 
     saveCategories: function saveCategories(event) {
         let panel = event.target;
         let item = document.getElementById("calendar-task-tree").currentTask;
         let categoriesMap = {};
 
-        for each (let cat in item.getCategories({})) {
+        for (let cat of item.getCategories({})) {
             categoriesMap[cat] = true;
         }
 
-        for each (let cat in panel.categories) {
+        for (let cat of panel.categories) {
             if (cat in categoriesMap) {
                 delete categoriesMap[cat];
             } else {
                 categoriesMap[cat] = false;
             }
         }
 
         if (categoriesMap.toSource() != "({})") {
--- a/calendar/base/content/calendar-ui-utils.js
+++ b/calendar/base/content/calendar-ui-utils.js
@@ -530,17 +530,17 @@ function createXULElement(el) {
  * @param aXULElement   The xul element to be inspected.
  * @param aStyleProps   The css style properties for which values are to be retrieved
  *                        e.g. 'font-size', 'min-width" etc.
  * @return              An integer value denoting the optimal minimum width
  */
 function getSummarizedStyleValues(aXULElement, aStyleProps) {
     var retValue = 0;
     var cssStyleDeclares = document.defaultView.getComputedStyle(aXULElement, null);
-    for each (var prop in aStyleProps) {
+    for (var prop of aStyleProps) {
         retValue += parseInt(cssStyleDeclares.getPropertyValue(prop), 10);
     }
     return retValue;
 }
 
 /**
  * Calculates the optimal minimum width based on the set css style-rules
  * by considering the css rules for the min-width, padding, border, margin
--- a/calendar/base/content/calendar-unifinder.js
+++ b/calendar/base/content/calendar-unifinder.js
@@ -409,17 +409,17 @@ var unifinderTreeView = {
     },
 
     /**
      * Sets the currently selected column in the unifinder (used for sorting).
      */
     set selectedColumn(aCol) {
         let tree = document.getElementById("unifinder-search-results-tree");
         let treecols = tree.getElementsByTagName("treecol");
-        for each (let col in Array.slice(treecols)) {
+        for (let col of treecols) {
             if (col.getAttribute("sortActive")) {
                   col.removeAttribute("sortActive");
                   col.removeAttribute("sortDirection");
             }
             if (aCol.getAttribute("itemproperty") == col.getAttribute("itemproperty")) {
                 col.setAttribute("sortActive", "true");
                 col.setAttribute("sortDirection", this.sortDirection);
             }
@@ -459,17 +459,17 @@ var unifinderTreeView = {
      */
     removeItems: function uTV_removeItems(aItemArray) {
         let indexesToRemove = [];
         // Removing items is a bit tricky. Our getItemRow function takes the
         // index from a cached map, so removing an item from the array will
         // remove the wrong indexes. We don't want to just invalidate the map,
         // since this will cause O(n^2) behavior. Instead, we keep a sorted
         // array of the indexes to remove:
-        for each (let item in aItemArray) {
+        for (let item of aItemArray) {
             let row = this.getItemRow(item);
             if (row > -1) {
                 if (!indexesToRemove.length || row <= indexesToRemove[0]) {
                     indexesToRemove.unshift(row);
                 } else {
                     indexesToRemove.push(row);
                 }
             }
@@ -628,17 +628,17 @@ var unifinderTreeView = {
             // If only one item is selected, scroll to it
             let rowToScrollTo = this.getItemRow(aItemArray[0]);
             if (rowToScrollTo > -1) {
                this.tree.ensureRowIsVisible(rowToScrollTo);
                this.tree.view.selection.select(rowToScrollTo);
             }
         } else if (aItemArray && aItemArray.length > 1) {
             // If there is more than one item, just select them all.
-            for each (let item in aItemArray) {
+            for (let item of aItemArray) {
                 let row = this.getItemRow(item);
                 this.tree.view.selection.rangedSelect(row, row, true);
             }
         }
 
         // This needs to be in a setTimeout
         setTimeout(function() { unifinderTreeView.resetAllowSelection(); }, 1);
     },
@@ -921,18 +921,17 @@ function addItemsFromCalendar(aCalendar,
                        0,
                        unifinderTreeView.mFilter.startDate,
                        unifinderTreeView.mFilter.endDate,
                        refreshListener);
 }
 
 function deleteItemsFromCalendar(aCalendar) {
     let filter = unifinderTreeView.mFilter;
-    let items = [ item for each (item in unifinderTreeView.eventArray)
-                    if (item.calendar.id == aCalendar.id) ];
+    let items = unifinderTreeView.eventArray.filter(item => item.calendar.id == aCalendar.id);
 
     unifinderTreeView.removeItems(items.filter(filter.isItemInFilters, filter));
 }
 
 /**
  * Focuses the unifinder search field
  */
 function focusSearch() {
--- a/calendar/base/content/calendar-views.js
+++ b/calendar/base/content/calendar-views.js
@@ -111,17 +111,17 @@ var calendarViewController = {
         // Make sure we are modifying a copy of aOccurrences, otherwise we will
         // run into race conditions when the view's doDeleteItem removes the
         // array elements while we are iterating through them. While we are at
         // it, filter out any items that have readonly calendars, so that
         // checking for one total item below also works out if all but one item
         // are readonly.
         var occurrences = aOccurrences.filter(function(item) { return isCalendarWritable(item.calendar); });
 
-        for each (var itemToDelete in occurrences) {
+        for (var itemToDelete of occurrences) {
             if (aUseParentItems) {
                 // Usually happens when ctrl-click is used. In that case we
                 // don't need to ask the user if he wants to delete an
                 // occurrence or not.
                 itemToDelete = itemToDelete.parentItem;
             } else if (!aDoNotConfirm && occurrences.length == 1) {
                 // Only give the user the selection if only one occurrence is
                 // selected. Otherwise he will get a dialog for each occurrence
@@ -145,17 +145,18 @@ var calendarViewController = {
                 // parent item gets modified more than once.
             } else {
                 doTransaction('delete', itemToDelete, itemToDelete.calendar, null, null);
             }
         }
 
         // Now handle recurring events. This makes sure that all occurrences
         // that have been passed are deleted.
-        for each (var ritem in recurringItems) {
+        for (var hashVal in recurringItems) {
+            let ritem = recurringItems[hashVal];
             doTransaction('modify',
                           ritem.newItem,
                           ritem.newItem.calendar,
                           ritem.oldItem,
                           null);
         }
         endBatchTransaction();
     }
@@ -342,17 +343,17 @@ function scheduleMidnightUpdate(aRefresh
 /**
  * Retuns a cached copy of the view stylesheet.
  *
  * @return      The view stylesheet object.
  */
 function getViewStyleSheet() {
   if (!getViewStyleSheet.sheet) {
       const cssUri = "chrome://calendar/content/calendar-view-bindings.css";
-      for each (let sheet in document.styleSheets) {
+      for (let sheet of document.styleSheets) {
           if (sheet.href == cssUri) {
               getViewStyleSheet.sheet = sheet;
               break;
           }
       }
   }
   return getViewStyleSheet.sheet;
 }
@@ -510,17 +511,17 @@ function getMinimonth() {
  * Update the view orientation based on the checked state of the command
  */
 function toggleOrientation() {
     var cmd = document.getElementById("calendar_toggle_orientation_command");
     var newValue = (cmd.getAttribute("checked") == "true" ? "false" : "true");
     cmd.setAttribute("checked", newValue);
 
     var deck = getViewDeck();
-    for each (var view in deck.childNodes) {
+    for (var view of deck.childNodes) {
         view.rotated = (newValue == "true");
     }
 
     // orientation refreshes automatically
 }
 
 /**
  * Toggle the workdays only checkbox and refresh the current view
@@ -529,51 +530,51 @@ function toggleOrientation() {
  * should happen automatically.
  */
 function toggleWorkdaysOnly() {
     var cmd = document.getElementById("calendar_toggle_workdays_only_command");
     var newValue = (cmd.getAttribute("checked") == "true" ? "false" : "true");
     cmd.setAttribute("checked", newValue);
 
     var deck = getViewDeck();
-    for each (var view in deck.childNodes) {
+    for (var view of deck.childNodes) {
         view.workdaysOnly = (newValue == "true");
     }
 
     // Refresh the current view
     currentView().goToDay();
 }
 
 /**
  * Toggle the tasks in view checkbox and refresh the current view
  */
 function toggleTasksInView() {
     var cmd = document.getElementById("calendar_toggle_tasks_in_view_command");
     var newValue = (cmd.getAttribute("checked") == "true" ? "false" : "true");
     cmd.setAttribute("checked", newValue);
 
     var deck = getViewDeck();
-    for each (var view in deck.childNodes) {
+    for (var view of deck.childNodes) {
         view.tasksInView = (newValue == "true");
     }
 
     // Refresh the current view
     currentView().goToDay();
 }
 
 /**
  * Toggle the show completed in view checkbox and refresh the current view
  */
 function toggleShowCompletedInView() {
     var cmd = document.getElementById("calendar_toggle_show_completed_in_view_command");
     var newValue = (cmd.getAttribute("checked") == "true" ? "false" : "true");
     cmd.setAttribute("checked", newValue);
 
     var deck = getViewDeck();
-    for each (var view in deck.childNodes) {
+    for (var view of deck.childNodes) {
         view.showCompleted = (newValue == "true");
     }
 
     // Refresh the current view
     currentView().goToDay();
 }
 
 /**
@@ -635,17 +636,17 @@ function selectAllEvents() {
         QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function selectAll_ooc(aCalendar, aStatus,
                                                     aOperationType, aId,
                                                     aDetail) {
             currentView().setSelectedItems(items.length, items, false);
         },
         onGetResult: function selectAll_ogr(aCalendar, aStatus, aItemType,
                                             aDetail, aCount, aItems) {
-            for each (var item in aItems) {
+            for (var item of aItems) {
                 items.push(item);
             }
         }
     };
 
     var composite = getCompositeCalendar();
     var filter = composite.ITEM_FILTER_CLASS_OCCURRENCES;
 
--- a/calendar/base/content/dialogs/calendar-alarm-dialog.js
+++ b/calendar/base/content/dialogs/calendar-alarm-dialog.js
@@ -47,17 +47,17 @@ function onDismissAlarm(event) {
  * Called to dismiss all alarms in the alarm window.
  */
 function onDismissAllAlarms() {
     // removes widgets on the fly:
     let alarmRichlist = document.getElementById("alarm-richlist");
     let parentItems = {};
 
     // Make a copy of the child nodes as they get modified live
-    for each (let node in Array.slice(alarmRichlist.childNodes)) {
+    for (let node of alarmRichlist.childNodes) {
         // Check if the node is a valid alarm and is still part of DOM
         if (node.parentNode && node.item && node.alarm &&
             !(node.item.parentItem.hashId in parentItems)) {
             // We only need to acknowledge one occurrence for repeating items
             parentItems[node.item.parentItem.hashId] = node.item.parentItem;
             getAlarmService().dismissAlarm(node.item, node.alarm);
         }
     }
@@ -135,17 +135,17 @@ function onFocusWindow() {
     }
 }
 
 /**
  * Timer callback to update all relative date labels
  */
 function updateRelativeDates() {
     let alarmRichlist = document.getElementById("alarm-richlist");
-    for each (let node in Array.slice(alarmRichlist.childNodes)) {
+    for (let node of alarmRichlist.childNodes) {
         if (node.item && node.alarm) {
             node.updateRelativeDateLabel();
         }
     }
 }
 
 /**
  * Function to snooze all alarms the given number of minutes.
@@ -156,17 +156,17 @@ function snoozeAllItems(aDurationMinutes
     let duration = cal.createDuration();
     duration.minutes = aDurationMinutes;
     duration.normalize();
 
     let alarmRichlist = document.getElementById("alarm-richlist");
     let parentItems = {};
 
     // Make a copy of the child nodes as they get modified live
-    for each (let node in Array.slice(alarmRichlist.childNodes)) {
+    for (let node of alarmRichlist.childNodes) {
         // Check if the node is a valid alarm and is still part of DOM
         if (node.parentNode && node.item && node.alarm &&
             !(node.item.parentItem.hashId in parentItems)) {
             // We only need to acknowledge one occurrence for repeating items
             parentItems[node.item.parentItem.hashId] = node.item.parentItem;
             getAlarmService().snoozeAlarm(node.item, node.alarm, duration);
         }
     }
--- a/calendar/base/content/dialogs/calendar-dialog-utils.js
+++ b/calendar/base/content/dialogs/calendar-dialog-utils.js
@@ -124,17 +124,17 @@ function updateReminderDetails() {
     let reminderList = document.getElementById("item-alarm");
     let reminderMultipleLabel = document.getElementById("reminder-multiple-alarms-label");
     let iconBox = document.getElementById("reminder-icon-box");
     let reminderSingleLabel = document.getElementById("reminder-single-alarms-label");
     let reminders = document.getElementById("reminder-custom-menuitem").reminders || [];
     let calendar = getCurrentCalendar();
     let actionValues = calendar.getProperty("capabilities.alarms.actionValues") || ["DISPLAY"];
     let actionMap = {};
-    for each (var action in actionValues) {
+    for (var action of actionValues) {
         actionMap[action] = true;
     }
 
     // Filter out any unsupported action types.
     reminders = reminders.filter(x => x.action in actionMap);
 
     if (reminderList.value == "custom") {
         // Depending on how many alarms we have, show either the "Multiple Alarms"
@@ -192,17 +192,17 @@ function matchCustomReminderToMenuitem(r
         }
 
         let unitMap = {
           days: 86400,
           hours: 3600,
           minutes: 60
         };
 
-        for each (let menuitem in Array.slice(reminderPopup.childNodes)) {
+        for (let menuitem of reminderPopup.childNodes) {
             if (menuitem.localName == "menuitem" &&
                 menuitem.hasAttribute("length") &&
                 menuitem.getAttribute("origin") == origin &&
                 menuitem.getAttribute("relation") == relation) {
                 let unitMult = unitMap[menuitem.getAttribute("unit")] || 1;
                 let length = menuitem.getAttribute("length") * unitMult;
 
                 if (Math.abs(reminder.offset.inSeconds) == length) {
@@ -252,17 +252,17 @@ function loadReminders(reminders) {
  * Save the selected reminder into the passed item.
  *
  * @param item      The item save the reminder into.
  */
 function saveReminder(item) {
     // We want to compare the old alarms with the new ones. If these are not
     // the same, then clear the snooze/dismiss times
     let oldAlarmMap = {};
-    for each (let alarm in item.getAlarms({})) {
+    for (let alarm of item.getAlarms({})) {
         oldAlarmMap[alarm.icalString] = true;
     }
 
     // Clear the alarms so we can add our new ones.
     item.clearAlarms();
 
     let reminderList = document.getElementById("item-alarm");
     if (reminderList.value != 'none') {
@@ -280,27 +280,27 @@ function saveReminder(item) {
             // Pre-defined entries specify the necessary information
             // as attributes attached to the menuitem elements.
             reminders = [createReminderFromMenuitem(menuitem)];
         }
 
         let alarmCaps = item.calendar.getProperty("capabilities.alarms.actionValues") ||
                         ["DISPLAY"];
         let alarmActions = {};
-        for each (let action in alarmCaps) {
+        for (let action of alarmCaps) {
             alarmActions[action] = true;
         }
 
         // Make sure only alarms are saved that work in the given calendar.
         reminders.filter(x => x.action in alarmActions)
                  .forEach(item.addAlarm, item);
     }
 
     // Compare alarms to see if something changed.
-    for each (let alarm in item.getAlarms({})) {
+    for (let alarm of item.getAlarms({})) {
         let ics = alarm.icalString;
         if (ics in oldAlarmMap) {
             // The new alarm is also in the old set, remember this
             delete oldAlarmMap[ics];
         } else {
             // The new alarm is not in the old set, this means the alarms
             // differ and we can break out.
             oldAlarmMap[ics] = true;
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.js
@@ -82,17 +82,17 @@ function onLoad() {
     propagateDateTime();
     // Set the scroll bar at where the event is
     scrollToCurrentTime();
     updateButtons();
 
     // we need to enforce several layout constraints which can't be modelled
     // with plain xul and css, at least as far as i know.
     const kStylesheet = "chrome://calendar/skin/calendar-event-dialog.css";
-    for each (var stylesheet in document.styleSheets) {
+    for (var stylesheet of document.styleSheets) {
         if (stylesheet.href == kStylesheet) {
             // make the dummy-spacer #1 [top] the same height as the timebar
             var timebar = document.getElementById("timebar");
             stylesheet.insertRule(
                 ".attendee-spacer-top { height: "
                     + timebar.boxObject.height+"px; }", 0);
             // make the dummy-spacer #2 [bottom] the same height as the scrollbar
             var scrollbar = document.getElementById("horizontal-scrollbar");
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
@@ -155,17 +155,17 @@
                   organizer.commonName = calendar.getProperty("organizerCN");
               }
               organizer.isOrganizer = true;
               this.appendAttendee(organizer, listbox, template, true);
           }
 
           var numRowsAdded = 0;
           if (attendees.length > 0) {
-              for each (var attendee in attendees) {
+              for (var attendee of attendees) {
                   this.appendAttendee(attendee, listbox, template, false);
                   numRowsAdded++;
               }
           }
           if (numRowsAdded == 0) {
               this.appendAttendee(null, listbox, template, false);
           }
 
@@ -596,17 +596,17 @@
                       if (entries.length > 0) {
                           let currentIndex = parseInt(input.id.substr(13));
                           let template = document.getAnonymousElementByAttribute(this, "anonid", "item");
                           let currentNode = template.parentNode.childNodes[currentIndex];
                           this._fillListItemWithEntry(currentNode, entries[0], currentIndex);
                           entries.shift();
                           let nextNode = template.parentNode.childNodes[currentIndex+1];
                           currentIndex++;
-                          for each (let entry in entries) {
+                          for (let entry of entries) {
                               currentNode = template.cloneNode(true);
                               template.parentNode.insertBefore(currentNode, nextNode);
                               this._fillListItemWithEntry(currentNode, entry, currentIndex);
                               currentIndex++;
                           }
                           this.mMaxAttendees += entries.length;
                           for (let i = currentIndex; i <= this.mMaxAttendees; i++) {
                               let row = template.parentNode.childNodes[i];
--- a/calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
@@ -768,17 +768,17 @@
               // First of all set all state slots to 'free'
               for (let i = 0; i < this.mState.length; i++) {
                   this.mState[i] = Components.interfaces.calIFreeBusyInterval.FREE;
               }
 
               let numHours = this.numHours;
 
               // Iterate all incoming freebusy entries
-              for each (let entry in aEntries) {
+              for (let entry of aEntries) {
                   let rangeStart = entry.interval.start.getInTimezone(kDefaultTimezone);
                   let rangeEnd = entry.interval.end.getInTimezone(kDefaultTimezone);
 
                   if (rangeStart.compare(start) < 0) {
                       rangeStart = start.clone();
                   }
                   if (rangeEnd.compare(end) > 0) {
                       rangeEnd = end.clone();
@@ -907,17 +907,17 @@
           var newTime = aStartTime.clone();
           var duration = aEndTime.subtractDate(aStartTime);
           var newEndTime = newTime.clone();
           newEndTime.addDuration(duration);
 
           var kDefaultTimezone = calendarDefaultTimezone();
 
           if (this.mEntries) {
-              for each (var entry in this.mEntries) {
+              for (var entry of this.mEntries) {
                 var rangeStart =
                     entry.interval.start.getInTimezone(kDefaultTimezone);
                 var rangeEnd =
                     entry.interval.end.getInTimezone(kDefaultTimezone);
 
                 var isZeroLength = !newTime.compare(newEndTime);
                 if ((isZeroLength &&
                      newTime.compare(rangeStart) >= 0 &&
@@ -1128,17 +1128,17 @@
         <body><![CDATA[
           this.onInitialize();
         ]]></body>
       </method>
 
       <method name="onUnload">
         <body><![CDATA[
           // Cancel pending free/busy requests
-          for each (var request in this.mPendingRequests) {
+          for (var request of this.mPendingRequests) {
               request.cancel(null);
           }
 
           this.mPendingRequests = [];
         ]]></body>
       </method>
 
       <method name="onInitialize">
--- a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
@@ -503,17 +503,17 @@ function enableRecurrenceFields(aAttribu
  * @param recurrenceInfo    An item's recurrence info to parse.
  * @return                  An array with two elements: an array of positive
  *                            rules and an array of negative rules.
  */
 function splitRecurrenceRules(recurrenceInfo) {
     var ritems = recurrenceInfo.getRecurrenceItems({});
     var rules = [];
     var exceptions = [];
-    for each (var r in ritems) {
+    for (var r of ritems) {
         if (r.isNegative) {
             exceptions.push(r);
         } else {
             rules.push(r);
         }
     }
     return [rules, exceptions];
 }
--- a/calendar/base/content/dialogs/calendar-event-dialog-reminder.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-reminder.js
@@ -34,24 +34,24 @@ function onLoad() {
     setElementValue("reminder-after-end-menuitem",
                     _sn("reminderCustomOriginEndAfter"),
                     "label");
 
 
     // Set up the action map
     let supportedActions = calendar.getProperty("capabilities.alarms.actionValues") ||
                            ["DISPLAY" /* TODO email support, "EMAIL" */];
-    for each (let action in supportedActions) {
+    for (let action of supportedActions) {
         allowedActionsMap[action] = true;
     }
 
     // Hide all actions that are not supported by this provider
     let firstAvailableItem;
     let actionNodes = document.getElementById("reminder-actions-menupopup").childNodes;
-    for each (let actionNode in Array.slice(actionNodes)) {
+    for (let actionNode of actionNodes) {
         let shouldHide = (!(actionNode.value in allowedActionsMap) ||
                           (actionNode.hasAttribute("provider") &&
                            actionNode.getAttribute("provider") != calendar.type));
         setElementValue(actionNode, shouldHide && "true", "hidden");
         if (!firstAvailableItem && !shouldHide) {
             firstAvailableItem = actionNode;
         }
     }
@@ -417,18 +417,17 @@ function onRemoveReminder() {
 
 /**
  * Handler function to be called when the accept button is pressed.
  *
  * @return      Returns true if the window should be closed
  */
 function onAccept() {
     let listbox = document.getElementById("reminder-listbox");
-    let reminders = [ node.reminder 
-                      for each (node in Array.slice(listbox.childNodes)) ];
+    let reminders = Array.from(listbox.childNodes).map(node => node.reminder);
     if (window.arguments[0].onOk) {
         window.arguments[0].onOk(reminders);
     }
 
     return true;
 }
 
 /**
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -240,17 +240,17 @@ function onLoad() {
     window.initialStartDateValue = args.initialStartDateValue;
 
     // we store the array of attendees in the window.
     // clone each existing attendee since we still suffer
     // from the 'lost x-properties'-bug.
     window.attendees = [];
     var attendees = item.getAttendees({});
     if (attendees && attendees.length) {
-        for each (var attendee in attendees) {
+        for (var attendee of attendees) {
             window.attendees.push(attendee.clone());
         }
     }
 
     window.organizer = null;
     if (item.organizer) {
         window.organizer = item.organizer.clone();
     } else if (item.getAttendees({}).length > 0) {
@@ -437,17 +437,17 @@ function loadDialog(item) {
     // Categories
     loadCategories(item);
 
     // Attachment
     loadCloudProviders();
     var hasAttachments = capSupported("attachments");
     var attachments = item.getAttachments({});
     if (hasAttachments && attachments && attachments.length > 0) {
-        for each (var attachment in attachments) {
+        for (var attachment of attachments) {
             addAttachment(attachment);
         }
     } else {
         updateAttachment();
     }
 
     // URL link
     updateLink();
@@ -922,17 +922,17 @@ function updateDateCheckboxes(aDatePicke
 function loadRepeat(item) {
     var recurrenceInfo = window.recurrenceInfo;
     setElementValue("item-repeat", "none");
     if (recurrenceInfo) {
         setElementValue("item-repeat", "custom");
         var ritems = recurrenceInfo.getRecurrenceItems({});
         var rules = [];
         var exceptions = [];
-        for each (var r in ritems) {
+        for (var r of ritems) {
             if (r.isNegative) {
                 exceptions.push(r);
             } else {
                 rules.push(r);
             }
         }
         if (rules.length == 1) {
             let rule = cal.wrapInstance(rules[0], Components.interfaces.calIRecurrenceRule);
@@ -1095,17 +1095,18 @@ function saveDialog(item) {
     // Categories
     saveCategories(item);
 
     // Attachment
     // We want the attachments to be up to date, remove all first.
     item.removeAllAttachments();
 
     // Now add back the new ones
-    for each (var att in gAttachMap) {
+    for (var hashId in gAttachMap) {
+        var att = gAttachMap[hashId];
         item.addAttachment(att);
     }
 
     // Description
     setItemProperty(item, "DESCRIPTION", getElementValue("item-description"));
 
     // Event Status
     if (isEvent(item)) {
@@ -1213,17 +1214,17 @@ function updateTitle() {
  *      dialog[itemType="task"] .event-only,
  *      dialog[itemType="event"] .task-only {
  *          display: none;
  *      }
 */
 function updateStyle() {
     const kDialogStylesheet = "chrome://calendar/skin/calendar-event-dialog.css";
 
-    for each (let stylesheet in document.styleSheets) {
+    for (let stylesheet of document.styleSheets) {
         if (stylesheet.href == kDialogStylesheet) {
             if (cal.isEvent(window.calendarItem)) {
                 stylesheet.insertRule(".todo-only { display: none; }",
                                       stylesheet.cssRules.length);
             } else if (cal.isToDo(window.calendarItem)) {
                 stylesheet.insertRule(".event-only { display: none; }",
                                       stylesheet.cssRules.length);
             }
@@ -2806,17 +2807,17 @@ function saveItem() {
 
     // serialize the item
     saveDialog(item);
 
     item.organizer = window.organizer;
 
     item.removeAllAttendees();
     if (window.attendees && (window.attendees.length > 0)) {
-        for each (var attendee in window.attendees) {
+        for (var attendee of window.attendees) {
            item.addAttendee(attendee);
         }
 
         let notifyCheckbox = document.getElementById("notify-attendees-checkbox");
         if (notifyCheckbox.disabled) {
             item.deleteProperty("X-MOZ-SEND-INVITATIONS");
         } else {
             item.setProperty("X-MOZ-SEND-INVITATIONS", notifyCheckbox.checked ? "TRUE" : "FALSE");
@@ -3152,17 +3153,17 @@ function showTimezonePopup(event, dateTi
     timezoneDefaultItem.label = defaultTimezone.displayName;
 
     // Clear out any old recent timezones
     while (timezoneDefaultItem.nextSibling != timezoneSeparator) {
         timezoneDefaultItem.nextSibling.remove();
     }
 
     // Fill in the new recent timezones
-    for each (let tz in recentTimezones) {
+    for (let tz of recentTimezones) {
         let menuItem = createXULElement("menuitem");
         menuItem.setAttribute("value", tz.tzid);
         menuItem.setAttribute("label", tz.displayName);
         timezonePopup.insertBefore(menuItem, timezoneDefaultItem.nextSibling);
     }
 
     // Show the popup
     timezonePopup.openPopup(event.target, "after_start", 0, 0, true);
--- a/calendar/base/content/dialogs/calendar-invitations-dialog.js
+++ b/calendar/base/content/dialogs/calendar-invitations-dialog.js
@@ -37,17 +37,17 @@ function onLoad() {
                                              aItems) {
             if (!Components.isSuccessCode(aStatus)) {
                 return;
             }
             document.title = invitationsText + " (" + aCount + ")";
             var updatingBox = document.getElementById("updating-box");
             updatingBox.setAttribute("hidden", "true");
             var richListBox = document.getElementById("invitations-listbox");
-            for each (var item in aItems) {
+            for (var item of aItems) {
                 richListBox.addCalendarItem(item);
             }
         }
     };
 
     var updatingBox = document.getElementById("updating-box");
     updatingBox.removeAttribute("hidden");
 
--- a/calendar/base/content/dialogs/calendar-migration-dialog.js
+++ b/calendar/base/content/dialogs/calendar-migration-dialog.js
@@ -30,17 +30,17 @@ var gMigrateWizard = {
         wizard.title = props.formatStringFromName("migrationTitle",
                                                   ["Lightning"],
                                                   1);
         desc.textContent = props.formatStringFromName("migrationDescription",
                                                       ["Lightning"],
                                                       1);
 
         migLOG("migrators: " + window.arguments.length);
-        for each (var migrator in window.arguments[0]) {
+        for (var migrator of window.arguments[0]) {
             var listItem = document.createElement("listitem");
             listItem.setAttribute("type", "checkbox");
             listItem.setAttribute("checked", true);
             listItem.setAttribute("label", migrator.title);
             listItem.migrator = migrator;
             listbox.appendChild(listItem);
         }
     },
@@ -177,19 +177,19 @@ var gDataMigrator = {
         migLOG("mPlatform is: " + this.mPlatform);
 
         var DMs = [];
         var migrators = [this.checkOldCal,
                          this.checkEvolution,
                          this.checkWindowsMail,
                          this.checkIcal];
         // XXX also define a category and an interface here for pluggability
-        for each (var migrator in migrators) {
+        for (var migrator of migrators) {
             var migs = migrator.call(this);
-            for each (var dm in migs) {
+            for (var dm of migs) {
                 DMs.push(dm);
             }
         }
 
         if (DMs.length == 0) {
             // No migration available
             return;
         }
@@ -244,17 +244,17 @@ var gDataMigrator = {
         }
 
         // Callback from the XHR above.  Parses CalendarManager.rdf and imports
         // the data describe therein.
         function parseAndMigrate(aDoc, aCallback) {
             // For duplicate detection
             var calManager = getCalendarManager();
             var uris = [];
-            for each (var oldCal in calManager.getCalendars({})) {
+            for (var oldCal of calManager.getCalendars({})) {
                 uris.push(oldCal.uri);
             }
 
             function getRDFAttr(aNode, aAttr) {
                 return aNode.getAttributeNS("http://home.netscape.com/NC-rdf#",
                                             aAttr);
             }
 
@@ -307,17 +307,17 @@ var gDataMigrator = {
         }
 
         // We're lightning, check Sunbird
         if ((sbProf = this.getSunbirdProfile())) {
             profiles.push(sbProf);
         }
 
         // Now check all of the profiles in each of these folders for data
-        for each (var prof in profiles) {
+        for (var prof of profiles) {
             var dirEnum = prof.directoryEntries;
             while (dirEnum.hasMoreElements()) {
                 var profile = dirEnum.getNext().QueryInterface(Components.interfaces.nsIFile);
                 if (profile.isFile()) {
                     continue;
                 } else {
                     profile.append("Calendar");
                     if (profile.exists()) {
--- a/calendar/base/content/dialogs/calendar-print-dialog.js
+++ b/calendar/base/content/dialogs/calendar-print-dialog.js
@@ -98,17 +98,17 @@ function getPrintSettings(receiverFunc) 
             if (cal.isToDo(item) && !settings.printTasks) return false;
             return true;
         });
 
         // If tasks should be printed, also include selected tasks from the
         // opening window.
         if (settings.printTasks) {
             let selectedTasks = window.opener.getSelectedTasks();
-            for each (var task in selectedTasks) {
+            for (var task of selectedTasks) {
                 settings.eventList.push(task);
             }
         }
 
         // We've set the event list above, no need to fetch items below.
         requiresFetch = false;
         break;
     }
@@ -137,17 +137,17 @@ function getPrintSettings(receiverFunc) 
             function onOperationComplete(aCalendar, aStatus, aOperationType, aId, aDateTime) {
                 receiverFunc(settings);
             },
             onGetResult:
             function onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 settings.eventList = settings.eventList.concat(aItems);
                 if (!settings.printTasksWithNoDueDate) {
                     eventWithDueDate = [];
-                    for each (var item in settings.eventList) {
+                    for (var item of settings.eventList) {
                         if (item.dueDate || item.endDate) {
                             eventWithDueDate.push(item)
                         }
                     }
                     settings.eventList = eventWithDueDate;
                 }
             }
         };
--- a/calendar/base/content/dialogs/calendar-properties-dialog.js
+++ b/calendar/base/content/dialogs/calendar-properties-dialog.js
@@ -144,17 +144,17 @@ function initRefreshInterval() {
 
     if (gCalendar.canRefresh) {
         let refreshInterval = gCalendar.getProperty("refreshInterval");
         if (refreshInterval === null) refreshInterval = 30;
 
         let foundValue = false;
         let separator = document.getElementById("calendar-refreshInterval-manual-separator");
         let menulist = document.getElementById("calendar-refreshInterval-menulist");
-        for each (let min in [1, 5, 15, 30, 60]) {
+        for (let min of [1, 5, 15, 30, 60]) {
             let menuitem = createMenuItem(min);
 
             separator.parentNode.insertBefore(menuitem, separator);
             if (refreshInterval == min) {
                 menulist.selectedItem = menuitem;
                 foundValue = true;
             }
         }
--- a/calendar/base/content/dialogs/calendar-subscriptions-dialog.js
+++ b/calendar/base/content/dialogs/calendar-subscriptions-dialog.js
@@ -92,25 +92,25 @@ function onCancel() {
  */
 function onSearch() {
     cancelPendingSearchOperation();
 
     var richListBox = document.getElementById("subscriptions-listbox");
     richListBox.clear();
 
     var registeredCals = {};
-    for each (var calendar in getCalendarManager().getCalendars({})) {
+    for (var calendar of getCalendarManager().getCalendars({})) {
         registeredCals[calendar.id] = true;
     }
 
     var opListener = {
         onResult: function search_onResult(op, result) {
             var richListBox = document.getElementById("subscriptions-listbox");
             if (result) {
-                for each (var calendar in result) {
+                for (var calendar of result) {
                     richListBox.addCalendar(calendar, registeredCals[calendar.id]);
                 }
             }
             if (!op.isPending) {
                 var statusDeck = document.getElementById("status-deck");
                 if (richListBox.getRowCount() > 0) {
                     statusDeck.selectedIndex = 0;
                 } else {
--- a/calendar/base/content/import-export.js
+++ b/calendar/base/content/import-export.js
@@ -45,17 +45,17 @@ function loadEventsFromFile(aCalendar) {
         try {
             importer = Components.classes[contractid]
                                  .getService(Components.interfaces.calIImporter);
         } catch (e) {
             cal.WARN("Could not initialize importer: " + contractid + "\nError: " + e);
             continue;
         }
         let types = importer.getFileTypes({});
-        for each (let type in types) {
+        for (let type of types) {
             fp.appendFilter(type.description, type.extensionFilter);
             if (type.extensionFilter=="*." + fp.defaultExtension) {
                 fp.filterIndex = currentListLength;
                 defaultCIDIndex = currentListLength;
             }
             contractids.push(contractid);
             currentListLength++;
         }
@@ -172,17 +172,17 @@ function putItemsIntoCal(destCal, aItems
                     showError(calGetString("calendar", "duplicateError", [duplicateCount, aFilePath]));
                 } else if (failedCount) {
                     showError(calGetString("calendar", "importItemsFailed", [failedCount, lastError.toString()]));
                 }
             }
         }
     }
 
-    for each (let item in aItems) {
+    for (let item of aItems) {
         // XXX prompt when finding a duplicate.
         try {
             destCal.addItem(item, listener);
         } catch(e) {
             failedCount++;
             lastError = e;
             // Call the listener's operationComplete, to increase the
             // counter and not miss failed items. Otherwise, endBatch might
@@ -243,17 +243,17 @@ function saveEventsToFile(calendarEventA
         try {
             exporter = Components.classes[contractid]
                                  .getService(Components.interfaces.calIExporter);
         } catch (e) {
             cal.WARN("Could not initialize exporter: " + contractid + "\nError: " + e);
             continue;
         }
         let types = exporter.getFileTypes({});
-        for each (let type in types) {
+        for (let type of types) {
             fp.appendFilter(type.description, type.extensionFilter);
             if (type.extensionFilter=="*." + fp.defaultExtension) {
                 fp.filterIndex = currentListLength;
                 defaultCIDIndex = currentListLength;
             }
             contractids.push(contractid);
             currentListLength++;
         }
@@ -323,17 +323,17 @@ function exportEntireCalendar(aCalendar)
     var getListener = {
         QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
         onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail)
         {
             saveEventsToFile(itemArray, aCalendar.name);
         },
         onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
         {
-            for each (let item in aItems) {
+            for (let item of aItems) {
                 itemArray.push(item);
             }
         }
     };
 
     function getItemsFromCal(aCal) {
         aCal.getItems(Components.interfaces.calICalendar.ITEM_FILTER_ALL_ITEMS,
                       0, null, null, getListener);
--- a/calendar/base/content/widgets/calendar-list-tree.xml
+++ b/calendar/base/content/widgets/calendar-list-tree.xml
@@ -233,17 +233,17 @@
       <constructor><![CDATA[
         Components.utils.import("resource://calendar/modules/calUtils.jsm");
         Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
         this.tree.view = this;
       ]]></constructor>
       <destructor><![CDATA[
         // Clean up the calendar manager observers. Do not use removeCalendar
         // here since that will remove the calendar from the composite calendar.
-        for each (let calendar in this.mCalendarList) {
+        for (let calendar of this.mCalendarList) {
             calendar.removeObserver(this.calObserver);
         }
 
         this.tree.view = null;
         this.calObserver.listTree = null;
 
         if (this.mCompositeCalendar) {
             this.mCompositeCalendar.removeObserver(this.compositeObserver);
@@ -323,17 +323,17 @@
       <property name="tree"
                 readonly="true"
                 onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'tree')"/>
 
 
       <property name="sheet" readonly="true">
         <getter><![CDATA[
           if (!this.mCachedSheet) {
-              for each (let sheet in document.styleSheets) {
+              for (let sheet of document.styleSheets) {
                   if (sheet.href == "chrome://calendar/skin/calendar-management.css") {
                       this.mCachedSheet = sheet;
                       break;
                   }
               }
               if (!this.mCachedSheet) {
                 cal.ERROR("Could not find calendar-management.css, needs to be added to " +
                           window.document.title + "'s stylesheets");
--- a/calendar/base/content/widgets/calendar-widgets.xml
+++ b/calendar/base/content/widgets/calendar-widgets.xml
@@ -174,28 +174,28 @@
         <body><![CDATA[
           let categoryListbox = document.getAnonymousElementByAttribute(this, "anonid", "categories-listbox");
           let categoryList = getPrefCategoriesArray();
 
           cal.sortArrayByLocaleCollator(categoryList);
 
           removeChildren(categoryListbox);
 
-          for each (let cat in categoryList) {
+          for (let cat of categoryList) {
               // First insert all categories from the prefs
               let item = categoryListbox.appendItem(cat, cat);
               item.setAttribute("type", "checkbox");
           }
 
           if (aItem) {
               let localeCollator = cal.createLocaleCollator();
               let compare = localeCollator.compareString.bind(localeCollator, 0);
 
               // Ensure the item's categories are in the list and they are checked.
-              for each (let cat in aItem.getCategories({})) {
+              for (let cat of aItem.getCategories({})) {
                 this.insertCategory(cat, categoryList, categoryListbox, compare);
               }
           }
         ]]></body>
       </method>
     </implementation>
   </binding>
 
@@ -562,18 +562,20 @@
         ]]></body>
       </method>
 
       <!-- removes all dropShadows from the binding. Dropshadows are recognized
            as such by carrying an attribute "dropshadow" -->
       <method name="removeDropShadows">
         <body><![CDATA[
             // method that may be overwritten by derived bindings...
-            for each (let shadow in this.calendarView.mDropShadows) {
-                cal.removeChildElementsByAttribute(shadow, "class", "dropshadow");
+            if (this.calendarView.mDropShadows) {
+                for (let shadow of this.calendarView.mDropShadows) {
+                    cal.removeChildElementsByAttribute(shadow, "class", "dropshadow");
+                }
             }
             this.calendarView.mDropShadows = null;
         ]]></body>
       </method>
 
       <!-- By setting the attribute "dropbox" to "true" or "false" the
            dropshadows are added or removed -->
       <method name="setAttribute">
--- a/calendar/base/content/widgets/minimonth.xml
+++ b/calendar/base/content/widgets/minimonth.xml
@@ -474,47 +474,47 @@
         <parameter name="aItemType"/>
         <parameter name="aDetail"/>
         <parameter name="aCount"/>
         <parameter name="aItems"/>
         <body><![CDATA[
             if (!Components.isSuccessCode(aStatus)) {
                 return;
             }
-            for each (var item in aItems) {
+            for (var item of aItems) {
                 this.setBusyDaysForOccurrence(item, true);
             }
         ]]></body>
       </method>
 
       <method name="setBusyDaysForItem">
         <parameter name="aItem"/>
         <parameter name="aState"/>
         <body><![CDATA[
           var items = [aItem];
           if (aItem.recurrenceInfo) {
               var startDate = this.firstDate;
               var endDate = this.lastDate;
               items = aItem.getOccurrencesBetween(startDate, endDate, {});
           }
-          for each (var item in items) {
+          for (var item of items) {
               this.setBusyDaysForOccurrence(item, aState);
           }
         ]]></body>
       </method>
 
       <method name="parseBoxBusy">
         <parameter name="aBox"/>
         <body><![CDATA[
           let boxBusy = {};
 
           let busyStr = aBox.getAttribute("busy");
           if (busyStr && busyStr.length > 0) {
               let calChunks = busyStr.split("\u001A");
-              for each (let chunk in calChunks) {
+              for (let chunk of calChunks) {
                   let expr = chunk.split("=");
                   boxBusy[expr[0]] = parseInt(expr[1]);
               }
           }
 
           return boxBusy;
         ]]></body>
       </method>
--- a/calendar/base/modules/calAuthUtils.jsm
+++ b/calendar/base/modules/calAuthUtils.jsm
@@ -119,17 +119,17 @@ cal.auth = {
         }
 
         try {
             if (!Services.logins.getLoginSavingEnabled(aUsername)) {
                 return false;
             }
 
             let logins = Services.logins.findLogins({}, aHostName, null, aRealm);
-            for each (let loginInfo in logins) {
+            for (let loginInfo of logins) {
                 if (loginInfo.username == aUsername) {
                     aPassword.value = loginInfo.password;
                     return true;
                 }
             }
         } catch (exc) {
             cal.ASSERT(false, exc);
         }
@@ -144,17 +144,17 @@ cal.auth = {
      * @param aRealm        The password realm (unused on branch)
      * @return              Could the user be removed?
      */
     passwordManagerRemove: function calPasswordManagerRemove(aUsername, aHostName, aRealm) {
         cal.ASSERT(aUsername);
 
         try {
             let logins = Services.logins.findLogins({}, aHostName, null, aRealm);
-            for each (let loginInfo in logins) {
+            for (let loginInfo of logins) {
                 if (loginInfo.username == aUsername) {
                     Services.logins.removeLogin(loginInfo);
                     return true;
                 }
             }
         } catch (exc) {
         }
         return false;
--- a/calendar/base/modules/calItemUtils.jsm
+++ b/calendar/base/modules/calItemUtils.jsm
@@ -63,17 +63,17 @@ itemDiff.prototype = {
      * Loads an array of items. This step cannot be executed
      * after calling the difference methods.
      *
      * @param items     The array of items to load
      */
     load: function load(items) {
         this._expectState(this.STATE_INITIAL | this.STATE_LOADING);
 
-        for each (let item in items) {
+        for (let item of items) {
             this.mInitialItems[item.hashId] = item;
         }
 
         this.state = this.STATE_LOADING;
     },
 
     /**
      * Calculates the difference for the passed item, see difference.
@@ -92,17 +92,17 @@ itemDiff.prototype = {
      */
     difference: function difference(items) {
         this._expectState(this.STATE_INITIAL | this.STATE_LOADING | this.STATE_DIFFERING);
 
         this.mModifiedOldItems.startBatch();
         this.mModifiedItems.startBatch();
         this.mAddedItems.startBatch();
 
-        for each (let item in items) {
+        for (let item of items) {
             if (item.hashId in this.mInitialItems) {
                 let oldItem = this.mInitialItems[item.hashId];
                 this.mModifiedOldItems.addItem(oldItem);
                 this.mModifiedItems.addItem(item);
             } else {
                 this.mAddedItems.addItem(item);
             }
             delete this.mInitialItems[item.hashId];
@@ -119,17 +119,18 @@ itemDiff.prototype = {
      * Tell the engine that all load and difference calls have been made, this
      * makes sure that all item states are correctly returned.
      */
     complete: function complete() {
         this._expectState(this.STATE_INITIAL | this.STATE_LOADING | this.STATE_DIFFERING);
 
         this.mDeletedItems.startBatch();
 
-        for each (let item in this.mInitialItems) {
+        for (let hashId in this.mInitialItems) {
+            let item = this.mInitialItems[hashId];
             this.mDeletedItems.addItem(item);
         }
 
         this.mDeletedItems.endBatch();
         this.mInitialItems = {};
 
         this.state = this.STATE_COMPLETED;
     },
--- a/calendar/base/modules/calIteratorUtils.jsm
+++ b/calendar/base/modules/calIteratorUtils.jsm
@@ -13,21 +13,21 @@ this.EXPORTED_SYMBOLS = ["cal"]; // even
  * overridden instances of a recurring series.
  *
  * @param items array of items
  */
 cal.itemIterator = function cal_itemIterator(items) {
     return {
         __iterator__: function itemIterator(aWantKeys) {
             cal.ASSERT(aWantKeys, "Please use for() on the item iterator");
-            for each (let item in items) {
+            for (let item of items) {
                 yield item;
                 let rec = item.recurrenceInfo;
                 if (rec) {
-                    for each (let exid in rec.getExceptionIds({})) {
+                    for (let exid of rec.getExceptionIds({})) {
                         yield rec.getExceptionFor(exid);
                     }
                 }
             }
         }
     };
 };
 
@@ -39,31 +39,39 @@ cal.itemIterator = function cal_itemIter
  *
  * If you would like to break or continue inside the body(), return either
  *     cal.forEach.BREAK or cal.forEach.CONTINUE
  *
  * Note since the event queue is used, this function will return immediately,
  * before the iteration is complete. If you need to run actions after the real
  * for each loop, use the optional completed() function.
  *
- * @param iter          The Iterator to go through in this loop.
+ * @param iter          The Iterator or the plain Object to go through in this
+ *                      loop.
  * @param body          The function called for each iteration. Its parameter is
  *                          the single item from the iterator.
  * @param completed     [optional] The function called after the loop completes.
  */
 cal.forEach = function cal_forEach(iter, body, completed) {
     // This should be a const one day, lets keep it a pref for now though until we
     // find a sane value.
     let LATENCY = Preferences.get("calendar.threading.latency", 250);
 
     let ourIter = iter;
     if (!(iter instanceof Iterator)) {
-        // If its not an iterator, we need to use a generator expression to make
-        // sure calling this function feels right.
-        ourIter = (i for each (i in iter));
+        // If its not an iterator, we need to use a generator to make sure
+        // calling this function feels right.
+        // FIXME: Dispatcher needs StopIteration, so we use legacy generator
+        // here for now.  Should be replaced with ES6 generator in the future,
+        // when removing Iterator from caller.
+        ourIter = (function() {
+            for (let key in iter) {
+              yield iter[key];
+            }
+        })();
     }
 
     let currentThread = Services.tm.currentThread;
 
     // This is our dispatcher, it will be used for the iterations
     let dispatcher = {
         run: function run() {
             try {
@@ -192,27 +200,34 @@ cal.ical = {
         };
     },
 
     /**
      * Use to iterate through all parameters of a calIIcalProperty.
      * This iterator behaves similar to the object iterator. Possible uses:
      *   for (let paramName in cal.ical.paramIterator(prop)) { ... }
      * or:
-     *   for each (let [paramName, paramValue] in cal.ical.paramIterator(prop)) { ... }
+     *   for (let [paramName, paramValue] of cal.ical.paramIterator(prop)) { ... }
      *
      * @param aProperty         The property to iterate.
      * @return                  An iterator object to iterate the properties.
      */
     paramIterator: function cal_ical_paramIterator(aProperty) {
         return {
             __iterator__: function icalParamIterator(aWantKeys) {
                 for (let paramName = aProperty.getFirstParameterName();
                      paramName;
                      paramName = aProperty.getNextParameterName()) {
                     yield (aWantKeys ? paramName :
                            [paramName, aProperty.getParameter(paramName)]);
                 }
+            },
+            [Symbol.iterator]: function* icalParamIterator() {
+                for (let paramName = aProperty.getFirstParameterName();
+                     paramName;
+                     paramName = aProperty.getNextParameterName()) {
+                    yield [paramName, aProperty.getParameter(paramName)];
+                }
             }
-        }
+        };
     }
 };
 
--- a/calendar/base/modules/calItipUtils.jsm
+++ b/calendar/base/modules/calItipUtils.jsm
@@ -544,17 +544,17 @@ cal.itip = {
                     return;
                 }
             }
 
             if (aOriginalItem.recurrenceInfo && aItem.recurrenceInfo) {
                 // check whether the two differ only in EXDATEs
                 let clonedItem = aItem.clone();
                 let exdates = [];
-                for each (let ritem in clonedItem.recurrenceInfo.getRecurrenceItems({})) {
+                for (let ritem of clonedItem.recurrenceInfo.getRecurrenceItems({})) {
 
                     let wrappedRItem = cal.wrapInstance(ritem, Components.interfaces.calIRecurrenceDate);
                     if (ritem.isNegative &&
                         wrappedRItem &&
                         !aOriginalItem.recurrenceInfo.getRecurrenceItems({}).some(
                             function(r) {
                                 let wrappedR = cal.wrapInstance(r, Components.interfaces.calIRecurrenceDate);
                                 return (r.isNegative &&
@@ -675,31 +675,32 @@ cal.itip = {
 
         let originalAtt = (aOriginalItem ? aOriginalItem.getAttendees({}) : []);
         let itemAtt = aItem.getAttendees({});
         let canceledAttendees = [];
         let addedAttendees = [];
 
         if (itemAtt.length > 0 || originalAtt.length > 0) {
             let attMap = {};
-            for each (let att in originalAtt) {
+            for (let att of originalAtt) {
                 attMap[att.id.toLowerCase()] = att;
             }
 
-            for each (let att in itemAtt) {
+            for (let att of itemAtt) {
                 if (att.id.toLowerCase() in attMap) {
                     // Attendee was in original item.
                     delete attMap[att.id.toLowerCase()];
                 } else {
                     // Attendee only in new item
                     addedAttendees.push(att);
                 }
             }
 
-            for each (let cancAtt in attMap) {
+            for (let id in attMap) {
+                let cancAtt = attMap[id];
                 canceledAttendees.push(cancAtt);
             }
         }
 
         // setting default value to control for sending (cancellation) messages
         // this will be set to false, once the user cancels sending manually
         let sendOut = true;
         // Check to see if some part of the item was updated, if so, re-send REQUEST
@@ -717,17 +718,17 @@ cal.itip = {
                 }
 
                 // Fix up our attendees for invitations using some good defaults
                 let recipients = [];
                 let itemAtt = requestItem.getAttendees({});
                 if (!isMinorUpdate) {
                     requestItem.removeAllAttendees();
                 }
-                for each (let attendee in itemAtt) {
+                for (let attendee of itemAtt) {
                     if (!isMinorUpdate) {
                         attendee = attendee.clone();
                         if (!attendee.role) {
                             attendee.role = "REQ-PARTICIPANT";
                         }
                         attendee.participationStatus = "NEEDS-ACTION";
                         attendee.rsvp = "TRUE";
                         requestItem.addAttendee(attendee);
@@ -752,17 +753,17 @@ cal.itip = {
 
             }
         }
 
         // Cancel the event for all canceled attendees
         if (canceledAttendees.length > 0) {
             let cancelItem = aOriginalItem.clone();
             cancelItem.removeAllAttendees();
-            for each (let att in canceledAttendees) {
+            for (let att of canceledAttendees) {
                 cancelItem.addAttendee(att);
             }
             if (sendOut) {
                 sendMessage(cancelItem, "CANCEL", canceledAttendees, autoResponse);
             }
         }
     },
 
@@ -907,33 +908,33 @@ function stripUserData(item_) {
  * @param item         the stored calendar item to update
  * @param itipItemItem the received item
  */
 function updateItem(item, itipItemItem) {
     function updateUserData(newItem, item) {
         // preserve user settings:
         newItem.generation = item.generation;
         newItem.clearAlarms();
-        for each (let alarm in item.getAlarms({})) {
+        for (let alarm of item.getAlarms({})) {
             newItem.addAlarm(alarm);
         }
         newItem.alarmLastAck = item.alarmLastAck;
         let cats = item.getCategories({});
         newItem.setCategories(cats.length, cats);
     }
 
     let newItem = item.clone();
     newItem.icalComponent = itipItemItem.icalComponent;
     setReceivedInfo(newItem, itipItemItem);
     updateUserData(newItem, item);
 
     let recInfo = itipItemItem.recurrenceInfo;
     if (recInfo) {
         // keep care of installing all overridden items, and mind existing alarms, categories:
-        for each (let rid in recInfo.getExceptionIds({})) {
+        for (let rid of recInfo.getExceptionIds({})) {
             let excItem = recInfo.getExceptionFor(rid).clone();
             cal.ASSERT(excItem, "unexpected!");
             let newExc = newItem.recurrenceInfo.getOccurrenceFor(rid).clone();
             newExc.icalComponent = excItem.icalComponent;
             setReceivedInfo(newExc, itipItemItem);
             let existingExcItem = (item.recurrenceInfo && item.recurrenceInfo.getExceptionFor(rid));
             if (existingExcItem) {
                 updateUserData(newExc, existingExcItem);
@@ -951,17 +952,17 @@ function updateItem(item, itipItemItem) 
  *
  * @param itipItem      The itip item containing the receivedMethod.
  * @param itipItemItem  The calendar item inside the itip item.
  * @param item          The target item to copy to.
  */
 function copyProviderProperties(itipItem, itipItemItem, item) {
     // Copy over itip properties to the item if requested by the provider
     let copyProps = item.calendar.getProperty("itip.copyProperties") || [];
-    for each (let prop in copyProps) {
+    for (let prop of copyProps) {
         if (prop == "METHOD") {
             // Special case, this copies over the received method
             item.setProperty("METHOD", itipItem.receivedMethod.toUpperCase());
         } else if (itipItemItem.hasProperty(prop)) {
             // Otherwise just copy from the item contained in the itipItem
             item.setProperty(prop, itipItemItem.getProperty(prop));
         }
     }
@@ -1033,17 +1034,17 @@ function sendMessage(aItem, aMethod, aRe
     };
 
     // split up transport, if attendee undisclosure is requested
     // and this is a message send by the organizer
     if((aItem.getProperty("X-MOZ-SEND-INVITATIONS-UNDISCLOSED") == "TRUE") &&
        aMethod != "REPLY" &&
        aMethod != "REFRESH" &&
        aMethod != "COUNTER") {
-        for each( aRecipient in aRecipientsList) {
+        for (let aRecipient of aRecipientsList) {
             // create a list with a single recipient
             let sendToList = [aRecipient];
             // remove other recipients from vevent attendee list
             let sendItem = aItem.clone();
             sendItem.removeAllAttendees();
             sendItem.addAttendee(aRecipient);
             // send message
             if (!_sendItem(sendToList, sendItem)) {
@@ -1265,18 +1266,18 @@ ItipItemFinder.prototype = {
                 //           implicitly on the parent (ics/memory/storage calls modifyException),
                 //           the generation check will fail. We should really consider to allow
                 //           deletion/modification/addition of occurrences directly on the providers,
                 //           which would ease client code a lot.
                 case "REFRESH":
                 case "PUBLISH":
                 case "REQUEST":
                 case "REPLY":
-                    for each (let itipItemItem in this.mItipItem.getItemList({})) {
-                        for each (let item in this.mFoundItems) {
+                    for (let itipItemItem of this.mItipItem.getItemList({})) {
+                        for (let item of this.mFoundItems) {
                             let rid = itipItemItem.recurrenceId; //  XXX todo support multiple
                             if (rid) { // actually applies to individual occurrence(s)
                                 if (item.recurrenceInfo) {
                                     item = item.recurrenceInfo.getOccurrenceFor(rid);
                                     if (!item) {
                                         continue;
                                     }
                                 } else { // the item has been rescheduled with master:
@@ -1407,18 +1408,18 @@ ItipItemFinder.prototype = {
                                     break;
                                 }
                             }
                         }
                     }
                     break;
                 case "CANCEL": {
                     let modifiedItems = {};
-                    for each (let itipItemItem in this.mItipItem.getItemList({})) {
-                        for each (let item in this.mFoundItems) {
+                    for (let itipItemItem of this.mItipItem.getItemList({})) {
+                        for (let item of this.mFoundItems) {
                             let rid = itipItemItem.recurrenceId; //  XXX todo support multiple
                             if (rid) { // actually a CANCEL of occurrence(s)
                                 if (item.recurrenceInfo) {
                                     // collect all occurrence deletions into a single parent modification:
                                     let newItem = modifiedItems[item.id];
                                     if (!newItem) {
                                         newItem = item.clone();
                                         modifiedItems[item.id] = newItem;
@@ -1456,17 +1457,17 @@ ItipItemFinder.prototype = {
         } else { // not found:
             cal.LOG("iTIP on " + method + ": no existing items.");
 
             // If the item was not found, observe the target calendar anyway.
             // It will likely be the composite calendar, so we should update
             // if an item was added or removed
             this._observeChanges(this.mItipItem.targetCalendar);
 
-            for each (let itipItemItem in this.mItipItem.getItemList({})) {
+            for (let itipItemItem of this.mItipItem.getItemList({})) {
                 switch (method) {
                     case "REQUEST":
                     case "PUBLISH": {
                         let this_ = this;
                         let action = function(opListener, partStat) {
                             let newItem = itipItemItem.clone();
                             setReceivedInfo(newItem, itipItemItem);
                             newItem.parentItem.calendar = this_.mItipItem.targetCalendar;
@@ -1509,17 +1510,17 @@ ItipItemFinder.prototype = {
                 }
             }
         }
 
         cal.LOG("iTIP operations: " + operations.length);
         let actionFunc = null;
         if (operations.length > 0) {
             actionFunc = function execOperations(opListener, partStat) {
-                for each (let op in operations) {
+                for (let op of operations) {
                     try {
                         op(opListener, partStat);
                     } catch (exc) {
                         cal.ERROR(exc);
                     }
                 }
             };
             actionFunc.method = actionMethod;
--- a/calendar/base/modules/calPrintUtils.jsm
+++ b/calendar/base/modules/calPrintUtils.jsm
@@ -27,17 +27,17 @@ cal.print = {
      *
      * @param document      The document that contains <style id="sheet"/>.
      * @param categories    Array of categories to insert rules for.
      */
     insertCategoryRules: function insertCategoryRules(document, categories) {
         let sheet = document.getElementById("sheet");
         sheet.insertedCategoryRules = sheet.insertedCategoryRules || {};
 
-        for each (let category in categories) {
+        for (let category of categories) {
             let prefName = cal.formatStringForCSSRule(category);
             let color = Preferences.get("calendar.category.color." + prefName) || "transparent";
             if (!(prefName in sheet.insertedCategoryRules)) {
                 sheet.insertedCategoryRules[prefName] = true;
                 let ruleAdd = ' .category-color-box[categories~="' + prefName + '"] { ' +
                               ' border: 2px solid ' + color + '; }' + "\n";
                 sheet.textContent += ruleAdd;
             }
--- a/calendar/base/modules/calRecurrenceUtils.jsm
+++ b/calendar/base/modules/calRecurrenceUtils.jsm
@@ -372,17 +372,17 @@ function recurrenceRule2String(recurrenc
  * @param recurrenceInfo    An item's recurrence info to parse.
  * @return                  An array with two elements: an array of positive
  *                            rules and an array of negative rules.
  */
 function splitRecurrenceRules(recurrenceInfo) {
     var ritems = recurrenceInfo.getRecurrenceItems({});
     var rules = [];
     var exceptions = [];
-    for each (var r in ritems) {
+    for (var r of ritems) {
         if (r.isNegative) {
             exceptions.push(r);
         } else {
             rules.push(r);
         }
     }
     return [rules, exceptions];
 }
@@ -391,16 +391,16 @@ function splitRecurrenceRules(recurrence
  * Check if a recurrence rule's component is valid.
  *
  * @see                     calIRecurrenceRule
  * @param aRule             The recurrence rule to check.
  * @param aArray            An array of component names to check.
  * @return                  Returns true if the rule is valid.
  */
 function checkRecurrenceRule(aRule, aArray) {
-    for each (var comp in aArray) {
+    for (var comp of aArray) {
         var ruleComp = aRule.getComponent(comp, {});
         if (ruleComp && ruleComp.length > 0) {
             return true;
         }
     }
     return false;
 }
--- a/calendar/base/modules/calUtils.jsm
+++ b/calendar/base/modules/calUtils.jsm
@@ -32,17 +32,17 @@ var cal = {
      * @param baseDir     base dir; defaults to calendar-js/
      */
     loadScripts: function cal_loadScripts(scriptNames, scope, baseDir) {
         if (!baseDir) {
             baseDir = __LOCATION__.parent.parent.clone();
             baseDir.append("calendar-js");
         }
 
-        for each (let script in scriptNames) {
+        for (let script of scriptNames) {
             if (!script) {
                 // If the array element is null, then just skip this script.
                 continue;
             }
             let scriptFile = baseDir.clone();
             scriptFile.append(script);
             let scriptUrlSpec = Services.io.newFileURI(scriptFile).spec;
             try {
@@ -115,17 +115,17 @@ var cal = {
                 methods = ["onCalendarAdded", "onCalendarRemoved",
                            "onDefaultCalendarChanged"];
                 break;
             default:
                 methods = [];
                 break;
         }
 
-        for each (let method in methods) {
+        for (let method of methods) {
             if (!(method in template)) {
                 adapter[method] = function() {};
             }
         }
         adapter.QueryInterface = XPCOMUtils.generateQI([iface]);
 
         return adapter;
     },
@@ -882,17 +882,17 @@ var cal = {
 
 // local to this module;
 // will be used to clean up global objects on shutdown
 // some objects have cyclic references due to wrappers
 function shutdownCleanup(obj, prop) {
     if (!shutdownCleanup.mEntries) {
         shutdownCleanup.mEntries = [];
         cal.addShutdownObserver(function() {
-                for each (let entry in shutdownCleanup.mEntries) {
+                for (let entry of shutdownCleanup.mEntries) {
                     if (entry.mProp) {
                         delete entry.mObj[entry.mProp];
                     } else {
                         delete entry.mObj;
                     }
                 }
                 delete shutdownCleanup.mEntries;
             });
--- a/calendar/base/src/calAlarm.js
+++ b/calendar/base/src/calAlarm.js
@@ -64,17 +64,17 @@ calAlarm.prototype = {
         if (this.mImmutable) {
             return;
         }
 
         const objectMembers = ["mAbsoluteDate",
                                "mOffset",
                                "mDuration",
                                "mLastAck"];
-        for each (let member in objectMembers) {
+        for (let member of objectMembers) {
             if (this[member] && this[member].isMutable) {
                 this[member].makeImmutable();
             }
         }
 
         // Properties
         let e = this.mProperties.enumerator;
         while (e.hasMoreElements()) {
@@ -104,39 +104,39 @@ calAlarm.prototype = {
         const arrayMembers = ["mAttendees",
                               "mAttachments"];
 
         const objectMembers = ["mAbsoluteDate",
                                "mOffset",
                                "mDuration",
                                "mLastAck"];
 
-        for each (let member in simpleMembers) {
+        for (let member of simpleMembers) {
             m[member] = this[member];
         }
 
-        for each (let member in arrayMembers) {
+        for (let member of arrayMembers) {
             let newArray = [];
-            for each (let oldElem in this[member]) {
+            for (let oldElem of this[member]) {
                 newArray.push(oldElem.clone());
             }
             m[member] = newArray;
         }
 
-        for each (let member in objectMembers) {
+        for (let member of objectMembers) {
             if (this[member] && this[member].clone) {
                 m[member] = this[member].clone();
             } else {
                 m[member] = this[member];
             }
         }
 
         // X-Props
         m.mProperties = new calPropertyBag();
-        for each (let [name, value] in this.mProperties) {
+        for (let [name, value] of this.mProperties) {
             if (value instanceof Components.interfaces.calIDateTime) {
                 value = value.clone();
             }
 
             m.mProperties.setProperty(name, value);
 
             let propBucket = this.mPropertyParams[name];
             if (propBucket) {
@@ -418,26 +418,26 @@ calAlarm.prototype = {
             comp.addProperty(durationProp);
         }
 
         // Set up attendees (REQUIRED for EMAIL action)
         /* TODO should we be strict here?
         if (this.action == "EMAIL" && !this.getAttendees({}).length) {
             throw Components.results.NS_ERROR_NOT_INITIALIZED;
         } */
-        for each (let attendee in this.getAttendees({})) {
+        for (let attendee of this.getAttendees({})) {
             comp.addProperty(attendee.icalProperty);
         }
 
         /* TODO should we be strict here?
         if (this.action == "EMAIL" && !this.attachments.length) {
             throw Components.results.NS_ERROR_NOT_INITIALIZED;
         } */
 
-        for each (let attachment in this.getAttachments({})) {
+        for (let attachment of this.getAttachments({})) {
             comp.addProperty(attachment.icalProperty);
         }
 
         // Set up summary (REQUIRED for EMAIL)
         if (this.summary || this.action == "EMAIL") {
             let summaryProp = icssvc.createIcalProperty("SUMMARY");
             // Summary needs to have a non-empty value
             summaryProp.value = this.summary ||
@@ -459,17 +459,17 @@ calAlarm.prototype = {
         // Set up lastAck
         if (this.lastAck) {
             let lastAckProp = icssvc.createIcalProperty("X-MOZ-LASTACK");
             lastAckProp.value = this.lastAck;
             comp.addProperty(lastAckProp);
         }
 
         // Set up X-Props. mProperties contains only non-promoted props
-        for (let propName in this.mProperties) {
+        for (let [propName, ] of this.mProperties) {
             let icalprop = icssvc.createIcalProperty(propName);
             icalprop.value = this.mProperties.getProperty(propName);
 
             // Add parameters
             let propBucket = this.mPropertyParams[propName];
             if (propBucket) {
                 for (let paramName in propBucket) {
                     try {
--- a/calendar/base/src/calAlarmMonitor.js
+++ b/calendar/base/src/calAlarmMonitor.js
@@ -131,17 +131,17 @@ calAlarmMonitor.prototype = {
             calAlarmWindow.addWidgetFor(aItem, aAlarm);
         }
     },
 
     window_onLoad: function cAM_window_onLoad() {
         let calAlarmWindow = this.mWindowOpening;
         this.mWindowOpening = null;
         if (this.mAlarms.length > 0) {
-            for each (let [item, alarm] in this.mAlarms) {
+            for (let [item, alarm] of this.mAlarms) {
                 calAlarmWindow.addWidgetFor(item, alarm);
             }
         } else {
             // Uh oh, it seems the alarms were removed even before the window
             // finished loading. Looks like we can close it again
             calAlarmWindow.closeIfEmpty();
         }
     },
--- a/calendar/base/src/calAlarmService.js
+++ b/calendar/base/src/calAlarmService.js
@@ -220,17 +220,17 @@ calAlarmService.prototype = {
         /* Tell people that we're alive so they can start monitoring alarms.
          */
         let notifier = Components.classes["@mozilla.org/embedcomp/appstartup-notifier;1"]
                                  .getService(Components.interfaces.nsIObserver);
         notifier.observe(null, "alarm-service-startup", null);
 
         getCalendarManager().addObserver(this.calendarManagerObserver);
 
-        for each (let calendar in getCalendarManager().getCalendars({})) {
+        for (let calendar of getCalendarManager().getCalendars({})) {
             this.observeCalendar(calendar);
         }
 
         /* set up a timer to update alarms every N hours */
         let timerCallback = {
             alarmService: this,
             notify: function timer_notify() {
                 let now = nowUTC();
@@ -280,17 +280,17 @@ calAlarmService.prototype = {
             this.mUpdateTimer.cancel();
             this.mUpdateTimer = null;
         }
 
         let calmgr = cal.getCalendarManager();
         calmgr.removeObserver(this.calendarManagerObserver);
 
         // Stop observing all calendars. This will also clear the timers.
-        for each (let calendar in calmgr.getCalendars({})) {
+        for (let calendar of calmgr.getCalendars({})) {
             this.unobserveCalendar(calendar);
         }
 
         this.mRangeEnd = null;
 
         Services.obs.removeObserver(this, "profile-after-change");
         Services.obs.removeObserver(this, "xpcom-shutdown");
         Services.obs.removeObserver(this, "wake_notification");
@@ -312,17 +312,17 @@ calAlarmService.prototype = {
         if (cal.isToDo(aItem) && aItem.isCompleted) {
             // If this is a task and it is completed, don't add the alarm.
             return;
         }
 
         let showMissed = Preferences.get("calendar.alarms.showmissed", true);
 
         let alarms = aItem.getAlarms({});
-        for each (let alarm in alarms) {
+        for (let alarm of alarms) {
             let alarmDate = cal.alarms.calculateAlarmDate(aItem, alarm);
 
             if (!alarmDate || alarm.action != "DISPLAY") {
                 // Only take care of DISPLAY alarms with an alarm date.
                 continue;
             }
 
             // Handle all day events.  This is kinda weird, because they don't have
@@ -386,17 +386,17 @@ calAlarmService.prototype = {
             }
         }
     },
 
     removeAlarmsForItem: function cAS_removeAlarmsForItem(aItem) {
         // make sure already fired alarms are purged out of the alarm window:
         this.mObservers.notify("onRemoveAlarmsByItem", [aItem]);
         // Purge alarms specifically for this item (i.e exception)
-        for each (let alarm in aItem.getAlarms({})) {
+        for (let alarm of aItem.getAlarms({})) {
             this.removeTimer(aItem, alarm);
         }
     },
 
     getOccurrencesInRange: function cAS_getOccurrencesInRange(aItem) {
         // We search 1 month in each direction for alarms.  Therefore,
         // we need occurrences between initial start date and 1 month from now
         let until = nowUTC();
@@ -462,20 +462,22 @@ calAlarmService.prototype = {
             // If the calendar map is empty, remove it from the timer map
             if (this.mTimerMap[aItem.calendar.id].toSource() == "({})") {
                 delete this.mTimerMap[aItem.calendar.id];
             }
         }
     },
 
     disposeCalendarTimers: function cAS_removeCalendarTimers(aCalendars) {
-        for each (let calendar in aCalendars) {
+        for (let calendar of aCalendars) {
             if (calendar.id in this.mTimerMap) {
-                for each (let itemTimerMap in this.mTimerMap[calendar.id]) {
-                    for each (let timer in itemTimerMap) {
+                for (let hashId in this.mTimerMap[calendar.id]) {
+                    let itemTimerMap = this.mTimerMap[calendar.id][hashId];
+                    for (let icalString in itemTimerMap) {
+                        let timer = itemTimerMap[icalString];
                         timer.cancel();
                     }
                 }
                 delete this.mTimerMap[calendar.id]
             }
         }
     },
 
@@ -533,17 +535,17 @@ calAlarmService.prototype = {
             }
         };
 
         const calICalendar = Components.interfaces.calICalendar;
         let filter = calICalendar.ITEM_FILTER_COMPLETED_ALL |
                      calICalendar.ITEM_FILTER_CLASS_OCCURRENCES |
                      calICalendar.ITEM_FILTER_TYPE_ALL;
 
-        for each (let calendar in aCalendars) {
+        for (let calendar of aCalendars) {
             // assuming that suppressAlarms does not change anymore until refresh:
             if (!calendar.getProperty("suppressAlarms") &&
                 !calendar.getProperty("disabled")) {
                 this.mLoadedCalendars[calendar.id] = false;
                 calendar.getItems(filter, 0, aStart, aUntil, getListener);
             } else {
                 this.mLoadedCalendars[calendar.id] = true;
                 this.mObservers.notify("onAlarmsLoaded", [calendar]);
--- a/calendar/base/src/calAttachment.js
+++ b/calendar/base/src/calAttachment.js
@@ -95,17 +95,17 @@ calAttachment.prototype = {
     },
     set encoding(aValue) {
         return this.setParameter("ENCODING", aValue);
     },
 
     get icalProperty() {
         let icalatt = cal.getIcsService().createIcalProperty("ATTACH");
 
-        for each (let [key, value] in this.mProperties) {
+        for (let [key, value] of this.mProperties) {
             try {
                 icalatt.setParameter(key, value);
             } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
                 // Illegal values should be ignored, but we could log them if
                 // the user has enabled logging.
                 cal.LOG("Warning: Invalid attachment parameter value " + key + "=" + value);
             }
         }
@@ -117,17 +117,17 @@ calAttachment.prototype = {
     },
 
     set icalProperty(attProp) {
         // Reset the property bag for the parameters, it will be re-initialized
         // from the ical property.
         this.mProperties = new cal.calPropertyBag();
         this.setData(attProp.value);
 
-        for each (let [name, value] in cal.ical.paramIterator(attProp)) {
+        for (let [name, value] of cal.ical.paramIterator(attProp)) {
             this.setParameter(name, value);
         }
     },
 
     get icalString() {
         let comp = this.icalProperty;
         return (comp ? comp.icalString : "");
     },
@@ -155,17 +155,17 @@ calAttachment.prototype = {
     deleteParameter: function (aName) {
         this.mProperties.deleteProperty(aName);
     },
 
     clone: function cA_clone() {
         let newAttachment = new calAttachment();
         newAttachment.mData = this.mData;
         newAttachment.mHashId = this.mHashId;
-        for each (let [name, value] in this.mProperties) {
+        for (let [name, value] of this.mProperties) {
             newAttachment.mProperties.setProperty(name, value);
         }
         return newAttachment;
     },
 
     setData: function setData(aData) {
         // Sets the data and invalidates the hash so it will be recalculated
         this.mHashId = null;
--- a/calendar/base/src/calAttendee.js
+++ b/calendar/base/src/calAttendee.js
@@ -40,21 +40,21 @@ calAttendee.prototype = {
         var a = new calAttendee();
 
         if (this.mIsOrganizer) {
             a.isOrganizer = true;
         }
 
         const allProps = ["id", "commonName", "rsvp", "role",
                           "participationStatus", "userType"];
-        for each (let prop in allProps) {
+        for (let prop of allProps) {
             a[prop] = this[prop];
         }
 
-        for each (let [key, value] in this.mProperties) {
+        for (let [key, value] of this.mProperties) {
             a.setProperty(key, value);
         }
 
         return a;
     },
     // XXX enforce legal values for our properties;
 
     icalAttendeePropMap: [
@@ -70,27 +70,27 @@ calAttendee.prototype = {
 
     // icalatt is a calIcalProperty of type attendee
     set icalProperty (icalatt) {
         this.modify();
         this.id = icalatt.valueAsIcalString;
         this.mIsOrganizer = (icalatt.propertyName == "ORGANIZER");
 
         let promotedProps = { };
-        for each (let prop in this.icalAttendeePropMap) {
+        for (let prop of this.icalAttendeePropMap) {
             this[prop.cal] = icalatt.getParameter(prop.ics);
             // Don't copy these to the property bag.
             promotedProps[prop.ics] = true;
         }
 
         // Reset the property bag for the parameters, it will be re-initialized
         // from the ical property.
         this.mProperties = new calPropertyBag();
 
-        for each (let [name, value] in cal.ical.paramIterator(icalatt)) {
+        for (let [name, value] of cal.ical.paramIterator(icalatt)) {
             if (!promotedProps[name]) {
                 this.setProperty(name, value);
             }
         }
     },
 
     get icalProperty() {
         var icssvc = cal.getIcsService();
@@ -112,17 +112,17 @@ calAttendee.prototype = {
                     icalatt.setParameter(prop.ics, this[prop.cal]);
                 } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
                     // Illegal values should be ignored, but we could log them if
                     // the user has enabled logging.
                     cal.LOG("Warning: Invalid attendee parameter value " + prop.ics + "=" + this[prop.cal]);
                 }
             }
         }
-        for each (let [key, value] in this.mProperties) {
+        for (let [key, value] of this.mProperties) {
             try {
                 icalatt.setParameter(key, value);
             } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
                 // Illegal values should be ignored, but we could log them if
                 // the user has enabled logging.
                 cal.LOG("Warning: Invalid attendee parameter value " + key + "=" + value);
             }
         }
--- a/calendar/base/src/calCachedCalendar.js
+++ b/calendar/base/src/calCachedCalendar.js
@@ -223,17 +223,17 @@ calCachedCalendar.prototype = {
     },
 
     getOfflineAddedItems: function cCC_getOfflineAddedItems(callbackFunc) {
         let this_ = this;
         this_.offlineCachedItems = {};
         let getListener = {
             QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-                for each (let item in aItems) {
+                for (let item of aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_CREATED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
                 this_.getOfflineModifiedItems(callbackFunc);
             }
@@ -242,17 +242,17 @@ calCachedCalendar.prototype = {
                                       0, null, null, getListener);
     },
 
     getOfflineModifiedItems: function cCC_getOfflineModifiedItems(callbackFunc) {
         let this_ = this;
         let getListener = {
             QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-                for each (let item in aItems) {
+                for (let item of aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_MODIFIED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
                 this_.getOfflineDeletedItems(callbackFunc);
             }
@@ -261,17 +261,17 @@ calCachedCalendar.prototype = {
                                       0, null, null, getListener);
     },
 
     getOfflineDeletedItems: function cCC_getOfflineDeletedItems(callbackFunc) {
         let this_ = this;
         let getListener = {
             QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function cCC_oOC_cL_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-                for each (let item in aItems) {
+                for (let item of aItems) {
                     this_.offlineCachedItems[item.hashId] = item;
                     this_.offlineCachedItemFlags[item.hashId] = cICL.OFFLINE_FLAG_DELETED_RECORD;
                 }
             },
 
             onOperationComplete: function cCC_oOC_cL_onOperationComplete(aCalendar, aStatus, aOpType, aId, aDetail) {
                 if (callbackFunc) {
                     callbackFunc();
--- a/calendar/base/src/calCalendarManager.js
+++ b/calendar/base/src/calCalendarManager.js
@@ -59,17 +59,18 @@ calCalendarManager.prototype = {
         if (Preferences.get("calendar.network.multirealm", false)) {
             Services.obs.addObserver(this, "http-on-examine-response", false);
         }
 
         aCompleteListener.onResult(null, Components.results.NS_OK);
     },
 
     shutdown: function ccm_shutdown(aCompleteListener) {
-        for each (var calendar in this.mCache) {
+        for (let id in this.mCache) {
+            let calendar = this.mCache[id];
             calendar.removeObserver(this.mCalObservers[calendar.id]);
         }
 
         this.cleanupOfflineObservers();
 
         Services.obs.removeObserver(this, "http-on-modify-request");
 
         AddonManager.removeAddonListener(gCalendarManagerAddonListener);
@@ -93,24 +94,25 @@ calCalendarManager.prototype = {
         Services.obs.removeObserver(this, "network:offline-status-changed");
     },
 
     observe: function ccm_observe(aSubject, aTopic, aData) {
         switch (aTopic) {
             case "timer-callback":
                 // Refresh all the calendars that can be refreshed.
                 var cals = this.getCalendars({});
-                for each (var calendar in cals) {
+                for (var calendar of cals) {
                     if (!calendar.getProperty("disabled") && calendar.canRefresh) {
                         calendar.refresh();
                     }
                 }
                 break;
             case "network:offline-status-changed":
-                for each (var calendar in this.mCache) {
+                for (var id in this.mCache) {
+                    let calendar = this.mCache[id];
                     if (calendar instanceof calCachedCalendar) {
                         calendar.onOfflineStatusChanged(aData == "offline");
                     }
                 }
                 break;
             case "http-on-examine-response":
                 try {
                     let channel = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
@@ -294,17 +296,18 @@ calCalendarManager.prototype = {
                             Preferences.set(getPrefBranchFor(id) + name, value);
                             break;
                     }
                 }
                 selectPrefs.reset();
             }
 
             let sortOrderAr = [];
-            for each (let s in sortOrder) {
+            for (let id in sortOrder) {
+                let s = sortOrder[id];
                 sortOrderAr.push(s);
             }
             Preferences.set("calendar.list.sortOrder", sortOrderAr.join(" "));
             flushPrefs();
 
         } finally {
             selectPrefs.reset();
             selectCalendars.reset();
@@ -639,30 +642,31 @@ calCalendarManager.prototype = {
         } else {
             return null;
         }
     },
 
     getCalendars: function cmgr_getCalendars(count) {
         this.assureCache();
         var calendars = [];
-        for each (var calendar in this.mCache) {
+        for (var id in this.mCache) {
+            let calendar = this.mCache[id];
             calendars.push(calendar);
         }
         count.value = calendars.length;
         return calendars;
     },
 
     assureCache: function cmgr_assureCache() {
         if (!this.mCache) {
             this.mCache = {};
             this.mCalObservers = {};
 
             let allCals = {};
-            for each (let key in Services.prefs.getChildList(REGISTRY_BRANCH)) { // merge down all keys
+            for (let key of Services.prefs.getChildList(REGISTRY_BRANCH)) { // merge down all keys
                 allCals[key.substring(0, key.indexOf(".", REGISTRY_BRANCH.length))] = true;
             }
 
             for (let calBranch in allCals) {
                 let id = calBranch.substring(REGISTRY_BRANCH.length);
                 let ctype = Preferences.get(calBranch + ".type", null);
                 let curi = Preferences.get(calBranch + ".uri", null);
 
@@ -700,17 +704,18 @@ calCalendarManager.prototype = {
                     this.setupCalendar(calendar);
                 } catch (exc) {
                     cal.ERROR("Can't create calendar for " + id + " (" + ctype + ", " + curi + "): " + exc);
                 }
             }
 
             // do refreshing in a second step, when *all* calendars are already available
             // via getCalendars():
-            for each (let calendar in this.mCache) {
+            for (let id in this.mCache) {
+                let calendar = this.mCache[id];
                 if (!calendar.getProperty("disabled") && calendar.canRefresh) {
                     calendar.refresh();
                 }
             }
         }
     },
 
     getCalendarPref_: function(calendar, name) {
@@ -869,17 +874,17 @@ calMgrCalendarObserver.prototype = {
                                 "auto-enabled",
                                 "cache.enabled",
                                 "refreshInterval",
                                 "suppressAlarms",
                                 "calendar-main-in-composite",
                                 "calendar-main-default",
                                 "readOnly",
                                 "imip.identity.key"];
-            for each (let prop in propsToCopy ) {
+            for (let prop of propsToCopy) {
               newCal.setProperty(prop,
                                  aCalendar.getProperty(prop));
             }
 
             if (initialSortOrderPos != null) {
                 newCal.setProperty("initialSortOrderPos",
                                    initialSortOrderPos);
             }
@@ -1064,18 +1069,17 @@ var gCalendarManagerAddonListener = {
         }
     },
 
     queryUninstallProvider: function(aAddon) {
         const uri = "chrome://calendar/content/calendar-providerUninstall-dialog.xul";
         const features = "chrome,titlebar,resizable,modal";
         let calMgr = cal.getCalendarManager();
         let affectedCalendars =
-            [ calendar for each (calendar in calMgr.getCalendars({}))
-              if (calendar.providerID == aAddon.id) ];
+            calMgr.getCalendars({}).filter(calendar => calendar.providerID == aAddon.id);
         if (!affectedCalendars.length) {
             // If no calendars are affected, then everything is fine.
             return true;
         }
 
         let args = { shouldUninstall: false, extension: aAddon };
 
         // Now find a window. The best choice would be the most recent
--- a/calendar/base/src/calDefaultACLManager.js
+++ b/calendar/base/src/calDefaultACLManager.js
@@ -76,17 +76,17 @@ calDefaultCalendarACLEntry.prototype = {
         let identities = [];
         cal.calIterateEmailIdentities(function (id, ac) { identities.push(id); });
         aCount.value = identities.length;
         return identities;
     },
 
     getUserAddresses: function calDefaultCalendarACLEntry_getUserAddresses(aCount) {
         let identities = this.getUserIdentities(aCount);
-        let addresses = [ id.email for each (id in identities) ];
+        let addresses = identities.map(id => id.email);
         return addresses;
     },
 
     getUserIdentities: function calDefaultCalendarACLEntry_getUserIdentities(aCount) {
         let identity = cal.getEmailIdentityOfCalendar(this.mCalendar);
         if (identity) {
             aCount.value = 1;
             return [identity];
--- a/calendar/base/src/calFilter.js
+++ b/calendar/base/src/calFilter.js
@@ -871,17 +871,17 @@ calFilter.prototype = {
 
             onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
                 let items;
                 if (props.occurrences == props.FILTER_OCCURRENCES_PAST_AND_NEXT) {
                     // with the FILTER_OCCURRENCES_PAST_AND_NEXT occurrence filter we will
                     // get parent items returned here, so we need to let the getOccurrences
                     // function handle occurrence expansion.
                     items = [];
-                    for each (let item in aItems) {
+                    for (let item of aItems) {
                         items = items.concat(self.getOccurrences(item));
                     }
                 } else {
                     // with other occurrence filters the calICalendar.getItems() function will
                     // return expanded occurrences appropriately, we only need to filter them.
                     items = self.filterItems(aItems);
                 }
 
--- a/calendar/base/src/calIcsParser.js
+++ b/calendar/base/src/calIcsParser.js
@@ -58,17 +58,17 @@ calIcsParser.prototype = {
                 state.submit(subComp);
             }
             calComp = rootComp.getNextSubcomponent("VCALENDAR");
         }
 
         state.join(function() {
             let fakedParents = {};
             // tag "exceptions", i.e. items with rid:
-            for each (let item in state.excItems) {
+            for (let item of state.excItems) {
                 let parent = state.uid2parent[item.id];
 
                 if (!parent) { // a parentless one, fake a master and override it's occurrence
                     parent = isEvent(item) ? createEvent() : createTodo();
                     parent.id = item.id;
                     parent.setProperty("DTSTART", item.recurrenceId);
                     parent.setProperty("X-MOZ-FAKED-MASTER", "1"); // this tag might be useful in the future
                     parent.recurrenceInfo = cal.createRecurrenceInfo(parent);
--- a/calendar/base/src/calIcsSerializer.js
+++ b/calendar/base/src/calIcsSerializer.js
@@ -62,20 +62,20 @@ calIcsSerializer.prototype = {
 
     getIcalComponent: function is_getIcalComponent() {
         let calComp = getIcsService().createIcalComponent("VCALENDAR");
         calSetProdidVersion(calComp);
 
         // xxx todo: think about that the below code doesn't clone the properties/components,
         //           thus ownership is moved to returned VCALENDAR...
 
-        for each (let prop in this.mProperties) {
+        for (let prop of this.mProperties) {
             calComp.addProperty(prop);
         }
-        for each (let comp in this.mComponents) {
+        for (let comp of this.mComponents) {
             calComp.addSubcomponent(comp);
         }
 
         for (let item in cal.itemIterator(this.mItems)) {
             calComp.addSubcomponent(item.icalComponent);
         }
 
         return calComp;
--- a/calendar/base/src/calItemBase.js
+++ b/calendar/base/src/calItemBase.js
@@ -192,30 +192,30 @@ calItemBase.prototype = {
 
         // make all our components immutable
         if (this.mRecurrenceInfo)
             this.mRecurrenceInfo.makeImmutable();
 
         if (this.mOrganizer)
             this.mOrganizer.makeImmutable();
         if (this.mAttendees) {
-            for each (let att in this.mAttendees) {
+            for (let att of this.mAttendees) {
                 att.makeImmutable();
             }
         }
 
-        for each (let [propKey, propValue] in this.mProperties) {
+        for (let [propKey, propValue] of this.mProperties) {
             if (propValue instanceof Components.interfaces.calIDateTime &&
                 propValue.isMutable) {
                 propValue.makeImmutable();
             }
         }
 
         if (this.mAlarms) {
-            for each (let alarm in this.mAlarms) {
+            for (let alarm of this.mAlarms) {
                 alarm.makeImmutable();
             }
         }
 
         if (this.mAlarmLastAck) {
             this.mAlarmLastAck.makeImmutable();
         }
 
@@ -257,22 +257,22 @@ calItemBase.prototype = {
 
         let org = this.organizer;
         if (org) {
             org = org.clone();
         }
         m.mOrganizer = org;
 
         m.mAttendees = [];
-        for each (let att in this.getAttendees({})) {
+        for (let att of this.getAttendees({})) {
             m.mAttendees.push(att.clone());
         }
 
         m.mProperties = new calPropertyBag();
-        for each (let [name, value] in this.mProperties) {
+        for (let [name, value] of this.mProperties) {
             if (value instanceof Components.interfaces.calIDateTime) {
                 value = value.clone();
             }
 
             m.mProperties.setProperty(name, value);
 
             let propBucket = this.mPropertyParams[name];
             if (propBucket) {
@@ -280,29 +280,29 @@ calItemBase.prototype = {
                 for (let param in propBucket) {
                     newBucket[param] = propBucket[param];
                 }
                 m.mPropertyParams[name] = newBucket;
             }
         }
 
         m.mAttachments = [];
-        for each (let att in this.getAttachments({})) {
+        for (let att of this.getAttachments({})) {
             m.mAttachments.push(att.clone());
         }
 
         m.mRelations = [];
-        for each (let rel in this.getRelations({})) {
+        for (let rel of this.getRelations({})) {
             m.mRelations.push(rel.clone());
         }
 
         m.mCategories = this.getCategories({});
 
         m.mAlarms = [];
-        for each (let alarm in this.getAlarms({})) {
+        for (let alarm of this.getAlarms({})) {
             // Clone alarms into new item, assume the alarms from the old item
             // are valid and don't need validation.
             m.mAlarms.push(alarm.clone());
         }
 
         let alarmLastAck = this.alarmLastAck;
         if (alarmLastAck) {
             alarmLastAck = alarmLastAck.clone();
@@ -514,17 +514,17 @@ calItemBase.prototype = {
             return [];
         }
     },
 
     // calIAttendee getAttendeeById(in AUTF8String id);
     getAttendeeById: function cIB_getAttendeeById(id) {
         var attendees = this.getAttendees({});
         var lowerCaseId = id.toLowerCase();
-        for each (var attendee in attendees) {
+        for (var attendee of attendees) {
             // This match must be case insensitive to deal with differing
             // cases of things like MAILTO:
             if (attendee.id.toLowerCase() == lowerCaseId) {
                 return attendee;
             }
         }
         return null;
     },
@@ -914,17 +914,17 @@ calItemBase.prototype = {
      * @param icalcomp      The ical component to read.
      * @param promoted      The map of promoted properties.
      */
     importUnpromotedProperties: function cIB_importUnpromotedProperties(icalcomp, promoted) {
         for (let prop in cal.ical.propertyIterator(icalcomp)) {
             let propName = prop.propertyName;
             if (!promoted[propName]) {
                 this.setProperty(propName, prop.value);
-                for each (let [paramName, paramValue] in cal.ical.paramIterator(prop)) {
+                for (let [paramName, paramValue] of cal.ical.paramIterator(prop)) {
                     if (!(propName in this.mPropertyParams)) {
                         this.mPropertyParams[propName] = {};
                     }
                     this.mPropertyParams[propName][paramName] = paramValue;
                 }
             }
         }
     },
@@ -962,42 +962,44 @@ calItemBase.prototype = {
 
         this.mapPropsToICS(icalcomp, this.icsBasePropMap);
 
         let org = this.organizer;
         if (org) {
             icalcomp.addProperty(org.icalProperty);
         }
 
-        for each (let attendee in this.getAttendees({})) {
+        for (let attendee of this.getAttendees({})) {
             icalcomp.addProperty(attendee.icalProperty);
         }
 
-        for each (let attachment in this.getAttachments({})) {
+        for (let attachment of this.getAttachments({})) {
             icalcomp.addProperty(attachment.icalProperty);
         }
 
-        for each (let relation in this.getRelations({})) {
+        for (let relation of this.getRelations({})) {
             icalcomp.addProperty(relation.icalProperty);
         }
 
         if (this.mRecurrenceInfo) {
-            for each (let ritem in this.mRecurrenceInfo.getRecurrenceItems({})) {
+            for (let ritem of this.mRecurrenceInfo.getRecurrenceItems({})) {
                 icalcomp.addProperty(ritem.icalProperty);
             }
         }
 
-        for each (let cat in this.getCategories({})) {
+        for (let cat of this.getCategories({})) {
             let catprop = icssvc.createIcalProperty("CATEGORIES");
             catprop.value = cat;
             icalcomp.addProperty(catprop);
         }
 
-        for each (let alarm in this.mAlarms) {
-            icalcomp.addSubcomponent(alarm.icalComponent);
+        if (this.mAlarms) {
+            for (let alarm of this.mAlarms) {
+                icalcomp.addSubcomponent(alarm.icalComponent);
+            }
         }
 
         let alarmLastAck = this.alarmLastAck;
         if (alarmLastAck) {
             let lastAck = cal.getIcsService().createIcalProperty("X-MOZ-LASTACK");
             // - should we further ensure that those are UTC or rely on calAlarmService doing so?
             lastAck.value = alarmLastAck.icalString;
             icalcomp.addProperty(lastAck);
--- a/calendar/base/src/calItipItem.js
+++ b/calendar/base/src/calItipItem.js
@@ -140,17 +140,17 @@ calItipItem.prototype = {
             }
         }
 
         // We set both methods now for safety's sake. It's the ItipProcessor's
         // responsibility to properly ascertain what the correct response
         // method is (using user feedback, prefs, etc.) for the given
         // receivedMethod.  The RFC tells us to treat items without a METHOD
         // as if they were METHOD:REQUEST.
-        for each (let prop in parser.getProperties({})) {
+        for (let prop of parser.getProperties({})) {
             if (prop.propertyName == "METHOD") {
                 this.mReceivedMethod = prop.value;
                 this.mResponseMethod = prop.value;
                 break;
             }
         }
 
         this.mIsInitialized = true;
@@ -187,17 +187,17 @@ calItipItem.prototype = {
      * way, which is a current limitation of the spec.
      */
     setAttendeeStatus: function ciiSAS(aAttendeeId, aStatus) {
         // Append "mailto:" to the attendee if it is missing it.
         if (!aAttendeeId.match(/^mailto:/i)) {
             aAttendeeId = ("mailto:" + aAttendeeId);
         }
 
-        for each (let item in this.mItemList) {
+        for (let item of this.mItemList) {
             let attendee = item.getAttendeeById(aAttendeeId);
             if (attendee) {
                 // Replies should not have the RSVP property.
                 // XXX BUG 351589: workaround for updating an attendee
                 item.removeAttendee(attendee);
                 attendee = attendee.clone();
                 attendee.rsvp = null;
                 item.addAttendee(attendee);
--- a/calendar/base/src/calRecurrenceInfo.js
+++ b/calendar/base/src/calRecurrenceInfo.js
@@ -54,17 +54,17 @@ calRecurrenceInfo.prototype = {
         if (this.mImmutable) {
             throw Components.results.NS_ERROR_OBJECT_IS_IMMUTABLE;
         }
     },
     ensureSortedRecurrenceRules: function cRI_ensureSortedRecurrenceRules() {
         if (!this.mPositiveRules || !this.mNegativeRules) {
             this.mPositiveRules = [];
             this.mNegativeRules = [];
-            for each (var ritem in this.mRecurrenceItems) {
+            for (var ritem of this.mRecurrenceItems) {
                 if (ritem.isNegative) {
                     this.mNegativeRules.push(ritem);
                 } else {
                     this.mPositiveRules.push(ritem);
                 }
             }
         }
     },
@@ -75,37 +75,38 @@ calRecurrenceInfo.prototype = {
     get isMutable() {
         return !this.mImmutable;
     },
     makeImmutable: function cRI_makeImmutable() {
         if (this.mImmutable) {
             return;
         }
 
-        for each (let ritem in this.mRecurrenceItems) {
+        for (let ritem of this.mRecurrenceItems) {
             if (ritem.isMutable) {
                 ritem.makeImmutable();
             }
         }
 
-        for each (let item in this.mExceptionMap) {
+        for (let ex in this.mExceptionMap) {
+            let item = this.mExceptionMap[ex];
             if (item.isMutable) {
                 item.makeImmutable();
             }
         }
 
         this.mImmutable = true;
     },
 
     clone: function cRI_clone() {
         var cloned = new calRecurrenceInfo();
         cloned.mBaseItem = this.mBaseItem;
 
         var clonedItems = [];
-        for each (var ritem in this.mRecurrenceItems) {
+        for (var ritem of this.mRecurrenceItems) {
             clonedItems.push(ritem.clone());
         }
         cloned.mRecurrenceItems = clonedItems;
 
         var clonedExceptions = {};
         for (var exitem in this.mExceptionMap) {
             clonedExceptions[exitem] = this.mExceptionMap[exitem].cloneShallow(this.mBaseItem);
         }
@@ -121,25 +122,26 @@ calRecurrenceInfo.prototype = {
         return this.mBaseItem;
     },
     set item(value) {
         this.ensureMutable();
 
         value = calTryWrappedJSObject(value);
         this.mBaseItem = value;
         // patch exception's parentItem:
-        for each (let exitem in this.mExceptionMap) {
+        for (let ex in this.mExceptionMap) {
+            let exitem = this.mExceptionMap[ex];
             exitem.parentItem = value;
         }
     },
 
     get isFinite() {
         this.ensureBaseItem();
 
-        for each (let ritem in this.mRecurrenceItems) {
+        for (let ritem of this.mRecurrenceItems) {
             if (!ritem.isFinite) {
                 return false;
             }
         }
         return true;
     },
 
     getRecurrenceItems: function cRI_getRecurrenceItems(aCount) {
@@ -261,33 +263,33 @@ calRecurrenceInfo.prototype = {
 
         var nextOccurrences = [];
         var invalidOccurrences;
         var negMap = {};
         var minOccRid;
 
         // Go through all negative rules to create a map of occurrences that
         // should be skipped when going through occurrences.
-        for each (var ritem in this.mNegativeRules) {
+        for (var ritem of this.mNegativeRules) {
             // TODO Infinite rules (i.e EXRULE) are not taken into account,
             // because its very performance hungry and could potentially
             // lead to a deadlock (i.e RRULE is canceled out by an EXRULE).
             // This is ok for now, since EXRULE is deprecated anyway.
             if (ritem.isFinite) {
                 // Get all occurrences starting at our recurrence start date.
                 // This is fine, since there will never be an EXDATE that
                 // occurrs before the event started and its illegal to EXDATE an
                 // RDATE.
                 var rdates = ritem.getOccurrences(startDate,
                                                   startDate,
                                                   null,
                                                   0,
                                                   {});
                 // Map all negative dates.
-                for each (var r in rdates) {
+                for (var r of rdates) {
                     negMap[getRidKey(r)] = true;
                 }
             } else {
                 WARN("Item '" + this.mBaseItem.title + "'" +
                      (this.mBaseItem.calendar ? " (" + this.mBaseItem.calendar.name + ")" : "") +
                      " has an infinite negative rule (EXRULE)");
             }
         }
@@ -376,17 +378,18 @@ calRecurrenceInfo.prototype = {
 
         // Since we need to compare occurrences by date, save the rid found
         // above also as a date. This works out because above we skipped
         // exceptions.
         var minOccDate = minOccRid;
 
         // Scan exceptions for any dates earlier than the above found
         // minOccDate, but still after aTime.
-        for each (var exc in this.mExceptionMap) {
+        for (var ex in this.mExceptionMap) {
+            let exc = this.mExceptionMap[ex];
             var start = exc.recurrenceStartDate;
             if (start.compare(aTime) > 0 &&
                 (!minOccDate || start.compare(minOccDate) <= 0)) {
                 // This exception is earlier, save its rid (for getting the
                 // occurrence later on) and its date (for comparing to other
                 // exceptions).
                 minOccRid = exc.recurrenceId;
                 minOccDate = start;
@@ -483,17 +486,17 @@ calRecurrenceInfo.prototype = {
         var maxCount;
         if (rangeStart && rangeEnd) {
             maxCount = 0;
         } else {
             maxCount = aMaxCount;
         }
 
         // Apply positive rules
-        for each (let ritem in this.mPositiveRules) {
+        for (let ritem of this.mPositiveRules) {
             var cur_dates = ritem.getOccurrences(startDate,
                                                  searchStart,
                                                  rangeEnd,
                                                  maxCount, {});
             if (cur_dates.length == 0) {
                 continue;
             }
 
@@ -524,30 +527,30 @@ calRecurrenceInfo.prototype = {
                 // TODO if cur_dates[] is also sorted, then this binary
                 // search could be optimized further
                 binaryInsert(dates, { id: date, rstart: date }, ridDateSortComptor);
                 occurrenceMap[dateKey] = true;
             }
         }
 
         // Apply negative rules
-        for each (let ritem in this.mNegativeRules) {
+        for (let ritem of this.mNegativeRules) {
             var cur_dates = ritem.getOccurrences(startDate,
                                                  searchStart,
                                                  rangeEnd,
                                                  maxCount, {});
             if (cur_dates.length == 0) {
                 continue;
             }
 
             // XXX: i'm pretty sure negative dates can't really have exceptions
             // (like, you can't make a date "real" by defining an RECURRENCE-ID which
             // is an EXDATE, and then giving it a real DTSTART) -- so we don't
             // check exceptions here
-            for each (let dateToRemove in cur_dates) {
+            for (let dateToRemove of cur_dates) {
                 let dateToRemoveKey = getRidKey(dateToRemove);
                 if (dateToRemove.isDate) {
                     // As decided in bug 734245, an EXDATE of type DATE shall also match a DTSTART of type DATE-TIME
                     let toRemove = [];
                     for (let occurenceKey in occurrenceMap) {
                         if (occurrenceMap[occurenceKey] && occurenceKey.substring(0,8) == dateToRemoveKey) {
                             dates = dates.filter(function (d) { return d.id.compare(dateToRemove) != 0; });
                             toRemove.push(occurenceKey)
@@ -726,17 +729,18 @@ calRecurrenceInfo.prototype = {
         this.ensureBaseItem();
         delete this.mExceptionMap[getRidKey(aRecurrenceId)];
     },
 
     getExceptionIds: function cRI_getExceptionIds(aCount) {
         this.ensureBaseItem();
 
         var ids = [];
-        for each (var item in this.mExceptionMap) {
+        for (let ex in this.mExceptionMap) {
+            let item = this.mExceptionMap[ex];
             ids.push(item.recurrenceId);
         }
 
         aCount.value = ids.length;
         return ids;
     },
 
     // changing the startdate of an item needs to take exceptions into account.
@@ -755,17 +759,17 @@ calRecurrenceInfo.prototype = {
         // convert both dates to UTC since subtractDate is not timezone aware.
         let timeDiff = aNewStartTime.getInTimezone(UTC()).subtractDate(aOldStartTime.getInTimezone(UTC()));
 
         let rdates = {};
 
         // take RDATE's and EXDATE's into account.
         const kCalIRecurrenceDate = Components.interfaces.calIRecurrenceDate;
         let ritems = this.getRecurrenceItems({});
-        for each (let ritem in ritems) {
+        for (let ritem of ritems) {
             let rDateInstance = cal.wrapInstance(ritem, kCalIRecurrenceDate);
             let rRuleInstance = cal.wrapInstance(ritem, Components.interfaces.calIRecurrenceRule);
             if (rDateInstance) {
                 ritem = rDateInstance;
                 let date = ritem.date;
                 date.addDuration(timeDiff);
                 if (!ritem.isNegative) {
                     rdates[getRidKey(date)] = date;
@@ -780,36 +784,37 @@ calRecurrenceInfo.prototype = {
                         ritem.untilDate = untilDate;
                     }
                 }
             }
         }
 
         let startTimezone = aNewStartTime.timezone;
         let modifiedExceptions = [];
-        for each (let exid in this.getExceptionIds({})) {
+        for (let exid of this.getExceptionIds({})) {
             let ex = this.getExceptionFor(exid);
             if (ex) {
                 ex = ex.clone();
                 // track RECURRENCE-IDs in DTSTART's or RDATE's timezone,
                 // otherwise those won't match any longer w.r.t DST:
                 let rid = ex.recurrenceId;
                 let rdate = rdates[getRidKey(rid)];
                 rid = rid.getInTimezone(rdate ? rdate.timezone : startTimezone);
                 rid.addDuration(timeDiff);
                 ex.recurrenceId = rid;
                 cal.shiftItem(ex, timeDiff);
                 modifiedExceptions.push(ex);
                 this.removeExceptionFor(exid);
             }
         }
-        for each (let modifiedEx in modifiedExceptions) {
+        for (let modifiedEx of modifiedExceptions) {
             this.modifyException(modifiedEx, true);
         }
     },
 
     onIdChange: function cRI_onIdChange(aNewId) {
         // patch all overridden items' id:
-        for each (let item in this.mExceptionMap) {
+        for (let ex in this.mExceptionMap) {
+            let item = this.mExceptionMap[ex];
             item.id = aNewId;
         }
     }
 };
--- a/calendar/base/src/calRelation.js
+++ b/calendar/base/src/calRelation.js
@@ -55,17 +55,17 @@ calRelation.prototype = {
         if (this.mId) {
             icalatt.value = this.mId;
         }
 
         if (this.mType) {
             icalatt.setParameter("RELTYPE", this.mType);
         }
 
-        for each (let [key, value] in this.mProperties) {
+        for (let [key, value] of this.mProperties) {
             try {
                 icalatt.setParameter(key, value);
             } catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
                 // Illegal values should be ignored, but we could log them if
                 // the user has enabled logging.
                 cal.LOG("Warning: Invalid relation property value " + key + "=" + value);
             }
         }
@@ -75,17 +75,17 @@ calRelation.prototype = {
     set icalProperty(attProp) {
         // Reset the property bag for the parameters, it will be re-initialized
         // from the ical property.
         this.mProperties = new calPropertyBag();
 
         if (attProp.value) {
             this.mId = attProp.value;
         }
-        for each (let [name, value] in cal.ical.paramIterator(attProp)) {
+        for (let [name, value] of cal.ical.paramIterator(attProp)) {
             if (name == "RELTYPE") {
                 this.mType = value;
                 continue;
             }
 
             this.setParameter(name, value);
         }
     },
@@ -114,14 +114,14 @@ calRelation.prototype = {
     deleteParameter: function (aName) {
         return this.mProperties.deleteProperty(aName);
     },
 
     clone: function cR_clone() {
         let newRelation = new calRelation();
         newRelation.mId = this.mId;
         newRelation.mType = this.mType;
-        for each (let [name, value] in this.mProperties) {
+        for (let [name, value] of this.mProperties) {
             newRelation.mProperties.setProperty(name, value);
         }
         return newRelation;
     }
 };
--- a/calendar/base/src/calTimezoneService.js
+++ b/calendar/base/src/calTimezoneService.js
@@ -691,17 +691,17 @@ function guessSystemTimezone() {
 
     // Second, give priority to "likelyTimezone"s if provided by locale.
     try {
         // The likelyTimezone property is a comma-separated list of
         // ZoneInfo timezone ids.
         const bundleTZString =
             calProperties.GetStringFromName("likelyTimezone");
         const bundleTZIds = bundleTZString.split(/\s*,\s*/);
-        for each (var bareTZId in bundleTZIds) {
+        for (var bareTZId of bundleTZIds) {
             var tzId = bareTZId;
             try {
                 var score = checkTZ(tzId);
 
                 switch (score) {
                 case 0:
                     break;
                 case 1: case 2:
--- a/calendar/base/src/calUtils.js
+++ b/calendar/base/src/calUtils.js
@@ -300,17 +300,17 @@ function attendeeMatchesAddresses(anAtte
         // Try getting the email through the EMAIL property.
         let emailProp = anAttendee.getProperty("EMAIL");
         if (emailProp) {
             attId = emailProp;
         }
     }
 
     attId = attId.toLowerCase().replace(/^mailto:/, "");
-    for each (let address in addresses) {
+    for (let address of addresses) {
         if (attId == address.toLowerCase().replace(/^mailto:/, "")) {
             return true;
         }
     }
 
     return false;
 }
 
@@ -560,17 +560,17 @@ function getPrefCategoriesArray() {
  */
 function setupDefaultCategories() {
     // First, set up the category names
     let categories = calGetString("categories", "categories2");
     Preferences.set("calendar.categories.names", categories);
 
     // Now, initialize the category default colors
     let categoryArray = categoriesStringToArray(categories);
-    for each (let category in categoryArray) {
+    for (let category of categoryArray) {
         let prefName = formatStringForCSSRule(category);
         Preferences.set("calendar.category.color." + prefName,
                         hashColor(category));
     }
 
     // Return the list of categories for further processing
     return categories;
 }
@@ -799,19 +799,21 @@ function doQueryInterface(aSelf, aProto,
         if (aIID.equals(Components.interfaces.nsIClassInfo)) {
             return aClassInfo;
         }
         if (!aList) {
             aList = aClassInfo.getInterfaces({});
         }
     }
 
-    for each (var iid in aList) {
-        if (aIID.equals(iid)) {
-            return aSelf;
+    if (aList) {
+        for (var iid of aList) {
+            if (aIID.equals(iid)) {
+                return aSelf;
+            }
         }
     }
 
     if (aIID.equals(Components.interfaces.nsISupports)) {
         return aSelf;
     }
 
     if (aProto) {
@@ -1592,18 +1594,20 @@ calPropertyBag.prototype = {
         aOutValues.value = values;
     },
     deleteProperty: function cpb_deleteProperty(aName) {
         delete this.mData[aName];
     },
     get enumerator() {
         return new calPropertyBagEnumerator(this);
     },
-    __iterator__: function cpb_iterator(aWantKeys) {
-        return Iterator(this.mData, aWantKeys);
+    [Symbol.iterator]: function* cpb_iterator() {
+        for (let name of Object.keys(this.mData)) {
+            yield [name, this.mData[name]];
+        }
     }
 };
 // implementation part of calPropertyBag
 function calPropertyBagEnumerator(bag) {
     this.mIndex = 0;
     this.mBag = bag;
     this.mKeys = [ key for (key in bag.mData) ];
 }
@@ -1684,17 +1688,17 @@ function compareItemContent(aFirstItem, 
     let ignoreParams = aIgnoreParams ||
         { "ATTENDEE": ["CN"], "ORGANIZER": ["CN"] };
     for (let x in ignoreParams) {
         ignoreParams[x] = arr2hash(ignoreParams[x]);
     }
 
     function arr2hash(arr) {
         let hash = {};
-        for each (let x in arr) {
+        for (let x of arr) {
             hash[x] = true;
         }
         return hash;
     }
 
     // This doesn't have to be super correct rfc5545, it just needs to be
     // in the same order
     function normalizeComponent(comp) {
@@ -1708,22 +1712,21 @@ function compareItemContent(aFirstItem, 
             normalizeComponent(subcomp)
             for (subcomp in cal.ical.subcomponentIterator(comp))
         ].sort();
 
         return comp.componentType + props.join("\r\n") + comps.join("\r\n");
     }
 
     function normalizeProperty(prop) {
-        let params = [
-            k + "=" + v
-            for each ([k,v] in cal.ical.paramIterator(prop))
-            if (!(prop.propertyName in ignoreParams) ||
-            !(k in ignoreParams[prop.propertyName]))
-        ].sort();
+        let params = [...cal.ical.paramIterator(prop)].
+            filter(([k, v]) => !(prop.propertyName in ignoreParams) ||
+                   !(k in ignoreParams[prop.propertyName])).
+            map(([k, v]) => k + "=" + v).
+            sort();
 
         return prop.propertyName + ";" +
                params.join(";") + ":" +
                prop.valueAsIcalString;
     }
 
     return normalizeComponent(aFirstItem.icalComponent) ==
            normalizeComponent(aSecondItem.icalComponent);
--- a/calendar/import-export/calHtmlExport.js
+++ b/calendar/import-export/calHtmlExport.js
@@ -52,17 +52,17 @@ calHtmlExporter.prototype = {
             }
             let start_b = b[cal.calGetStartDateProp(b)];
             if (!start_b) {
                 return 1;
             }
             return start_a.compare(start_b);
         });
 
-        for each (let item in aItems) {
+        for (let item of aItems) {
             let itemNode = document.getElementById("item-template").cloneNode(true);
             itemNode.removeAttribute("id");
 
             let setupTextRow = function(classKey, propValue, prefixKey) {
                 if (propValue) {
                     let prefix = cal.calGetString("calendar", prefixKey);
                     itemNode.querySelector("." + classKey + "key").textContent = prefix;
                     itemNode.querySelector("." + classKey).textContent = propValue;
--- a/calendar/import-export/calMonthGridPrinter.js
+++ b/calendar/import-export/calMonthGridPrinter.js
@@ -51,17 +51,17 @@ calMonthPrinter.prototype = {
             for (let current = startDate.clone();
                  weekInfoService.getEndOfWeek(current.endOfMonth).compare(endDate) < 0;
                  current.month += 1)
             {
                 this.setupMonth(document, current, dayTable);
             }
         }
 
-        for each (let item in aItems) {
+        for (let item of aItems) {
             let itemStartDate = item[cal.calGetStartDateProp(item)] || item[cal.calGetEndDateProp(item)];
             let itemEndDate = item[cal.calGetEndDateProp(item)] || item[cal.calGetStartDateProp(item)];
 
             if (!itemStartDate && !itemEndDate) {
                 cal.print.addItemToDayboxNodate(document, item);
                 continue;
             }
             itemStartDate = itemStartDate.getInTimezone(defaultTimezone);
--- a/calendar/import-export/calOutlookCSVImportExport.js
+++ b/calendar/import-export/calOutlookCSVImportExport.js
@@ -459,17 +459,17 @@ calOutlookCSVExporter.prototype = {
         headers.push(localeEn['headPrivate']);
         headers = headers.map(function(v) {
             return '"' + v + '"';
         });
         str = headers.join(',');
         str += exportLineEnding;
         aStream.write(str, str.length);
 
-        for each (let item in aItems) {
+        for (let item of aItems) {
             if (!cal.isEvent(item)) {
                 // XXX TODO: warn the user (once) that tasks are not supported
                 // (bug 336175)
                 continue;
             }
             let line = [];
             line.push(item.title);
             line.push(dateString(item.startDate));
--- a/calendar/import-export/calWeekPrinter.js
+++ b/calendar/import-export/calWeekPrinter.js
@@ -44,17 +44,17 @@ calWeekPrinter.prototype = {
 
         // Make sure to create tables from start to end, if passed
         if (aStart && aEnd) {
             for (let current = weekInfoService.getStartOfWeek(aStart); current.compare(aEnd) < 0; current.day += 7) {
                 this.setupWeek(document, current, dayTable);
             }
         }
 
-        for each (let item in aItems) {
+        for (let item of aItems) {
             let itemStartDate = item[cal.calGetStartDateProp(item)] || item[cal.calGetEndDateProp(item)];
             let itemEndDate = item[cal.calGetEndDateProp(item)] || item[cal.calGetStartDateProp(item)];
 
             if (!itemStartDate && !itemEndDate) {
                 cal.print.addItemToDayboxNodate(document, item);
                 continue;
             }
             itemStartDate = itemStartDate.getInTimezone(defaultTimezone);
--- a/calendar/providers/caldav/calDavCalendar.js
+++ b/calendar/providers/caldav/calDavCalendar.js
@@ -208,26 +208,26 @@ calDavCalendar.prototype = {
     },
 
     set checkedServerInfo(val) {
         return (this.mCheckedServerInfo = val);
     },
 
     saveCalendarProperties: function caldav_saveCalendarProperties() {
         let properties = {};
-        for each (let property in this.offlineCachedProperties) {
+        for (let property of this.offlineCachedProperties) {
             if (this[property] !== undefined) {
                 properties[property] = this[property];
             }
         }
         this.mOfflineStorage.setMetaData("calendar-properties", JSON.stringify(properties));
     },
     restoreCalendarProperties: function caldav_restoreCalendarProperties(data) {
         let properties = JSON.parse(data);
-        for each (let property in this.offlineCachedProperties) {
+        for (let property of this.offlineCachedProperties) {
             if (properties[property] !== undefined) {
                 this[property] = properties[property];
             }
         }
     },
 
     // in calIGenericOperationListener aListener
     replayChangesOn: function caldav_replayChangesOn(aChangeLogListener) {
@@ -257,17 +257,17 @@ calDavCalendar.prototype = {
      * changes may not be reflected
      */
     ensureMetaData: function caldav_ensureMetaData() {
         let self = this;
         let refreshNeeded = false;
         let getMetaListener = {
             QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIOperationListener]),
             onGetResult: function meta_onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-                for each (let item in aItems) {
+                for (let item of aItems) {
                     if (!(item.id in self.mItemInfoCache)) {
                         let path = self.getItemLocationPath(item);
                         cal.LOG("Adding meta-data for cached item " + item.id);
                         self.mItemInfoCache[item.id] = { etag: null,
                                                          isNew: false,
                                                          locationPath: path,
                                                          isInboxItem: false};
                         self.mHrefIndex[self.mLocationPath + path] = item.id;
@@ -1046,17 +1046,17 @@ calDavCalendar.prototype = {
             // certain event failed.
             cal.WARN("Failed to parse item: " + calData + "\n\nException:" + e);
             return;
         }
         // with CalDAV there really should only be one item here
         let items = parser.getItems({});
         let propertiesList = parser.getProperties({});
         let method;
-        for each (var prop in propertiesList) {
+        for (var prop of propertiesList) {
             if (prop.propertyName == "METHOD") {
                 method = prop.value;
                 break;
             }
         }
         let isReply = (method == "REPLY");
         let item = items[0];
         if (!item) {
@@ -1837,17 +1837,17 @@ calDavCalendar.prototype = {
 
 
             // Use supported-calendar-component-set if the server supports it; some do not
             // Accept name attribute from all namespaces to workaround Cosmo bug see bug 605378 comment 6
             let supportedComponents = caldavXPath(multistatus,
                 "/D:multistatus/D:response/D:propstat/D:prop/C:supported-calendar-component-set/C:comp/@*[local-name()='name']");
             if (supportedComponents && supportedComponents.length) {
                 thisCalendar.mSupportedItemTypes = [ compName
-                    for each (compName in supportedComponents)
+                    for (compName of supportedComponents)
                     if (thisCalendar.mGenerallySupportedItemTypes.includes(compName))
                 ];
                 cal.LOG("Adding supported items: " + thisCalendar.mSupportedItemTypes.join(",") + " for calendar: " + thisCalendar.name);
             }
 
             // check if owner is specified; might save some work
             let owner = caldavXPathFirst(multistatus, "/D:multistatus/D:response/D:propstat/D:prop/D:owner/D:href/text()");
             let cuprincipal = caldavXPathFirst(multistatus, "/D:multistatus/D:response/D:propstat/D:prop/D:current-user-principal/D:href/text()");
@@ -2214,19 +2214,21 @@ calDavCalendar.prototype = {
                 return url;
             }
 
             // If there are multiple home sets, we need to match the email addresses for scheduling.
             // If there is only one, assume its the right one.
             // TODO with multiple address sets, we should just use the ACL manager.
             if (homeSets && (homeSets.length == 1 || homeSets.some(homeSetMatches))) {
                 let cuaSets = caldavXPath(multistatus, "/D:multistatus/D:response/D:propstat/D:prop/C:calendar-user-address-set/D:href/text()");
-                for each (let addr in cuaSets) {
-                    if (addr.match(/^mailto:/i)) {
-                        thisCalendar.mCalendarUserAddress = addr;
+                if (cuaSets) {
+                    for (let addr of cuaSets) {
+                        if (addr.match(/^mailto:/i)) {
+                            thisCalendar.mCalendarUserAddress = addr;
+                        }
                     }
                 }
 
 
                 let inboxPath = caldavXPathFirst(multistatus, "/D:multistatus/D:response/D:propstat/D:prop/C:schedule-inbox-URL/D:href/text()");
                 if (!inboxPath) {
                     // most likely this is a Kerio server that omits the "href"
                     inboxPath = caldavXPathFirst(multistatus, "/D:multistatus/D:response/D:propstat/D:prop/C:schedule-inbox-URL/text()");
@@ -2653,17 +2655,17 @@ calDavCalendar.prototype = {
                                                               aCount,
                                                               aItems) {
             var itemToUpdate = aItems[0];
             if (aItem.recurrenceId && itemToUpdate.recurrenceInfo) {
                 itemToUpdate = itemToUpdate.recurrenceInfo.getOccurrenceFor(aItem.recurrenceId);
             }
             var newItem = itemToUpdate.clone();
 
-            for each (var attendee in aItem.getAttendees({})) {
+            for (var attendee of aItem.getAttendees({})) {
                 var att = newItem.getAttendeeById(attendee.id);
                 if (att) {
                     newItem.removeAttendee(att);
                     att = att.clone();
                     att.participationStatus = attendee.participationStatus;
                     newItem.addAttendee(att);
                 }
             }
@@ -2748,17 +2750,17 @@ calDavCalendar.prototype = {
             var attendee = aItipItem.getItemList({})[0].getAttendeeById(this.calendarUserAddress);
             if (!attendee) {
                 return false;
             }
             // work around BUG 351589, the below just removes RSVP:
             aItipItem.setAttendeeStatus(attendee.id, attendee.participationStatus);
         }
 
-        for each (var item in aItipItem.getItemList({})) {
+        for (var item of aItipItem.getItemList({})) {
 
             var serializer = Components.classes["@mozilla.org/calendar/ics-serializer;1"]
                                        .createInstance(Components.interfaces.calIIcsSerializer);
             serializer.addItems([item], 1);
             var methodProp = getIcsService().createIcalProperty("METHOD");
             methodProp.value = aItipItem.responseMethod;
             serializer.addProperty(methodProp);
 
@@ -2798,27 +2800,29 @@ calDavCalendar.prototype = {
                         return;
                     }
 
                     var remainingAttendees = [];
                     // TODO The following XPath expressions are currently
                     // untested code, as I don't have a caldav-sched server
                     // available. If you find someone who does, please test!
                     let responses = caldavXPath(responseXML, "/C:schedule-response/C:response");
-                    for each (let response in responses) {
-                        let recip = caldavXPathFirst(response, "C:recipient/D:href/text()");
-                        let status = caldavXPathFirst(response, "C:request-status/text()");
-                        if (status.substr(0, 1) != "2") {
-                            if (thisCalendar.verboseLogging()) {
-                                cal.LOG("CalDAV: Failed scheduling delivery to " + recip);
-                            }
-                            for each (let att in aRecipients) {
-                                if (att.id.toLowerCase() == recip.toLowerCase()) {
-                                    remainingAttendees.push(att);
-                                    break;
+                    if (responses) {
+                        for (let response of responses) {
+                            let recip = caldavXPathFirst(response, "C:recipient/D:href/text()");
+                            let status = caldavXPathFirst(response, "C:request-status/text()");
+                            if (status.substr(0, 1) != "2") {
+                                if (thisCalendar.verboseLogging()) {
+                                    cal.LOG("CalDAV: Failed scheduling delivery to " + recip);
+                                }
+                                for (let att of aRecipients) {
+                                    if (att.id.toLowerCase() == recip.toLowerCase()) {
+                                        remainingAttendees.push(att);
+                                        break;
+                                    }
                                 }
                             }
                         }
                     }
 
                     if (remainingAttendees.length) {
                         // try to fall back to email delivery if CalDAV-sched
                         // didn't work
@@ -2839,17 +2843,17 @@ calDavCalendar.prototype = {
             let uploadData = serializer.serializeToString();
             let requestUri = this.makeUri(null, this.outboxUrl);
             if (this.verboseLogging()) {
                 cal.LOG("CalDAV: send(" + requestUri.spec + "): " + uploadData);
             }
             this.sendHttpRequest(requestUri, uploadData, MIME_TEXT_CALENDAR, null, (channel) => {
                 channel.requestMethod = "POST";
                 channel.setRequestHeader("Originator", this.calendarUserAddress, false);
-                for each (var recipient in aRecipients) {
+                for (var recipient of aRecipients) {
                     channel.setRequestHeader("Recipient", recipient.id, true);
                 }
                 return streamListener;
             }, () => {
                 notifyListener(Components.results.NS_ERROR_NOT_AVAILABLE,
                                "Error preparing http channel");
             });
         }
--- a/calendar/providers/composite/calCompositeCalendar.js
+++ b/calendar/providers/composite/calCompositeCalendar.js
@@ -125,17 +125,17 @@ calCompositeCalendar.prototype = {
     get enabledCalendars() {
       return this.mCalendars.filter(
         function(e) { return !e.getProperty("disabled"); }
       );
     },
 
     set prefPrefix (aPrefPrefix) {
         if (this.mPrefPrefix) {
-            for each (let calendar in this.mCalendars) {
+            for (let calendar of this.mCalendars) {
                 this.removeCalendar(calendar);
             }
         }
         this.mPrefPrefix = aPrefPrefix;
         this.mActivePref = aPrefPrefix + "-in-composite";
         this.mDefaultPref = aPrefPrefix + "-default";
         let mgr = cal.getCalendarManager();
         let cals = mgr.getCalendars({});
@@ -185,17 +185,17 @@ calCompositeCalendar.prototype = {
                 aCalendar.deleteProperty(this.mDefaultPref);
             }
             aCalendar.removeObserver(this.mObserverHelper);
             this.mCompositeObservers.notify("onCalendarRemoved", [aCalendar]);
         }
     },
 
     getCalendarById: function cCC_getCalendarById(aId) {
-        for each (let calendar in this.mCalendars) {
+        for (let calendar of this.mCalendars) {
             if (calendar.id == aId) {
                 return calendar;
             }
         }
         return null;
     },
 
     getCalendars: function getCalendars(count) {
@@ -315,17 +315,17 @@ calCompositeCalendar.prototype = {
         }
         this.mObservers.remove(aObserver);
     },
 
     refresh: function cCC_refresh() {
         if (this.mStatusObserver) {
             this.mStatusObserver.startMeteors(Components.interfaces.calIStatusObserver.DETERMINED_PROGRESS, this.mCalendars.length);
         }
-        for each (let calendar in this.enabledCalendars) {
+        for (let calendar of this.enabledCalendars) {
             try {
                 if (calendar.canRefresh) {
                     this.mObserverHelper.pendingLoads[calendar.id] = true;
                     calendar.refresh();
                 }
             } catch (e) {
                 cal.ASSERT(false, e);
                 delete this.mObserverHelper.pendingLoads[calendar.id];
@@ -358,17 +358,17 @@ calCompositeCalendar.prototype = {
     addItem: function (aItem, aListener) {
         return this.mDefaultCalendar.addItem(aItem, aListener);
     },
 
     // void getItem( in string aId, in calIOperationListener aListener );
     getItem: function (aId, aListener) {
         let enabledCalendars = this.enabledCalendars;
         let cmpListener = new calCompositeGetListenerHelper(this, aListener);
-        for each (let calendar in enabledCalendars) {
+        for (let calendar of enabledCalendars) {
             try {
                 cmpListener.opGroup.add(calendar.getItem(aId, cmpListener));
             } catch (exc) {
                 cal.ASSERT(false, exc);
             }
         }
         return cmpListener.opGroup;
     },
@@ -389,17 +389,17 @@ calCompositeCalendar.prototype = {
         }
         if (this.mStatusObserver) {
             if (this.mStatusObserver.spinning == Components.interfaces.calIStatusObserver.NO_PROGRESS) {
                 this.mStatusObserver.startMeteors(Components.interfaces.calIStatusObserver.UNDETERMINED_PROGRESS, -1);
             }
         }
         let cmpListener = new calCompositeGetListenerHelper(this, aListener, aCount);
 
-        for each (let calendar in enabledCalendars) {
+        for (let calendar of enabledCalendars) {
             try {
                 cmpListener.opGroup.add(calendar.getItems(aItemFilter,
                                                           aCount,
                                                           aRangeStart,
                                                           aRangeEnd,
                                                           cmpListener));
             } catch (exc) {
                 cal.ASSERT(false, exc);
--- a/calendar/providers/ics/calICSCalendar.js
+++ b/calendar/providers/ics/calICSCalendar.js
@@ -269,17 +269,17 @@ calICSCalendar.prototype = {
         // for non-existing or empty files, but not good for invalid files.
         // That's why we put them in readOnly mode
         let parser = Components.classes["@mozilla.org/calendar/ics-parser;1"]
                                .createInstance(Components.interfaces.calIIcsParser);
         let this_ = this;
         let listener = { // calIIcsParsingListener
             onParsingComplete: function ics_onParsingComplete(rc, parser_) {
                 try {
-                    for each (let item in parser_.getItems({})) {
+                    for (let item of parser_.getItems({})) {
                         this_.mMemoryCalendar.adoptItem(item, null);
                     }
                     this_.unmappedComponents = parser_.getComponents({});
                     this_.unmappedProperties = parser_.getProperties({});
                     cal.LOG("[calICSCalendar] Parsing ICS succeeded for " + this_.uri.spec);
                 } catch (exc) {
                     cal.LOG("[calICSCalendar] Parsing ICS failed for " + "\nException: "+ exc);
                     this_.mObserver.onError(this_.superCalendar, exc.result, exc.toString());
@@ -376,20 +376,20 @@ calICSCalendar.prototype = {
             },
             onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
             {
                 this.serializer.addItems(aItems, aCount);
             }
         };
         listener.serializer = Components.classes["@mozilla.org/calendar/ics-serializer;1"].
                                          createInstance(Components.interfaces.calIIcsSerializer);
-        for each (let comp in this.unmappedComponents) {
+        for (let comp of this.unmappedComponents) {
             listener.serializer.addComponent(comp);
         }
-        for each (let prop in this.unmappedProperties) {
+        for (let prop of this.unmappedProperties) {
             switch (prop.propertyName) {
                 // we always set the current name and timezone:
                 case "X-WR-CALNAME":
                 case "X-WR-TIMEZONE":
                     break;
                 default:
                     listener.serializer.addProperty(prop);
                     break;
--- a/calendar/providers/storage/calStorageCalendar.js
+++ b/calendar/providers/storage/calStorageCalendar.js
@@ -67,31 +67,35 @@ calStorageCalendar.prototype = {
 
     createCalendar: function cSC_createCalendar() {
         throw NS_ERROR_NOT_IMPLEMENTED;
     },
 
     deleteCalendar: function cSC_deleteCalendar(aCalendar, listener) {
         aCalendar = aCalendar.wrappedJSObject;
 
-        for each (let stmt in this.mDeleteEventExtras) {
-            try {
-                this.prepareStatement(stmt);
-                stmt.executeStep();
-            } finally {
+        if (this.mDeleteEventExtras) {
+            for (let stmt of this.mDeleteEventExtras) {
+                try {
+                    this.prepareStatement(stmt);
+                    stmt.executeStep();
+                } finally {
                 stmt.reset();
+                }
             }
         }
 
-        for each (let stmt in this.mDeleteTodoExtras) {
-            try {
-                this.prepareStatement(stmt);
-                stmt.executeStep();
-            } finally {
-                stmt.reset();
+        if (this.mDeleteTodoExtras) {
+            for (let stmt of this.mDeleteTodoExtras) {
+                try {
+                    this.prepareStatement(stmt);
+                    stmt.executeStep();
+                } finally {
+                    stmt.reset();
+                }
             }
         }
 
         try {
             this.prepareStatement(this.mDeleteAllEvents);
             this.mDeleteAllEvents.executeStep();
         } finally {
             this.mDeleteAllEvents.reset();
@@ -274,21 +278,21 @@ calStorageCalendar.prototype = {
                 /**
                  * Helper function to migrate all tables from one id to the next
                  *
                  * @param db        The database to use
                  * @param newCalId  The new calendar id to set
                  * @param oldCalId  The old calendar id to look for
                  */
                 let migrateTables = function(db, newCalId, oldCalId) {
-                    for each (let tbl in ["cal_alarms", "cal_attachments",
-                                          "cal_attendees", "cal_events",
-                                          "cal_metadata", "cal_properties",
-                                          "cal_recurrence", "cal_relations",
-                                          "cal_todos"]) {
+                    for (let tbl of ["cal_alarms", "cal_attachments",
+                                     "cal_attendees", "cal_events",
+                                     "cal_metadata", "cal_properties",
+                                     "cal_recurrence", "cal_relations",
+                                     "cal_todos"]) {
                         let stmt;
                         try {
                             stmt = db.createStatement("UPDATE " + tbl +
                                                       "   SET cal_id = :cal_id" +
                                                       " WHERE cal_id = :old_cal_id");
                             stmt.params.cal_id = newCalId;
                             stmt.params.old_cal_id = oldCalId;
                             stmt.executeStep();
@@ -832,25 +836,26 @@ calStorageCalendar.prototype = {
                 }
             } catch (e) {
                 this.logError("Error selecting non recurring events by range!\n", e);
             } finally {
                 this.mSelectNonRecurringEventsByRange.reset();
             }
 
             // Process the non-recurring events:
-            for each (var evitem in resultItems) {
+            for (var evitem of resultItems) {
                 count += handleResultItem(evitem, Components.interfaces.calIEvent);
                 if (checkCount()) {
                     return;
                 }
             }
 
             // Process the recurring events from the cache
-            for each (let evitem in this.mRecEventCache) {
+            for (let id in this.mRecEventCache) {
+                let evitem = this.mRecEventCache[id];
                 let offline_journal_flag = this.mRecEventCacheOfflineFlags[evitem.id] || null;
                 // No need to return flagged unless asked i.e. sp.offline_journal == offline_journal_flag
                 // Return created and modified offline records if sp.offline_journal is null alongwith events that have no flag
                 if ((sp.offline_journal == null && offline_journal_flag != cICL.OFFLINE_FLAG_DELETED_RECORD)
                     || (sp.offline_journal != null && offline_journal_flag == sp.offline_journal)) {
                     count += handleResultItem(evitem, Components.interfaces.calIEvent);
                     if (checkCount()) {
                         return;
@@ -883,29 +888,30 @@ calStorageCalendar.prototype = {
                 }
             } catch (e) {
                 this.logError("Error selecting non recurring todos by range", e);
             } finally {
                 this.mSelectNonRecurringTodosByRange.reset();
             }
 
             // process the non-recurring todos:
-            for each (var todoitem in resultItems) {
+            for (var todoitem of resultItems) {
                 count += handleResultItem(todoitem, Components.interfaces.calITodo, checkCompleted);
                 if (checkCount()) {
                     return;
                 }
             }
 
             // Note: Reading the code, completed *occurrences* seems to be broken, because
             //       only the parent item has been filtered; I fixed that.
             //       Moreover item.todo_complete etc seems to be a leftover...
 
             // process the recurring todos from the cache
-            for each (let todoitem in this.mRecTodoCache) {
+            for (let id in this.mRecTodoCache) {
+                let todoitem = this.mRecTodoCache[id];
                 let offline_journal_flag = this.mRecTodoCacheOfflineFlags[todoitem.id] || null;
                 if ((sp.offline_journal == null &&
                      (offline_journal_flag == cICL.OFFLINE_FLAG_MODIFIED_RECORD ||
                       offline_journal_flag == cICL.OFFLINE_FLAG_CREATED_RECORD ||
                       offline_journal_flag == null)) ||
                     (sp.offline_journal != null &&
                      (offline_journal_flag == sp.offline_journal))) {
 
@@ -1464,20 +1470,20 @@ calStorageCalendar.prototype = {
             if (this.mSelectPropertiesForItemWithRecurrenceId) { this.mSelectPropertiesForItemWithRecurrenceId.finalize(); }
             if (this.mSelectRecurrenceForItem) { this.mSelectRecurrenceForItem.finalize(); }
             if (this.mSelectRelationsForItem) { this.mSelectRelationsForItem.finalize(); }
             if (this.mSelectRelationsForItemWithRecurrenceId) { this.mSelectRelationsForItemWithRecurrenceId.finalize(); }
             if (this.mSelectTodo) { this.mSelectTodo.finalize(); }
             if (this.mSelectTodoExceptions) { this.mSelectTodoExceptions.finalize(); }
             if (this.mSelectTodosWithRecurrence) { this.mSelectTodosWithRecurrence.finalize(); }
             if (this.mDeleteEventExtras) {
-                for each (let stmt in this.mDeleteEventExtras) { stmt.finalize(); }
+                for (let stmt of this.mDeleteEventExtras) { stmt.finalize(); }
             }
             if (this.mDeleteTodoExtras) {
-                for each (let stmt in this.mDeleteTodoExtras) { stmt.finalize(); }
+                for (let stmt of this.mDeleteTodoExtras) { stmt.finalize(); }
             }
 
             if (this.mDB) { this.mDB.asyncClose(); this.mDB = null; }
         } catch (e) {
             cal.ERROR("Error closing storage database: " + e);
         }
     },
 
@@ -2075,17 +2081,17 @@ calStorageCalendar.prototype = {
 
     writeAttendees: function cSC_writeAttendees(item, olditem) {
         var attendees = item.getAttendees({});
         if (item.organizer) {
             attendees = attendees.concat([]);
             attendees.push(item.organizer);
         }
         if (attendees.length > 0) {
-            for each (var att in attendees) {
+            for (var att of attendees) {
                 var ap = this.mInsertAttendee.params;
                 ap.item_id = item.id;
                 try {
                     this.prepareStatement(this.mInsertAttendee);
                     this.setDateParamHelper(ap, "recurrence_id", item.recurrenceId);
                     ap.icalString = att.icalString;
                     this.mInsertAttendee.executeStep();
                 } finally {
@@ -2149,17 +2155,17 @@ calStorageCalendar.prototype = {
 
     writeRecurrence: function cSC_writeRecurrence(item, olditem) {
         var flags = 0;
 
         var rec = item.recurrenceInfo;
         if (rec) {
             flags = CAL_ITEM_FLAG.HAS_RECURRENCE;
             let ritems = rec.getRecurrenceItems({});
-            for each (let ritem in ritems) {
+            for (let ritem of ritems) {
                 let ap = this.mInsertRecurrence.params;
                 try {
                     this.prepareStatement(this.mInsertRecurrence);
                     ap.item_id = item.id;
                     ap.icalString = ritem.icalString;
                     this.mInsertRecurrence.executeStep();
                 } finally {
                     this.mInsertRecurrence.reset();
@@ -2168,34 +2174,34 @@ calStorageCalendar.prototype = {
 
             var exceptions = rec.getExceptionIds ({});
             if (exceptions.length > 0) {
                 flags |= CAL_ITEM_FLAG.HAS_EXCEPTIONS;
 
                 // we need to serialize each exid as a separate
                 // event/todo; setupItemBase will handle
                 // writing the recurrenceId for us
-                for each (let exid in exceptions) {
+                for (let exid of exceptions) {
                     let ex = rec.getExceptionFor(exid);
                     if (!ex)
                         throw Components.results.NS_ERROR_UNEXPECTED;
                     this.writeItem(ex, null);
                 }
             }
         } else  if (item.recurrenceId && item.recurrenceId.isDate) {
             flags |= CAL_ITEM_FLAG.RECURRENCE_ID_ALLDAY;
         }
 
         return flags;
     },
 
     writeAttachments: function cSC_writeAttachments(item, olditem) {
         let attachments = item.getAttachments({});
         if (attachments && attachments.length > 0) {
-            for each (let att in attachments) {
+            for (let att of attachments) {
                 let ap = this.mInsertAttachment.params;
                 try {
                     this.prepareStatement(this.mInsertAttachment);
                     this.setDateParamHelper(ap, "recurrence_id", item.recurrenceId);
                     ap.item_id = item.id;
                     ap.icalString = att.icalString;
 
                     this.mInsertAttachment.executeStep();
@@ -2206,17 +2212,17 @@ calStorageCalendar.prototype = {
             return CAL_ITEM_FLAG.HAS_ATTACHMENTS;
         }
         return 0;
     },
 
     writeRelations: function cSC_writeRelations(item, olditem) {
         let relations = item.getRelations({});
         if (relations && relations.length > 0) {
-            for each (var rel in relations) {
+            for (var rel of relations) {
                 let rp = this.mInsertRelation.params;
                 try {
                     this.prepareStatement(this.mInsertRelation);
                     this.setDateParamHelper(rp, "recurrence_id", item.recurrenceId);
                     rp.item_id = item.id;
                     rp.icalString = rel.icalString;
 
                     this.mInsertRelation.executeStep();
@@ -2230,17 +2236,17 @@ calStorageCalendar.prototype = {
     },
 
     writeAlarms: function cSC_writeAlarms(item, olditem) {
         let alarms = item.getAlarms({});
         if (alarms.length < 1) {
             return 0;
         }
 
-        for each (let alarm in alarms) {
+        for (let alarm of alarms) {
             let pp = this.mInsertAlarm.params;
             try {
                 this.prepareStatement(this.mInsertAlarm);
                 this.setDateParamHelper(pp, "recurrence_id", item.recurrenceId);
                 pp.item_id = item.id;
                 pp.icalString = alarm.icalString;
                 this.mInsertAlarm.executeStep();
             } catch (e) {
@@ -2425,17 +2431,17 @@ calStorageCalendar.prototype = {
             aItem.setProperty("SEQUENCE", newSequence);
         } else {
             aItem.deleteProperty("SEQUENCE");
         }
         var rec = aItem.recurrenceInfo;
         if (rec) {
             var exceptions = rec.getExceptionIds ({});
             if (exceptions.length > 0) {
-                for each (exid in exceptions) {
+                for (exid of exceptions) {
                     let ex = rec.getExceptionFor(exid);
                     if (newSequence) {
                         ex.setProperty("SEQUENCE", newSequence);
                     } else {
                         ex.deleteProperty("SEQUENCE");
                     }
                 }
             }
--- a/calendar/providers/storage/calStorageUpgrade.jsm
+++ b/calendar/providers/storage/calStorageUpgrade.jsm
@@ -400,17 +400,17 @@ function ensureUpdatedTimezones(db) {
             cal.ERROR("Error updating timezones: " + e +
                       "\nDB Error " + lastErrorString(db));
         } finally {
             getZones.reset();
         }
 
         beginTransaction(db);
         try {
-            for each (let update in zonesToUpdate) {
+            for (let update of zonesToUpdate) {
                 executeSimpleSQL(db,
                     "UPDATE cal_attendees    SET recurrence_id_tz = '" + update.newTzId + "' WHERE recurrence_id_tz = '" + update.oldTzId + "'; " +
                     "UPDATE cal_events       SET recurrence_id_tz = '" + update.newTzId + "' WHERE recurrence_id_tz = '" + update.oldTzId + "'; " +
                     "UPDATE cal_events       SET event_start_tz   = '" + update.newTzId + "' WHERE event_start_tz   = '" + update.oldTzId + "'; " +
                     "UPDATE cal_events       SET event_end_tz     = '" + update.newTzId + "' WHERE event_end_tz     = '" + update.oldTzId + "'; " +
                     "UPDATE cal_properties   SET recurrence_id_tz = '" + update.newTzId + "' WHERE recurrence_id_tz = '" + update.oldTzId + "'; " +
                     "UPDATE cal_todos        SET recurrence_id_tz = '" + update.newTzId + "' WHERE recurrence_id_tz = '" + update.oldTzId + "'; " +
                     "UPDATE cal_todos        SET todo_entry_tz    = '" + update.newTzId + "' WHERE todo_entry_tz    = '" + update.oldTzId + "'; " +
@@ -454,17 +454,17 @@ function addColumn(tblData, tblName, col
  * Deletes columns from the given table.
  *
  * @param tblData       The table data object to apply the operation on.
  * @param tblName       The table name to delete on
  * @param colNameArray  An array of colum names to delete
  * @param db            (optional) The database to apply the operation on
  */
 function deleteColumns(tblData, tblName, colNameArray, db) {
-    for each (let colName in colNameArray) {
+    for (let colName of colNameArray) {
         delete tblData[tblName][colName];
     }
 
     let columns = [ k for (k in tblData[tblName]) ];
     executeSimpleSQL(db, getSql(tblName, tblData, tblName + "_temp"));
     executeSimpleSQL(db, "INSERT INTO " + tblName + "_temp" +
                          "  (" + columns.join(",") + ") " +
                          "SELECT " + columns.join(",") +
@@ -506,17 +506,17 @@ function copyTable(tblData, tblName, new
  *
  * @param tblData       The table data object to apply the operation on.
  * @param tblName       The table name to alter
  * @param colNameArray  An array of colum names to delete
  * @param newType       The new type of the column
  * @param db            (optional) The database to apply the operation on
  */
 function alterTypes(tblData, tblName, colNameArray, newType, db) {
-    for each (let colName in colNameArray) {
+    for (let colName of colNameArray) {
         tblData[tblName][colName] = newType;
     }
 
     let columns = [ k for (k in tblData[tblName]) ];
     executeSimpleSQL(db, getSql(tblName, tblData, tblName + "_temp"));
     executeSimpleSQL(db, "INSERT INTO " + tblName + "_temp" +
                          "  (" + columns.join(",") + ") " +
                          "SELECT " + columns.join(",") +
@@ -804,17 +804,17 @@ upgrade.v3 = function upgrade_v3(db, ver
  * r=shaver,p=vlad
  */
 upgrade.v4 = function upgrade_v4(db, version) {
     let tbl = upgrade.v3(version < 3 && db, version);
     LOGdb(db, "Storage: Upgrading to v4");
 
     beginTransaction(db);
     try {
-        for each (let tblid in ["events", "todos", "attendees", "properties"]) {
+        for (let tblid of ["events", "todos", "attendees", "properties"]) {
             addColumn(tbl, "cal_" + tblid, "recurrence_id", "INTEGER", db);
             addColumn(tbl, "cal_" + tblid, "recurrence_id_tz", "VARCHAR", db);
         }
         setDbVersionAndCommit(db, 4);
     } catch (e) {
         throw reportErrorAndRollback(db, e);
     }
 
@@ -827,17 +827,17 @@ upgrade.v4 = function upgrade_v4(db, ver
  * r=dmose, p=jminta
  */
 upgrade.v5 = function upgrade_v5(db, version) {
     let tbl = upgrade.v4(version < 4 && db, version);
     LOGdb(db, "Storage: Upgrading to v5");
 
     beginTransaction(db);
     try {
-        for each (let tblid in ["events", "todos"]) {
+        for (let tblid of ["events", "todos"]) {
             addColumn(tbl, "cal_" + tblid, "alarm_offset", "INTEGER", db);
             addColumn(tbl, "cal_" + tblid, "alarm_related", "INTEGER", db);
             addColumn(tbl, "cal_" + tblid, "alarm_last_ack", "INTEGER", db);
         }
         setDbVersionAndCommit(db, 5);
     } catch (e) {
         throw reportErrorAndRollback(db, e);
     }
@@ -998,32 +998,32 @@ upgrade.v13 = function upgrade_v13(db, v
     LOGdb(db, "Storage: Upgrading to v13");
 
     beginTransaction(db);
     try {
         alterTypes(tbl, "cal_metadata", ["item_id"], "TEXT", db);
 
         let calIds = {};
         if (db) {
-            for each (let itemTable in ["events", "todos"]) {
+            for (let itemTable of ["events", "todos"]) {
                 let stmt = createStatement(db,
                                            "SELECT id, cal_id FROM cal_" + itemTable);
                 try {
                     while (stmt.executeStep()) {
                         calIds[stmt.row.id] = stmt.row.cal_id;
                     }
                 }
                 finally {
                     stmt.reset();
                 }
             }
         }
 
-        for each (let tblid in ["attendees", "recurrence", "properties",
-                                "attachments"]) {
+        for (let tblid of ["attendees", "recurrence", "properties",
+                           "attachments"]) {
             addColumn(tbl, "cal_" + tblid, "cal_id", "INTEGER", db);
 
             for (let itemId in calIds) {
                 executeSimpleSQL(db, "UPDATE cal_" + tblid +
                                      "   SET cal_id = " + calIds[itemId] +
                                      " WHERE item_id = '" + itemId + "'");
             }
         }
@@ -1180,17 +1180,17 @@ upgrade.v16 = function upgrade_v16(db, v
                              "     FROM cal_alarms " +
                              "     WHERE cal_alarms.cal_id = cal_todos.cal_id)");
 
         // Remote obsolete columns
         let cols = ["alarm_time",
                     "alarm_time_tz",
                     "alarm_offset",
                     "alarm_related"];
-        for each (let tblid in ["events", "todos"]) {
+        for (let tblid of ["events", "todos"]) {
             deleteColumns(tbl, "cal_" + tblid, cols, db);
         }
 
         setDbVersionAndCommit(db, 16);
     } catch (e) {
         throw reportErrorAndRollback(db, e);
     }
 
@@ -1207,17 +1207,17 @@ upgrade.v16 = function upgrade_v16(db, v
  * Therefore all this upgrader does is handle users of 1.0pre before the
  * mentioned bug.
  */
 upgrade.v17 = function upgrade_v17(db, version) {
     let tbl = upgrade.v16(version < 16 && db, version);
     LOGdb(db, "Storage: Upgrading to v17");
     beginTransaction(db);
     try {
-        for each (let tblName in ["alarms", "relations", "attachments"]) {
+        for (let tblName of ["alarms", "relations", "attachments"]) {
             let hasColumns = true;
             let stmt;
             try {
                 // Stepping this statement will fail if the columns don't exist.
                 // We don't use the delegate here since it would show an error to
                 // the user, even through we expect the error. If the db is null,
                 // then swallowing the error is ok too since the cols will
                 // already be added in v16.
@@ -1279,22 +1279,22 @@ upgrade.v18 = function upgrade_v18(db, v
     LOGdb(db, "Storage: Upgrading to v18");
     beginTransaction(db);
     try {
         // These fields are often indexed over
         let simpleIds = ["cal_id", "item_id"];
         let allIds = simpleIds.concat(["recurrence_id", "recurrence_id_tz"]);
 
         // Alarms, Attachments, Attendees, Relations
-        for each (let tblName in ["alarms", "attachments", "attendees", "relations"]) {
+        for (let tblName of ["alarms", "attachments", "attendees", "relations"]) {
             createIndex(tbl, "cal_" + tblName, allIds, db);
         }
 
         // Events and Tasks
-        for each (let tblName in ["events", "todos"]) {
+        for (let tblName of ["events", "todos"]) {
             createIndex(tbl, "cal_" + tblName, ["flags", "cal_id", "recurrence_id"], db);
             createIndex(tbl, "cal_" + tblName, ["id", "cal_id", "recurrence_id"], db);
         }
 
         // Metadata
         createIndex(tbl, "cal_metadata", simpleIds, db);
 
         // Properties. Remove the index we used to create first, since our index
@@ -1319,21 +1319,21 @@ upgrade.v18 = function upgrade_v18(db, v
  * r=simon.at.orcl, p=philipp,dbo
  */
 upgrade.v19 = function upgrade_v19(db, version) {
     let tbl = upgrade.v18(version < 18 && db, version);
     LOGdb(db, "Storage: Upgrading to v19");
     beginTransaction(db);
     try {
         // Change types of column to TEXT.
-        for each (let tblName in ["cal_alarms", "cal_attachments",
-                                  "cal_attendees", "cal_events",
-                                  "cal_metadata", "cal_properties",
-                                  "cal_recurrence", "cal_relations",
-                                  "cal_todos"]) {
+        for (let tblName of ["cal_alarms", "cal_attachments",
+                             "cal_attendees", "cal_events",
+                             "cal_metadata", "cal_properties",
+                             "cal_recurrence", "cal_relations",
+                             "cal_todos"]) {
             alterTypes(tbl, tblName, ["cal_id"], "TEXT", db);
         }
         setDbVersionAndCommit(db, 19);
     } catch (e) {
         throw reportErrorAndRollback(db, e);
     }
 
     return tbl;
@@ -1345,17 +1345,17 @@ upgrade.v19 = function upgrade_v19(db, v
  * r=philipp, p=redDragon
  */
 upgrade.v20 = function upgrade_v20(db, version) {
     let tbl = upgrade.v19(version < 19 && db, version);
     LOGdb(db, "Storage: Upgrading to v20");
     beginTransaction(db);
     try {
         //Adding a offline_journal column
-        for each (let tblName in ["cal_events", "cal_todos"]) {
+        for (let tblName of ["cal_events", "cal_todos"]) {
             addColumn(tbl, tblName, ["offline_journal"], "INTEGER", db);
         }
         setDbVersionAndCommit(db, 20);
     } catch (e) {
         throw reportErrorAndRollback(db,e);
     }
     return tbl;
 }
@@ -1499,17 +1499,17 @@ upgrade.v22 = function upgrade_v22(db, v
                     if (aRsvp === 1) attendee.rsvp = "TRUE";
                     // default: keep undefined
 
                     attendee.role = aRole;
                     attendee.participationStatus = aStatus;
                     attendee.userType = aType;
                     attendee.isOrganizer = !!aIsOrganizer;
                     if (aProperties) {
-                        for each (let pair in aProperties.split(",")) {
+                        for (let pair of aProperties.split(",")) {
                             let [key, value] = pair.split(":");
                             attendee.setProperty(decodeURIComponent(key),
                                                  decodeURIComponent(value));
                         }
                     }
 
                     return attendee.icalString;
                 } catch (e) {
--- a/calendar/providers/wcap/calWcapCalendar.js
+++ b/calendar/providers/wcap/calWcapCalendar.js
@@ -158,17 +158,17 @@ calWcapCalendar.prototype = {
     },
 
     setProperty: function calWcapCalendar_setProperty(aName, aValue) {
         switch (aName) {
             case "disabled":
                 if (this.isDefaultCalendar) {
                     // disabling/enabling the default calendar will enable/disable all calendars
                     // belonging to the same session:
-                    for each (let calendar in this.session.getRegisteredCalendars()) {
+                    for (let calendar of this.session.getRegisteredCalendars()) {
                         if (!calendar.isDefaultCalendar) {
                             calendar.setProperty("disabled", aValue);
                         }
                     }
                 }
                 // fallthru intended
             default:
                 this.__proto__.__proto__.setProperty.apply(this, arguments);
--- a/calendar/providers/wcap/calWcapCalendarItems.js
+++ b/calendar/providers/wcap/calWcapCalendarItems.js
@@ -37,17 +37,17 @@ calWcapCalendar.prototype.getRecurrenceP
 function calWcapCalendar_getRecurrenceParams(item, out_rrules, out_rdates, out_exrules, out_exdates) {
     // recurrences:
     out_rrules.value = [];
     out_rdates.value = [];
     out_exrules.value = [];
     out_exdates.value = [];
     if (item.recurrenceInfo) {
         var rItems = item.recurrenceInfo.getRecurrenceItems({});
-        for each (var rItem in rItems) {
+        for (var rItem of rItems) {
             var isNeg = rItem.isNegative;
             let rRuleInstance = cal.wrapInstance(rItem, Components.interfaces.calIRecurrenceRule);
             let rDateInstance = cal.wrapInstance(rItem, Components.interfaces.calIRecurrenceDate);
             if (rRuleInstance) {
                 var rule = ("\"" + encodeURIComponent(rRuleInstance.icalProperty.valueAsIcalString) + "\"");
                 if (isNeg) {
                     out_exrules.value.push(rule);
                 } else {
@@ -179,17 +179,17 @@ function calWcapCalendar_getAlarmParams(
 
 // why ever, X-S1CS-EMAIL is unsupported though documented
 // for get_calprops... WTF.
 function getCalId(att) {
     return (att ? att.getProperty("X-S1CS-CALID") : null);
 }
 
 function getAttendeeByCalId(atts, calId) {
-    for each (var att in atts) {
+    for (var att of atts) {
         if (getCalId(att) == calId) {
             return att;
         }
     }
     return null;
 }
 
 calWcapCalendar.prototype.isInvitation =
@@ -304,17 +304,17 @@ function calWcapCalendar_storeItem(bAddI
     function getPrivacy(item) {
         return ((item.privacy && item.privacy != "") ? item.privacy : "PUBLIC");
     }
     function getAttachments(item) {
         var ret;
         var attachments = item.attachments;
         if (attachments) {
             var strings = [];
-            for each (var att in attachements) {
+            for (var att of attachments) {
                 let wrappedAtt = cal.wrapInstance(att, Components.interfaces.calIAttachment);
                 if (typeof(att) == "string") {
                     strings.push(encodeURIComponent(att));
                 } else if (wrappedAtt && wrappedAtt.uri) {
                     strings.push(encodeURIComponent(wrappedAtt.uri.spec));
                 } else { // xxx todo
                     logError("only URLs supported as attachment, not: " + att, this_);
                 }
@@ -927,17 +927,17 @@ calWcapCalendar.prototype.parseItems = f
                     item.makeImmutable();
                 }
                 items.push(item);
             }
         }
     }
 
     // tag "exceptions", i.e. items with rid:
-    for each (let item in excItems) {
+    for (let item of excItems) {
         let parent = uid2parent[item.id];
 
         if (!parent) { // a parentless one, fake a master and override it's occurrence
             parent = isEvent(item) ? createEvent() : createTodo();
             parent.id = item.id;
             parent.calendar = this.superCalendar;
             parent.setProperty("DTSTART", item.recurrenceId);
             parent.setProperty("X-MOZ-FAKED-MASTER", "1"); // this tag might be useful in the future
@@ -961,27 +961,27 @@ calWcapCalendar.prototype.parseItems = f
             rid.isDate = true;
             item.recurrenceId = rid;
         }
 
         parent.recurrenceInfo.modifyException(item, true);
     }
 
     if (itemFilter & calICalendar.ITEM_FILTER_CLASS_OCCURRENCES) {
-        for each (let item in unexpandedItems) {
+        for (let item of unexpandedItems) {
             if (maxResults != 0 && items.length >= maxResults) {
                 break;
             }
 
             let recStartDate = item.recurrenceStartDate;
             if (recStartDate && !recStartDate.isDate) {
                 recStartDate = null;
             }
             let recItems = item.recurrenceInfo.getRecurrenceItems({});
-            for each (let recItem in recItems) {
+            for (let recItem of recItems) {
                 // cs bug: workaround missing COUNT
                 let rRuleInstance = cal.wrapInstance(recItem, Components.interfaces.calIRecurrenceRule);
                 let rDateInstance = cal.wrapInstance(recItem, Components.interfaces.calIRecurrenceDate);
                 if (rRuleInstance) {
                     recItem = rRuleInstance;
                     if (!recItem.isFinite && !recItem.isNegative) {
                         recItem.count = recurrenceBound;
                     }
@@ -1001,37 +1001,37 @@ calWcapCalendar.prototype.parseItems = f
             }
             let occurrences = item.recurrenceInfo.getOccurrences(rangeStart, rangeEnd,
                                                                  maxResults == 0 ? 0 : maxResults - items.length,
                                                                  {});
             if (LOG_LEVEL > 1) {
                 log("item: " + item.title + " has " + occurrences.length.toString() + " occurrences.", this);
                 if (LOG_LEVEL > 2) {
                     log("master item: " + item.title + "\n" + item.icalString, this);
-                    for each (let occ in occurrences) {
+                    for (let occ of occurrences) {
                         log("item: " + occ.title + "\n" + occ.icalString, this);
                     }
                 }
             }
             // only proxies returned:
             items = items.concat(occurrences);
         }
 
     } else {
         if (maxResults != 0 &&
             (items.length + unexpandedItems.length) > maxResults) {
             unexpandedItems.length = (maxResults - items.length);
         }
         if (!bLeaveMutable) {
-            for each (let item in unexpandedItems) {
+            for (let item of unexpandedItems) {
                 item.makeImmutable();
             }
         }
         if (LOG_LEVEL > 2) {
-            for each (let item in unexpandedItems) {
+            for (let item of unexpandedItems) {
                 log("item: " + item.title + "\n" + item.icalString, this);
             }
         }
         items = items.concat(unexpandedItems);
     }
 
     if (LOG_LEVEL > 1) {
         log("parseItems(): returning " + items.length + " items", this);
@@ -1176,17 +1176,17 @@ function calWcapCalendar_getItems(itemFi
     // m_cachedResults holds the last data revtrieval. This is expecially useful when
     // switching on multiple subcriptions: the composite calendar multiplexes getItems()
     // calls to all composited calendars over and over again, most often on the same
     // date range (as the user usually looks at the same view).
     // This will most likely vanish when a better caching is implemented in the views,
     // or WCAP local storage caching has sufficient performance.
     // The cached results will be invalidated after 2 minutes to reflect incoming invitations.
     if (CACHE_LAST_RESULTS > 0 && this.m_cachedResults) {
-        for each (var entry in this.m_cachedResults) {
+        for (var entry of this.m_cachedResults) {
             if ((itemFilter == entry.itemFilter) &&
                 equalDatetimes(rangeStart, entry.rangeStart) &&
                 equalDatetimes(rangeEnd, entry.rangeEnd)) {
                 log("reusing last getItems() cached data.", this);
                 if (listener) {
                     listener.onGetResult(
                         this.superCalendar, NS_OK, calIItemBase,
                         "getItems()", entry.results.length, entry.results);
@@ -1218,17 +1218,17 @@ function calWcapCalendar_getItems(itemFi
                             rangeStart && rangeEnd) {
 
                             var freeBusyListener = { // calIGenericOperationListener:
                                 onResult: function freeBusyListener_onResult(request, result) {
                                     if (!Components.isSuccessCode(request.status)) {
                                         throw request.status;
                                     }
                                     var items = [];
-                                    for each (var entry in result) {
+                                    for (var entry of result) {
                                         var item = createEvent();
                                         item.id = (g_busyPhantomItemUuidPrefix + getIcalUTC(entry.interval.start));
                                         item.calendar = this_.superCalendar;
                                         item.title = g_busyItemTitle;
                                         item.startDate = entry.interval.start;
                                         item.endDate = entry.interval.end;
                                         item.makeImmutable();
                                         items.push(item);
@@ -1350,33 +1350,33 @@ function calWcapCalendar_replayChangesOn
                 if (!Components.isSuccessCode(status)) {
                     request.execRespFunc(status); // any error on writing breaks whole operation
                 }
             }
         };
         var request = new calWcapRequest(
             function netFinishedRespFunc(err, data) {
                 var modifiedIds = {};
-                for each (var item in request.m_modifiedItems) {
+                for (var item of request.m_modifiedItems) {
                     var dtCreated = item.getProperty("CREATED");
                     var bAdd = (!dtCreated || !dtFrom || dtCreated.compare(dtFrom) >= 0);
                     modifiedIds[item.id] = true;
                     if (bAdd) {
                         log("replayChangesOn(): new item " + item.id, this_);
                         if (this_.offlineStorage) {
                             this_.offlineStorage.addItem(item, writeListener);
                         }
                     } else {
                         log("replayChangesOn(): modified item " + item.id, this_);
                         if (this_.offlineStorage) {
                             this_.modifyItem(item, null, writeListener);
                         }
                     }
                 }
-                for each (var item in request.m_deletedItems) {
+                for (var item of request.m_deletedItems) {
                     // don't delete anything that has been touched by lastmods:
                     if (modifiedIds[item.id]) {
                         log("replayChangesOn(): skipping deletion of " + item.id, this_);
                     } else if (isParent(item)) {
                         log("replayChangesOn(): deleted item " + item.id, this_);
                         if (this_.offlineStorage) {
                             this_.offlineStorage.deleteItem(item, writeListener);
                         }
--- a/calendar/providers/wcap/calWcapRequest.js
+++ b/calendar/providers/wcap/calWcapRequest.js
@@ -77,17 +77,17 @@ calWcapRequest.prototype = {
     },
 
     toString: function calWcapRequest_toString() {
         var ret = ("calWcapRequest id=" + this.id +
                    ", parent-id=" + (this.parentRequest ? this.parentRequest.id : "<none>") +
                    " (" + this.m_logContext + ")");
         if (LOG_LEVEL > 2 && this.m_attachedRequests.length > 0) {
             ret += "\nattached requests:";
-            for each (var req in this.m_attachedRequests) {
+            for (var req of this.m_attachedRequests) {
                 ret += ("\n#" + req.id + "\t" + req);
             }
         }
         ret += (", isPending=" + this.isPending);
         ret += (", status=" + errorToString(this.status));
         return ret;
     },
 
--- a/calendar/providers/wcap/calWcapSession.js
+++ b/calendar/providers/wcap/calWcapSession.js
@@ -53,32 +53,32 @@ function getWcapSessionFor(calendar, uri
     let session = getWcapSessionFor.m_sessions[contextId];
 
     if (!session) {
         session = new calWcapSession(contextId);
         getWcapSessionFor.m_sessions[contextId] = session;
 
         let defaultCal = null;
         let registeredCalendars = session.getRegisteredCalendars();
-        for each (let regCal in registeredCalendars) {
+        for (let regCal of registeredCalendars) {
             if (regCal.isDefaultCalendar) {
                 defaultCal = regCal;
                 break;
             }
         }
 
         if (defaultCal) {
             session.defaultCalendar = defaultCal;
             let [defaultSpec,] = splitUriParams(defaultCal.uri);
             session.uri = cal.makeURL(defaultSpec);
             session.credentials.userId = defaultCal.getProperty("user_id");
             log("default calendar found.", defaultCal);
 
             // check and fix changing urls (autoconf) of subscribed calendars here:
-            for each (let regCal in registeredCalendars) {
+            for (let regCal of registeredCalendars) {
                 if (!regCal.isDefaultCalendar) {
                     let [spec, params] = splitUriParams(regCal.uri);
                     if (spec != defaultSpec) {
                         log("fixing url of subscribed calendar: " + regCal.calId, session);
                         let uri = regCal.uri.clone();
                         uri.spec = (defaultSpec + params);
                         regCal.uri = uri;
                         regCal.setProperty("uri", uri.spec);
@@ -499,20 +499,20 @@ calWcapSession.prototype = {
                     var defaultCal = this_.defaultCalendar;
                     if (defaultCal && cals[defaultCal.calId] && // default calendar is registered
                         getPref("calendar.wcap.subscriptions", true) &&
                         !defaultCal.getProperty("subscriptions_registered")) {
 
                         var hasSubscriptions = false;
                         // post register subscribed calendars:
                         var list = this_.getUserPreferences("X-NSCP-WCAP-PREF-icsSubscribed");
-                        for each (var item in list) {
+                        for (var item of list) {
                             var ar = item.split(',');
                             // ',', '$' are not encoded. ',' can be handled here. WTF.
-                            for each (var a in ar) {
+                            for (var a of ar) {
                                 var dollar = a.indexOf('$');
                                 if (dollar >= 0) {
                                     var calId = a.substring(0, dollar);
                                     if (calId != this_.defaultCalId) {
                                         cals[calId] = null;
                                         hasSubscriptions = true;
                                     }
                                 }
@@ -623,17 +623,17 @@ calWcapSession.prototype = {
                     onResult: function search_onResult(request, result) {
                         try {
                             if (!Components.isSuccessCode(request.status)) {
                                 throw request.status;
                             }
                             if (result.length < 1) {
                                 throw Components.results.NS_ERROR_UNEXPECTED;
                             }
-                            for each (let calendar in result) {
+                            for (let calendar of result) {
                                 // user may have dangling users referred in his subscription list, so
                                 // retrieve each by each, don't break:
                                 try {
                                     var calId = calendar.calId;
                                     if ((cals[calId] !== undefined) && !retrievedCals[calId]) {
                                         retrievedCals[calId] = calendar;
                                         if (respFunc) {
                                             respFunc(calendar);
@@ -791,17 +791,17 @@ calWcapSession.prototype = {
 
     get userId() {
         return this.credentials.userId;
     },
 
     get defaultCalId() {
         var list = this.getUserPreferences("X-NSCP-WCAP-PREF-icsCalendar");
         var id = null;
-        for each (var item in list) {
+        for (var item of list) {
             if (item.length > 0) {
                 id = item;
                 break;
             }
         }
         return (id ? id : this.credentials.userId);
     },
 
@@ -822,17 +822,17 @@ calWcapSession.prototype = {
         } catch (exc) {
         }
         return null;
     },
 
     getRegisteredCalendars: function calWcapSession_getRegisteredCalendars(asAssocObj) {
         let registeredCalendars = (asAssocObj ? {} : []);
         let cals = cal.getCalendarManager().getCalendars({});
-        for each (let calendar in cals) {
+        for (let calendar of cals) {
             calendar = this.belongsTo(calendar);
             if (calendar) {
                 if (asAssocObj) {
                     registeredCalendars[calendar.calId] = calendar;
                 } else {
                     registeredCalendars.push(calendar);
                 }
             }
@@ -856,17 +856,17 @@ calWcapSession.prototype = {
         }
         return alarmStart;
     },
 
     getDefaultAlarmEmails: function calWcapSession_getDefaultAlarmEmails(out_count) {
         var ret = [];
         var ar = this.getUserPreferences("X-NSCP-WCAP-PREF-ceDefaultAlarmEmail");
         if (ar.length > 0 && ar[0].length > 0) {
-            for each (var i in ar) {
+            for (var i of ar) {
                 ret = ret.concat(i.split(/[;,]/).map(String.trim));
             }
         }
         out_count.value = ret.length;
         return ret;
     },
 
     // calICalendarSearchProvider:
@@ -1097,17 +1097,17 @@ calWcapSession.prototype = {
         try {
             // make sure the calendar belongs to this session and is the default calendar,
             // then remove all subscribed calendars:
             aCalendar = this.belongsTo(aCalendar);
             if (aCalendar && aCalendar.isDefaultCalendar) {
                 getFreeBusyService().removeProvider(this);
                 getCalendarSearchService().removeProvider(this);
                 var registeredCalendars = this.getRegisteredCalendars();
-                for each (var regCal in registeredCalendars) {
+                for (var regCal of registeredCalendars) {
                     try {
                         if (!regCal.isDefaultCalendar) {
                             cal.getCalendarManager().unregisterCalendar(regCal);
                         }
                     } catch (exc) {
                         this.notifyError(exc);
                     }
                 }
@@ -1123,17 +1123,17 @@ calWcapSession.prototype = {
 };
 
 function confirmInsecureLogin(uri)
 {
     if (!confirmInsecureLogin.m_confirmedHttpLogins) {
         confirmInsecureLogin.m_confirmedHttpLogins = {};
         var confirmedHttpLogins = getPref("calendar.wcap.confirmed_http_logins", "");
         var tuples = confirmedHttpLogins.split(',');
-        for each (var tuple in tuples) {
+        for (var tuple of tuples) {
             var ar = tuple.split(':');
             confirmInsecureLogin.m_confirmedHttpLogins[ar[0]] = ar[1];
         }
     }
 
     var bConfirmed = false;
 
     var host = uri.hostPort;
--- a/calendar/resources/content/datetimepickers/datetimepickers.xml
+++ b/calendar/resources/content/datetimepickers/datetimepickers.xml
@@ -122,17 +122,17 @@
       <method name="parseLanguageDate">
         <parameter name="aValue"/>
         <body><![CDATA[
            if (!aValue) {
              return null;
            }
            var val = aValue.toLowerCase();
            // Look for the easy ones like today, tomorrow, etc
-           for each (var rel in this.mRelativeDates) {
+           for (var rel of this.mRelativeDates) {
              if (val == rel.word) {
                var now = new Date();
                now.setDate(now.getDate()+rel.offset);
                return now;
              }
            }
 
            var parser = this;
@@ -181,18 +181,18 @@
                newVal = newVal.replace(' ', '/');
                return this.parseDateTime(newVal);
              }
           }
 
           // Now for the cool 'next' and 'last'
           var words = val.split(' ');
           var offset, day;
-          for each (let word in words) {
-            for each (let rel in this.mRelationWords) {
+          for (let word of words) {
+            for (let rel of this.mRelationWords) {
               if (word == rel.word) {
                 offset = rel.offset;
                 break;
               }
             }
             for (var i in this.mDayNames) {
               if (word == this.mDayNames[i]) {
                 day = getDateForDay(word);
--- a/calendar/test/mozmill/shared-modules/timezone-utils.js
+++ b/calendar/test/mozmill/shared-modules/timezone-utils.js
@@ -62,17 +62,17 @@ function verify(controller, dates, timez
       // previous day
       if(day != undefined && day == -1) {
         calUtils.back(controller, 1);
         stackNode = (new elementslib.Lookup(controller.window.document, dayStack)).getNode();
       }
       
       calUtils.findEventsInNode(stackNode, eventNodes);
       
-      for each (node in eventNodes) {
+      for (let node of eventNodes) {
         if (Math.abs(timeY - node.boxObject.y) < allowedDifference &&
                      timezones[tz] == node.mOccurrence.title) {
           found = true;
           break;
         }
       }
       
       if(day != undefined && day == 1) {
--- a/calendar/test/unit/test_alarmservice.js
+++ b/calendar/test/unit/test_alarmservice.js
@@ -62,17 +62,17 @@ var alarmObserver = {
         this.expectedMap[aCalendar.id][aItem.hashId][aAlarm.icalString] = aExpected;
     },
 
     expectOccurrences: function obs_expectOccurrences(aCalendar, aItem, aAlarm, aExpectedArray) {
         // we need to be earlier than the first occurrence
         let dt = aItem.startDate.clone();
         dt.second -= 1;
 
-        for each (let expected in aExpectedArray) {
+        for (let expected of aExpectedArray) {
             let occ = aItem.recurrenceInfo.getNextOccurrence(dt);
             dt = occ.startDate;
             this.expectResult(aCalendar, occ, aAlarm, expected);
         }
     },
 
     checkExpected: function obs_checkExpected() {
         for (let calId in this.expectedMap) {
@@ -133,17 +133,17 @@ function initializeAlarmService() {
                                        .getService(Components.interfaces.calIAlarmService)
                                        .wrappedJSObject;
     ok(!alarmObserver.service.mStarted);
 
     alarmObserver.service.startup();
     ok(alarmObserver.service.mStarted);
 
     // we need to replace the existing observers with our observer
-    for each (let obs in alarmObserver.service.mObservers.mInterfaces) {
+    for (let obs of alarmObserver.service.mObservers.mInterfaces) {
         alarmObserver.service.removeObserver(obs);
     }
     alarmObserver.service.addObserver(alarmObserver);
 }
 
 function createAlarmFromDuration(aOffset) {
     let alarm = cal.createAlarm();
 
--- a/calendar/test/unit/test_ics.js
+++ b/calendar/test/unit/test_ics.js
@@ -111,17 +111,17 @@ function test_roundtrip() {
         if ("expectedDateProps" in data) {
             checkProps(data.expectedDateProps, event.startDate);
             checkProps(data.expectedDateProps, event.endDate);
         }
     }
 
     let icssrv = cal.getIcsService();
 
-    for each (var data in test_data) {
+    for (var data of test_data) {
         // First round, use the icalString setter which uses synchronous parsing
         dump("Checking" + data.ics + "\n");
         let event = createEventFromIcalString(data.ics);
         checkEvent(data, event);
 
         // Now, try the same thing with asynchronous parsing. We need a copy of
         // the data variable, otherwise javascript will mix the data between
         // foreach loop iterations.
--- a/calendar/test/unit/test_ics_service.js
+++ b/calendar/test/unit/test_ics_service.js
@@ -187,17 +187,17 @@ function test_icalcomponent() {
        ["dueTime", cal.createDateTime("20120101T010103")],
        ["stampTime", cal.createDateTime("20120101T010104")],
        ["createdTime", cal.createDateTime("20120101T010105")],
        ["completedTime", cal.createDateTime("20120101T010106")],
        ["lastModified", cal.createDateTime("20120101T010107")],
        ["recurrenceId", cal.createDateTime("20120101T010108")]
     ];
 
-    for each (let prop in props) {
+    for (let prop of props) {
         check_getset.apply(null, prop);
     }
 }
 
 function test_param() {
     let svc = cal.getIcsService();
     let prop = svc.createIcalProperty("DTSTART");
     prop.value = "20120101T010101";
--- a/calendar/test/unit/test_providers.js
+++ b/calendar/test/unit/test_providers.js
@@ -314,17 +314,17 @@ function run_test() {
     * (2) Perform a getItem() call.
     * The properties of the returned item are compared with the passed item.
     */
     function testGetItem(aItem) {
         // get calendars
         var calArray = [];
         calArray.push(getStorageCal());
         calArray.push(getMemoryCal());
-        for each (let calendar in calArray) {
+        for (let calendar of calArray) {
             // implement listener
             var count = 0;
             var returnedItem = null;
             var listener = {
                 onOperationComplete: function(aCalendar,
                                               aStatus,
                                               aOperationType,
                                               aId,
--- a/calendar/test/unit/test_storage.js
+++ b/calendar/test/unit/test_storage.js
@@ -66,17 +66,17 @@ function testAttachRoundtrip() {
             let relations = item.getRelations({});
             let rel = relations[0];
             equal(relations.length, 1);
             equal(rel.relType, "SIBLING");
             equal(rel.relId, "VALUE");
             equal(rel.getParameter("FOO"), "BAR");
 
             // Check recurrence item
-            for each (let ritem in item.recurrenceInfo.getRecurrenceItems({})) {
+            for (let ritem of item.recurrenceInfo.getRecurrenceItems({})) {
                 if (ritem instanceof Components.interfaces.calIRecurrenceRule) {
                     equal(ritem.type, "MONTHLY");
                     equal(ritem.interval, 2);
                     equal(ritem.count, 5);
                     equal(ritem.isByCount, true);
                     equal(ritem.getComponent("BYDAY", {}).toString(), [2].toString());
                     equal(ritem.isNegative, false);
                 } else if (ritem instanceof Components.interfaces.calIRecurrenceDate) {