Bug 1198412 - Use Array.includes in calendar. r=Fallen
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 22 Sep 2015 10:51:50 +0200
changeset 18416 990bb78f92846d729b4cba846d0a0f6ea6fceb40
parent 18415 5e95881b6b2511415a53c349b65c08513979f582
child 18417 e326fb651da9c16bfd64f77c19b72c92d1d4c214
push id11278
push userarchaeopteryx@coole-files.de
push dateTue, 22 Sep 2015 09:21:25 +0000
treeherdercomm-central@e326fb651da9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFallen
bugs1198412
Bug 1198412 - Use Array.includes in calendar. r=Fallen
calendar/base/content/calendar-base-view.xml
calendar/base/content/calendar-dnd-listener.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/dialogs/calendar-dialog-utils.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/import-export.js
calendar/base/content/preferences/alarms.js
calendar/base/content/preferences/general.js
calendar/base/content/widgets/calendar-widgets.xml
calendar/base/modules/calAlarmUtils.jsm
calendar/base/modules/calExtract.jsm
calendar/base/src/calApplicationUtils.js
calendar/base/src/calCalendarManager.js
calendar/base/src/calFilter.js
calendar/base/src/calTimezoneService.js
calendar/base/src/calUtils.js
calendar/lightning/components/calItipProtocolHandler.js
calendar/providers/caldav/calDavCalendar.js
calendar/providers/caldav/calDavRequestHandlers.js
calendar/providers/gdata/modules/gdataRequest.jsm
calendar/providers/gdata/modules/gdataSession.jsm
calendar/providers/gdata/modules/shim/Loader.jsm
calendar/providers/ics/calICSCalendar.js
calendar/providers/wcap/calWcapCalendarItems.js
calendar/resources/content/datetimepickers/datetimepickers.xml
calendar/test/mozmill/eventDialog/testEventDialog.js
calendar/test/mozmill/shared-modules/calendar-utils.js
calendar/test/mozmill/testLocalICS.js
calendar/test/unit/test_alarm.js
calendar/test/unit/test_attendee.js
calendar/test/unit/test_bug668222.js
calendar/test/unit/test_recur.js
calendar/test/unit/test_relation.js
--- a/calendar/base/content/calendar-base-view.xml
+++ b/calendar/base/content/calendar-base-view.xml
@@ -615,17 +615,17 @@
       <!-- A preference handler which is called by the preference observer.
            Can be overwritten in derived bindings. -->
       <method name="handleCommonPreference">
         <parameter name="aSubject"/>
         <parameter name="aTopic"/>
         <parameter name="aPreference"/>
         <body><![CDATA[
            // refresh view if categories seem to have changed
-           if (aPreference.indexOf("calendar.category.color") == 0) {
+           if (aPreference.startsWith("calendar.category.color")) {
                this.refreshView();
                return;
            }
            switch (aPreference) {
                case "calendar.week.d0sundaysoff":
                case "calendar.week.d1mondaysoff":
                case "calendar.week.d2tuesdaysoff":
                case "calendar.week.d3wednesdaysoff":
--- a/calendar/base/content/calendar-dnd-listener.js
+++ b/calendar/base/content/calendar-dnd-listener.js
@@ -228,17 +228,17 @@ calDNDBaseObserver.prototype = {
         try {
             data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
         } catch (exc) {
             // we currently only supports strings:
             return;
         }
 
         // Treat unicode data with VEVENT in it as text/calendar
-        if (bestFlavor.value == "text/unicode" && data.toString().indexOf("VEVENT") != -1) {
+        if (bestFlavor.value == "text/unicode" && data.toString().includes("VEVENT")) {
             bestFlavor.value = "text/calendar";
         }
 
         var destCal = getSelectedCalendar();
         switch (bestFlavor.value) {
             case "text/calendar":
 #ifdef XP_MACOSX
                 // Mac likes to convert all \r to \n, we need to reverse this.
--- a/calendar/base/content/calendar-item-editing.js
+++ b/calendar/base/content/calendar-item-editing.js
@@ -106,17 +106,17 @@ function setDefaultItemValues(aItem, aCa
         } else {
             let defaultStart = Preferences.get("calendar.task.defaultstart", "none");
             if (Preferences.get("calendar.alarms.onfortodos", 0) == 1 && defaultStart == "none") {
                 // start date is required if we want to set an alarm
                 defaultStart = "offsetcurrent";
             }
 
             let units = Preferences.get("calendar.task.defaultstartoffsetunits", "minutes");
-            if (["days", "hours", "minutes"].indexOf(units) < 0) {
+            if (!["days", "hours", "minutes"].includes(units)) {
                 units = "minutes";
             }
             let startOffset = cal.createDuration();
             startOffset[units] = Preferences.get("calendar.task.defaultstartoffset", 0);
             let start;
 
             switch (defaultStart) {
                 case "none":
@@ -151,17 +151,17 @@ function setDefaultItemValues(aItem, aCa
         }
 
         if (aEndDate) {
             aItem.dueDate = aEndDate.clone();
         } else {
             let defaultDue = Preferences.get("calendar.task.defaultdue", "none");
 
             let units = Preferences.get("calendar.task.defaultdueoffsetunits", "minutes");
-            if (["days", "hours", "minutes"].indexOf(units) < 0) {
+            if (!["days", "hours", "minutes"].includes(units)) {
                 units = "minutes";
             }
             let dueOffset = cal.createDuration();
             dueOffset[units] = Preferences.get("calendar.task.defaultdueoffset", 0);
 
             let start = aItem.entryDate ? aItem.entryDate.clone() : initDate.clone();
             let due;
 
--- a/calendar/base/content/calendar-month-view.xml
+++ b/calendar/base/content/calendar-month-view.xml
@@ -923,17 +923,17 @@
       </method>
 
       <method name="hideDaysOff">
         <body><![CDATA[
           var columns = document.getAnonymousElementByAttribute(this, "anonid", "monthgridcolumns").childNodes;
           let headerkids = document.getAnonymousElementByAttribute(this, "anonid", "labeldaybox").childNodes;
           for (var i in columns) {
             var dayForColumn = (Number(i) + this.mWeekStartOffset) % 7;
-            var dayOff = (this.mDaysOffArray.indexOf(dayForColumn) != -1);
+            var dayOff = this.mDaysOffArray.includes(dayForColumn);
             columns[i].collapsed = dayOff && !this.mDisplayDaysOff;
             headerkids[i].collapsed = dayOff && !this.mDisplayDaysOff;
           }
         ]]></body>
       </method>
 
       <method name="findDayBoxForDate">
         <parameter name="aDate"/>
--- a/calendar/base/content/calendar-multiday-view.xml
+++ b/calendar/base/content/calendar-multiday-view.xml
@@ -3253,17 +3253,17 @@
 
           let computedDateList = new Array();
           let startDate = this.mStartDate.clone();
           while (startDate.compare(this.mEndDate) <= 0) {
               let workday = startDate.clone();
               workday.makeImmutable();
               if (this.mDisplayDaysOff) {
                   computedDateList.push(workday);
-              } else if (this.mDaysOffArray.indexOf(startDate.weekday) == -1) {
+              } else if (!this.mDaysOffArray.includes(startDate.weekday)) {
                   computedDateList.push(workday);
               }
               startDate.day += 1;
           }
           this.mDateList = computedDateList;
 
           // unselect previous selected event upon switch views, otherwise those
           // events will stay selected forever, if select other events after
--- a/calendar/base/content/dialogs/calendar-dialog-utils.js
+++ b/calendar/base/content/dialogs/calendar-dialog-utils.js
@@ -333,17 +333,17 @@ function saveReminder(item) {
  * first alarm action the calendar supports.
  *
  * @return      The default alarm type.
  */
 function getDefaultAlarmType() {
     let calendar = getCurrentCalendar();
     let alarmCaps = calendar.getProperty("capabilities.alarms.actionValues") ||
                     ["DISPLAY"];
-    return (alarmCaps.indexOf("DISPLAY") < 0 ? alarmCaps[0] : "DISPLAY");
+    return (alarmCaps.includes("DISPLAY") ? "DISPLAY" : alarmCaps[0]);
 }
 
 /**
  * Get the currently selected calendar. For dialogs with a menulist of
  * calendars, this is the currently chosen calendar, otherwise its the fixed
  * calendar from the window's item.
  *
  * @return      The currently selected calendar.
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
@@ -509,17 +509,17 @@
             }
 
             let addressLists = mailingList.addressLists;
             for (var i=0;i<addressLists.length;i++) {
               let abCard = addressLists.queryElementAt(i, Components.interfaces.nsIAbCard);
               let thisId = abCard.primaryEmail;
               if (abCard.displayName.length > 0) {
                   let rCn = abCard.displayName;
-                  if (rCn.indexOf(",") >= 0) {
+                  if (rCn.includes(",")) {
                       rCn = '"' + rCn + '"';
                   }
                   thisId = rCn + " <" + thisId + ">";
               }
               if (in_list(attendees, thisId)) continue;
 
               if (abCard.displayName.length > 0) {
                 let ml = this._findListInAddrBooks(abCard.displayName);
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -1607,17 +1607,17 @@ function updatePrivacy() {
             for (var i = 0; i < numChilds; i++) {
                 var node = menupopup.childNodes[i];
                 if (node.hasAttribute("privacy")) {
                     var currentPrivacyValue = node.getAttribute("privacy");
                     // Collapsed state
 
                     // Hide the toolbar if the value is unsupported or is for a
                     // specific provider and doesn't belong to the current provider.
-                    if (privacyValues.indexOf(currentPrivacyValue) < 0 ||
+                    if (!privacyValues.includes(currentPrivacyValue) ||
                         (currentProvider && currentProvider != calendar.type)) {
                         node.setAttribute("collapsed", "true");
                     } else {
                         node.removeAttribute("collapsed");
                     }
 
                     // Checked state
                     if (gPrivacy == currentPrivacyValue) {
@@ -1636,17 +1636,17 @@ function updatePrivacy() {
             var node = menupopup.childNodes[i];
             var currentProvider = node.getAttribute("provider");
             if (node.hasAttribute("privacy")) {
                 var currentPrivacyValue = node.getAttribute("privacy");
                 // Collapsed state
 
                 // Hide the menu if the value is unsupported or is for a
                 // specific provider and doesn't belong to the current provider.
-                if (privacyValues.indexOf(currentPrivacyValue) < 0 ||
+                if (!privacyValues.includes(currentPrivacyValue) ||
                     (currentProvider && currentProvider != calendar.type)) {
                     node.setAttribute("collapsed", "true");
                 } else {
                     node.removeAttribute("collapsed");
                 }
 
                 // Checked state
                 if (gPrivacy == currentPrivacyValue) {
@@ -1665,17 +1665,17 @@ function updatePrivacy() {
             var node = privacyPanel.childNodes[i];
             var currentProvider = node.getAttribute("provider");
             if (node.hasAttribute("privacy")) {
                 var currentPrivacyValue = node.getAttribute("privacy");
 
                 // Hide the panel if the value is unsupported or is for a
                 // specific provider and doesn't belong to the current provider,
                 // or is not the items privacy value
-                if (privacyValues.indexOf(currentPrivacyValue) < 0 ||
+                if (!privacyValues.includes(currentPrivacyValue) ||
                     (currentProvider && currentProvider != calendar.type) ||
                     gPrivacy != currentPrivacyValue) {
                     node.setAttribute("collapsed", "true");
                 } else {
                     node.removeAttribute("collapsed");
                     hasAnyPrivacyValue = true;
                 }
             }
--- a/calendar/base/content/import-export.js
+++ b/calendar/base/content/import-export.js
@@ -274,17 +274,17 @@ function saveEventsToFile(calendarEventA
             // For some reason the wrong filter was selected, assume default extension
             filterIndex = defaultCIDIndex;
         }
 
         let exporter = Components.classes[contractids[filterIndex]]
                                  .getService(Components.interfaces.calIExporter);
 
         let filePath = fp.file.path;
-        if (filePath.indexOf(".") == -1) {
+        if (!filePath.includes(".")) {
             filePath += "."+exporter.getFileTypes({})[0].defaultExtension;
         }
 
         const nsILocalFile = Components.interfaces.nsILocalFile;
         const nsIFileOutputStream = Components.interfaces.nsIFileOutputStream;
 
         let outputStream;
         let localFileInstance = Components.classes["@mozilla.org/file/local;1"]
--- a/calendar/base/content/preferences/alarms.js
+++ b/calendar/base/content/preferences/alarms.js
@@ -44,17 +44,17 @@ var gAlarmsPane = {
 
     /**
      * Handler function to be called when the calendar.alarms.soundURL pref has
      * changed. Updates the label in the dialog.
      */
     readSoundLocation: function gAP_readSoundLocation() {
         var soundUrl = document.getElementById("alarmSoundFileField");
         soundUrl.value = document.getElementById("calendar.alarms.soundURL").value;
-        if (soundUrl.value.indexOf("file://") == 0) {
+        if (soundUrl.value.startsWith("file://")) {
             soundUrl.label = this.convertURLToLocalFile(soundUrl.value).leafName;
         } else {
             soundUrl.label = soundUrl.value;
         }
         soundUrl.image = "moz-icon://" + soundUrl.label + "?size=16";
         return undefined;
     },
 
--- a/calendar/base/content/preferences/general.js
+++ b/calendar/base/content/preferences/general.js
@@ -65,19 +65,19 @@ var gCalendarGeneralPane = {
     },
 
     updateDefaultTodoDates: function gCGP_updateDefaultTodoDates() {
         let defaultDue = document.getElementById("default_task_due").value;
         let defaultStart = document.getElementById("default_task_start").value;
         let offsetValues = ["offsetcurrent", "offsetnexthour"];
 
         document.getElementById("default_task_due_offset")
-                .style.visibility = offsetValues.indexOf(defaultDue) > -1 ? "" : "hidden";
+                .style.visibility = offsetValues.includes(defaultDue) ? "" : "hidden";
         document.getElementById("default_task_start_offset")
-                .style.visibility = offsetValues.indexOf(defaultStart) > -1 ? "" : "hidden";
+                .style.visibility = offsetValues.includes(defaultStart) ? "" : "hidden";
 
         updateMenuLabelsPlural("default_task_start_offset_text", "default_task_start_offset_units");
         updateMenuLabelsPlural("default_task_due_offset_text", "default_task_due_offset_units");
     },
 
     updateItemtypeDeck: function() {
         let panelId = document.getElementById("defaults-itemtype-menulist").value;
         let panel = document.getElementById(panelId);
--- a/calendar/base/content/widgets/calendar-widgets.xml
+++ b/calendar/base/content/widgets/calendar-widgets.xml
@@ -337,18 +337,17 @@
       <method name="isVisible">
         <parameter name="aMode"/>
         <body><![CDATA[
             var lMode = aMode || this.currentMode;
             if (!this.isVisibleInMode(lMode)) {
                 return false;
             }
             var collapsedModes = this.getAttribute("collapsedinmodes").split(",");
-            var modeIndex = collapsedModes.indexOf(lMode);
-            return (modeIndex == -1);
+            return (!collapsedModes.includes(lMode));
         ]]></body>
       </method>
 
       <method name="setModeAttribute"> 
         <parameter name="aModeAttribute"/>
         <parameter name="aModeValue"/>
         <parameter name="amode"/>
         <body><![CDATA[
@@ -440,17 +439,17 @@
             var lMode = aMode || this.currentMode;
             var display = true;
             var lModes = new Array();
             if (this.hasAttribute("mode")) {
                 var modeString = this.getAttribute("mode");
                 lModes = modeString.split(",");
             }
             if (lModes && lModes.length > 0) {
-                display = lModes.indexOf(lMode) > -1;
+                display = lModes.includes(lMode);
             }
             return display;
         ]]></body>
       </method>
 
       <method name="onModeModified">
         <parameter name="aEvent"/>
         <parameter name="aBinding"/>
--- a/calendar/base/modules/calAlarmUtils.jsm
+++ b/calendar/base/modules/calAlarmUtils.jsm
@@ -17,17 +17,17 @@ cal.alarms = {
     setDefaultValues: function cal_alarm_setDefaultValues(aItem) {
         let type = cal.isEvent(aItem) ? "event" : "todo";
         if (Preferences.get("calendar.alarms.onfor" + type + "s", 0) == 1) {
             let alarmOffset = cal.createDuration();
             let alarm = cal.createAlarm();
             let units = Preferences.get("calendar.alarms." + type + "alarmunit", "minutes");
 
             // Make sure the alarm pref is valid, default to minutes otherwise
-            if (["weeks", "days", "hours", "minutes", "seconds"].indexOf(units) < 0) {
+            if (!["weeks", "days", "hours", "minutes", "seconds"].includes(units)) {
                 units = "minutes";
             }
 
             alarmOffset[units] = Preferences.get("calendar.alarms." + type + "alarmlen", 0);
             alarmOffset.normalize();
             alarmOffset.isNegative = true;
             if (type == "todo" && !aItem.entryDate) {
                 // You can't have an alarm if the entryDate doesn't exist.
@@ -37,17 +37,17 @@ cal.alarms = {
             alarm.offset = alarmOffset;
 
             // Default to a display alarm, unless the calendar doesn't support
             // it or we have no calendar yet. (Man this is hard to wrap)
             let actionValues = ((aItem.calendar &&
                                  aItem.calendar.getProperty("capabilities.alarms.actionValues")) ||
                                 ["DISPLAY"]);
 
-            alarm.action = (actionValues.indexOf("DISPLAY") < 0 ? actionValues[0] : "DISPLAY");
+            alarm.action = (actionValues.includes("DISPLAY") ? "DISPLAY" : actionValues[0]);
             aItem.addAlarm(alarm);
         }
     },
 
     /**
      * Calculate the alarm date for a calIAlarm.
      *
      * @param aItem     The item used to calculate the alarm date.
--- a/calendar/base/modules/calExtract.jsm
+++ b/calendar/base/modules/calExtract.jsm
@@ -398,17 +398,17 @@ Extractor.prototype = {
             while ((res = re.exec(this.email)) != null) {
                 if (!this.limitNums(res, this.email) && !this.limitChars(res, this.email)) {
                     let day = parseInt(res[positions[1]], 10);
                     let month = res[positions[2]];
                     let year = parseInt(this.normalizeYear(res[positions[3]]), 10);
 
                     if (this.isValidDay(day)) {
                         for (let i = 0; i < 12; i++) {
-                            if (this.months[i].split("|").indexOf(month.toLowerCase()) != -1) {
+                            if (this.months[i].split("|").includes(month.toLowerCase())) {
                                 let rev = this.prefixSuffixStartEnd(res, relation, this.email);
                                 this.guess(year, i + 1, day, null, null,
                                            rev.start, rev.end, rev.pattern, rev.relation, pattern);
                                 break;
                             }
                         }
                     }
                 }
@@ -443,17 +443,17 @@ Extractor.prototype = {
             while ((res = re.exec(this.email)) != null) {
                 if (!this.limitNums(res, this.email) && !this.limitChars(res, this.email)) {
                     let day = this.parseNumber(res[positions[1]], this.numbers);
                     let month = res[positions[2]];
 
                     if (this.isValidDay(day)) {
                         for (let i = 0; i < 12; i++) {
                             let ms = this.months[i].unescape().split("|");
-                            if (ms.indexOf(month.toLowerCase()) != -1) {
+                            if (ms.includes(month.toLowerCase())) {
                                 let date = {year: this.now.getFullYear(), month: i + 1, day: day};
                                 if (this.isPastDate(date, this.now)) {
                                     // find next such date
                                     let item = new Date(this.now.getTime());
                                     while (true) {
                                         item.setDate(item.getDate() + 1);
                                         if (item.getMonth() == date.month - 1 &&
                                             item.getDate() == date.day) {
@@ -1247,17 +1247,17 @@ Extractor.prototype = {
     parseNumber: function parseNumber(number, numbers) {
         let r = parseInt(number, 10);
         // number comes in as plain text, numbers are already adjusted for usage
         // in regular expression
         number = this.cleanPatterns(number);
         if (isNaN(r)) {
             for (let i = 0; i <= 31; i++) {
                 let ns = numbers[i].split("|");
-                if (ns.indexOf(number.toLowerCase()) != -1) {
+                if (ns.includes(number.toLowerCase())) {
                     return i;
                 }
             }
             return -1;
         } else {
             return r;
         }
     },
--- a/calendar/base/src/calApplicationUtils.js
+++ b/calendar/base/src/calApplicationUtils.js
@@ -18,17 +18,17 @@ function launchBrowser(url, event)
   if (!url || (event && event.button != 0)) {
     return;
   }
 
   // 0. Prevent people from trying to launch URLs such as javascript:foo();
   //    by only allowing URLs starting with http or https.
   // XXX: We likely will want to do this using nsIURLs in the future to
   //      prevent sneaky nasty escaping issues, but this is fine for now.
-  if (url.indexOf("http") != 0) {
+  if (!url.startsWith("http")) {
     Components.utils.reportError ("launchBrowser: " +
                                   "Invalid URL provided: " + url +
                                   " Only http:// and https:// URLs are valid.");
     return;
   }
 
   Components.classes["@mozilla.org/uriloader/external-protocol-service;1"]
             .getService(Components.interfaces.nsIExternalProtocolService)
--- a/calendar/base/src/calCalendarManager.js
+++ b/calendar/base/src/calCalendarManager.js
@@ -145,17 +145,17 @@ calCalendarManager.prototype = {
                 // client is used for access, so add our UA String to each
                 // request.
                 let httpChannel = aSubject.QueryInterface(Components.interfaces.nsIHttpChannel);
                 try {
                     // NOTE: For some reason, this observer call doesn't have
                     // the "cal" namespace defined
                     let ua = httpChannel.getRequestHeader("User-Agent");
                     let calUAString = Preferences.get("calendar.useragent.extra");
-                    if (calUAString && ua.indexOf(calUAString) < 0) {
+                    if (calUAString && !ua.includes(calUAString)) {
                         // User-Agent is not a mergeable header. We need to
                         // merge the user agent ourselves.
                         httpChannel.setRequestHeader("User-Agent",
                                                      ua + " " + calUAString,
                                                      false);
                     }
                 } catch (e if e.result == Components.results.NS_ERROR_NOT_AVAILABLE) {
                     // We swallow this error since it means the User Agent
--- a/calendar/base/src/calFilter.js
+++ b/calendar/base/src/calFilter.js
@@ -350,25 +350,25 @@ calFilter.prototype = {
 
         let searchText = this.mFilterText.toLowerCase();
 
         if (!searchText.length || searchText.match(/^\s*$/)) {
             return true;
         }
 
         //XXX TODO: Support specifying which fields to search on
-        for each (let field in ["SUMMARY", "DESCRIPTION", "LOCATION", "URL"]) {
+        for (let field of ["SUMMARY", "DESCRIPTION", "LOCATION", "URL"]) {
             let val = aItem.getProperty(field);
-            if (val && val.toLowerCase().indexOf(searchText) != -1) {
+            if (val && val.toLowerCase().includes(searchText)) {
                 return true;
             }
         }
 
         return aItem.getCategories({}).some(function(cat) {
-            return (cat.toLowerCase().indexOf(searchText) != -1);
+            return cat.toLowerCase().includes(searchText);
         });
     },
 
     /**
      * Checks if the item matches the current filter date range.
      *
      * @param aItem               The item to check.
      * @return                    Returns true if the item falls within the date range
@@ -416,17 +416,17 @@ calFilter.prototype = {
             let cats = [];
 
             if (typeof(props.category) == "string") {
                 cats.push(props.category);
             } else if (Array.isArray(props.category)) {
                 cats = props.category;
             }
             result = cats.some(function(cat) {
-                return aItem.getCategories({}).indexOf(cat) > -1;
+                return aItem.getCategories({}).includes(cat);
             });
         }
 
         // test the status property. Only applies to tasks.
         if (result && props.status != null && cal.isToDo(aItem)) {
             let completed = aItem.isCompleted;
             let current = !aItem.completedDate || today.compare(aItem.completedDate) <= 0;
             let percent = aItem.percentComplete || 0;
--- a/calendar/base/src/calTimezoneService.js
+++ b/calendar/base/src/calTimezoneService.js
@@ -179,17 +179,17 @@ calTimezoneService.prototype = {
     },
 
     // calITimezoneProvider:
     getTimezone: function calTimezoneService_getTimezone(tzid) {
         if (!tzid) {
             cal.ERROR("Unknown timezone requested\n" + cal.STACK(10));
             return null;
         }
-        if (tzid.indexOf("/mozilla.org/") == 0) {
+        if (tzid.startsWith("/mozilla.org/")) {
             // We know that our former tzids look like "/mozilla.org/<dtstamp>/continent/..."
             // The ending of the mozilla prefix is the index of that slash before the
             // continent. Therefore, we start looking for the prefix-ending slash
             // after position 13.
             tzid = tzid.substring(tzid.indexOf("/", 13) + 1);
         }
 
         let tz = this.mZones.get(tzid);
--- a/calendar/base/src/calUtils.js
+++ b/calendar/base/src/calUtils.js
@@ -123,17 +123,17 @@ function calendarDefaultTimezone() {
  *
  * @param aTzid     The timezone id to add
  */
 function saveRecentTimezone(aTzid) {
     let recentTimezones = getRecentTimezones();
     const MAX_RECENT_TIMEZONES = 5; // We don't need a pref for *everything*.
 
     if (aTzid != calendarDefaultTimezone().tzid &&
-        recentTimezones.indexOf(aTzid) < 0) {
+        !recentTimezones.includes(aTzid)) {
         // Add the timezone if its not already the default timezone
         recentTimezones.unshift(aTzid);
         recentTimezones.splice(MAX_RECENT_TIMEZONES);
         Preferences.set("calendar.timezone.recent", JSON.stringify(recentTimezones));
     }
 }
 
 /**
--- a/calendar/lightning/components/calItipProtocolHandler.js
+++ b/calendar/lightning/components/calItipProtocolHandler.js
@@ -106,17 +106,17 @@ ItipContentHandler.prototype = {
         contractID: "@mozilla.org/uriloader/content-handler;1?type=" + ITIP_HANDLER_MIMETYPE,
         classDescription: "Lightning text/calendar content handler",
         interfaces: ItipContentHandlerInterfaces
     }),
 
     handleContent: function (contentType, windowTarget, request) {
         let channel = request.QueryInterface(CI.nsIChannel);
         let uri = channel.URI.spec;
-        if (uri.indexOf(ITIP_HANDLER_PROTOCOL + ":") != 0) {
+        if (!uri.startsWith(ITIP_HANDLER_PROTOCOL + ":")) {
             cal.ERROR("Unexpected iTIP uri: " + uri + "\n");
             return Components.results.NS_ERROR_FAILURE;
         }
         // moz-cal-handle-itip:///?
         let paramString = uri.substring(ITIP_HANDLER_PROTOCOL.length + 4);
         let paramArray = paramString.split("&");
         let paramBlock = { };
         paramArray.forEach(function (v) {
--- a/calendar/providers/caldav/calDavCalendar.js
+++ b/calendar/providers/caldav/calDavCalendar.js
@@ -560,19 +560,19 @@ calDavCalendar.prototype = {
             case "organizerCN":
                 return null; // xxx todo
             case "itip.transport":
                 if (this.hasAutoScheduling || this.hasScheduling) {
                     return this.QueryInterface(Components.interfaces.calIItipTransport);
                 } // else use outbound email-based iTIP (from cal.ProviderBase)
                 break;
             case "capabilities.tasks.supported":
-                return (this.supportedItemTypes.indexOf("VTODO") > -1);
+                return (this.supportedItemTypes.includes("VTODO"));
             case "capabilities.events.supported":
-                return (this.supportedItemTypes.indexOf("VEVENT") > -1);
+                return (this.supportedItemTypes.includes("VEVENT"));
             case "capabilities.autoschedule.supported":
                 return this.hasAutoScheduling;
         }
         return this.__proto__.__proto__.getProperty.apply(this, arguments);
     },
 
     promptOverwrite: function caldav_promptOverwrite(aMethod, aItem, aListener, aOldItem) {
         let overwrite = cal.promptOverwrite(aMethod, aItem, aListener, aOldItem);
@@ -1838,17 +1838,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)
-                    if (thisCalendar.mGenerallySupportedItemTypes.indexOf(compName) >= 0)
+                    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()");
             if (cuprincipal) {
@@ -1963,32 +1963,32 @@ calDavCalendar.prototype = {
             // Google does not yet support OPTIONS but does support scheduling
             // so we'll spoof the DAV header until Google gets fixed
             if (thisCalendar.calendarUri.host == "www.google.com") {
                 dav = "calendar-schedule";
                 // Google also reports an inbox URL distinct from the calendar
                 // URL but a) doesn't use it and b) 405s on etag queries to it
                 thisCalendar.mShouldPollInbox = false;
             }
-            if (dav && dav.indexOf("calendar-auto-schedule") != -1) {
+            if (dav && dav.includes("calendar-auto-schedule")) {
                 if (thisCalendar.verboseLogging()) {
                     cal.LOG("CalDAV: Calendar " + thisCalendar.name +
                             " supports calendar-auto-schedule");
                 }
                 thisCalendar.hasAutoScheduling = true;
                 // leave outbound inbox/outbox scheduling off
-            } else if (dav && dav.indexOf("calendar-schedule") != -1) {
+            } else if (dav && dav.includes("calendar-schedule")) {
                 if (thisCalendar.verboseLogging()) {
                     cal.LOG("CalDAV: Calendar " + thisCalendar.name +
                             " generally supports calendar-schedule");
                 }
                 thisCalendar.hasScheduling = true;
             }
 
-            if (thisCalendar.hasAutoScheduling || (dav && dav.indexOf("calendar-schedule") != -1)) {
+            if (thisCalendar.hasAutoScheduling || (dav && dav.includes("calendar-schedule"))) {
                 // XXX - we really shouldn't register with the fb service
                 // if another calendar with the same principal-URL has already
                 // done so. We also shouldn't register with the fb service if we
                 // don't have an outbox.
                 if (!thisCalendar.hasFreeBusy) {
                     // This may have already been set by fetchCachedMetaData,
                     // we only want to add the freebusy provider once.
                     thisCalendar.hasFreeBusy = true;
@@ -2606,17 +2606,17 @@ calDavCalendar.prototype = {
         }
         return uriComponents.join("/");
     },
     isInbox: function caldav_isInbox(aString) {
         // Note: If you change this, make sure it really returns a boolean
         // value and not null!
         return ((this.hasScheduling || this.hasAutoScheduling) &&
                 (this.mInboxUrl != null) &&
-                aString.indexOf(this.mInboxUrl.spec) == 0);
+                aString.startsWith(this.mInboxUrl.spec));
     },
 
     /**
      * Query contents of scheduling inbox
      *
      */
     pollInbox: function caldav_pollInbox() {
         // If polling the inbox was switched off, no need to poll the inbox.
--- a/calendar/providers/caldav/calDavRequestHandlers.js
+++ b/calendar/providers/caldav/calDavRequestHandlers.js
@@ -540,18 +540,17 @@ webDavSyncHandler.prototype = {
             case "sync-response": // WebDAV Sync draft 0,1,2
                 let r = this.currentResponse;
                 if (r.href && r.href.length) {
                     r.href = this.calendar.ensureDecodedPath(r.href);
                 }
 
                 if ((!r.getcontenttype || r.getcontenttype == "text/plain")  &&
                     r.href &&
-                    r.href.length >= 4 &&
-                    r.href.substr(r.href.length - 4,4) == ".ics") {
+                    r.href.endsWith(".ics")) {
                   // If there is no content-type (iCloud) or text/plain was passed
                   // (iCal Server) for the resource but its name ends with ".ics"
                   // assume the content type to be text/calendar. Apple
                   // iCloud/iCal Server interoperability fix.
                   r.getcontenttype = "text/calendar";
                 }
 
                 // Deleted item
@@ -580,17 +579,17 @@ webDavSyncHandler.prototype = {
                     let itemId = this.calendar.mHrefIndex[r.href];
                     let oldEtag = (itemId && this.calendar.mItemInfoCache[itemId].etag);
 
                     if (!oldEtag || oldEtag != r.getetag) {
                         // Etag mismatch, getting new/updated item.
                         this.itemsNeedFetching.push(r.href);
                     }
                 } else if (r.status &&
-                            r.status.indexOf(" 507") > -1) {
+                           r.status.includes(" 507")) {
                     // webdav-sync says that if a 507 is encountered and the
                     // url matches the request, the current token should be
                     // saved and another request should be made. We don't
                     // actually compare the URL, its too easy to get this
                     // wrong.
 
                     // The 507 doesn't mean the data received is invalid, so
                     // continue processing.
@@ -599,19 +598,19 @@ webDavSyncHandler.prototype = {
                            r.status.indexOf(" 200") &&
                            r.href &&
                            r.href.endsWith("/")) {
                     // iCloud returns status responses for directories too
                     // so we just ignore them if they have status code 200. We
                     // want to make sure these are not counted as unhandled
                     // errors in the next block
                 } else if ((r.getcontenttype &&
-                            r.getcontenttype.substr(0,13) == "text/calendar") ||
+                            r.getcontenttype.startsWith("text/calendar") ||
                            (r.status &&
-                            r.status.indexOf(" 404") == -1)) {
+                            !r.status.includes(" 404"))) {
                     // If the response element is still not handled, log an
                     // error only if the content-type is text/calendar or the
                     // response status is different than 404 not found.  We
                     // don't care about response elements on non-calendar
                     // resources or whose status is not indicating a deleted
                     // resource.
                     cal.WARN("CalDAV: Unexpected response, status: " + r.status + ", href: " + r.href);
                     this.unhandledErrors++;
--- a/calendar/providers/gdata/modules/gdataRequest.jsm
+++ b/calendar/providers/gdata/modules/gdataRequest.jsm
@@ -125,17 +125,17 @@ calGoogleRequest.prototype = {
      * attribute type
      * The type of this reqest. Must be one of
      * GET, ADD, MODIFY, DELETE
      */
     get type() { return this.method; },
 
     set type(v) {
         let valid = [this.GET, this.ADD, this.MODIFY, this.PATCH, this.DELETE];
-        if (valid.indexOf(v) < 0) {
+        if (!valid.includes(v)) {
             throw new Components.Exception("Invalid request type: " + v,
                                             Components.results.NS_ERROR_ILLEGAL_VALUE);
         }
         return (this.method = v);
     },
 
     /**
      * setUploadData
--- a/calendar/providers/gdata/modules/gdataSession.jsm
+++ b/calendar/providers/gdata/modules/gdataSession.jsm
@@ -401,17 +401,17 @@ calGoogleSession.prototype = {
             cal.LOG("[calGoogleCalendar] Freebusy query for " + aCalId +
                     " failed (" + aStatus + "): " + aMessage);
 
             // Usually we would notify with a result, but this causes trouble
             // with Lightning 3.9 and older.
             aListener.onResult({ status: aStatus }, null);
         }.bind(this);
 
-        if (aCalId.indexOf("@") < 0 || aCalId.indexOf(".") < 0 ||
+        if (!aCalId.includes("@") || !aCalId.includes(".") ||
             !aCalId.toLowerCase().startsWith("mailto:")) {
             // No valid email, screw it
             return failSync(Components.results.NS_ERROR_FAILURE, null);
         }
 
         if (aRangeStart) {
             aRangeStart = aRangeStart.getInTimezone(cal.UTC());
         }
--- a/calendar/providers/gdata/modules/shim/Loader.jsm
+++ b/calendar/providers/gdata/modules/shim/Loader.jsm
@@ -79,16 +79,25 @@ function shimIt(global) {
         Object.defineProperty(global.String.prototype, 'includes', {
           enumerable: false,
           configurable: true,
           writable: false,
           value: StringContains
         });
     }
 
+    if (!global.Array.prototype.includes) {
+        Object.defineProperty(global.Array.prototype, 'includes', {
+          enumerable: false,
+          configurable: true,
+          writable: false,
+          value: ArrayIncludes
+        });
+    }
+
     if (!global.Map) {
         global.Map = Map;
     }
     if (!global.Set) {
         global.Set = Set;
     }
 
     if (typeof global.Map.prototype.forEach !== "function") {
@@ -112,16 +121,23 @@ function shimIt(global) {
 /**
  * Implementation for String.prototype.includes/contains.
  */
 function StringContains() {
     return String.prototype.indexOf.apply(this, arguments) !== -1;
 }
 
 /**
+ * Implementation for Array.prototype.includes.
+ */
+function ArrayIncludes() {
+    return Array.prototype.indexOf.apply(this, arguments) !== -1;
+}
+
+/**
  * forEach implementation for Map and Set, for Thunderbird 24
  */
 function MapSetForEach(cb) {
     let iter = this.entries();
     while (1) {
         let k, v;
         try {
             [k,v] = iter.next();
--- a/calendar/providers/ics/calICSCalendar.js
+++ b/calendar/providers/ics/calICSCalendar.js
@@ -661,19 +661,17 @@ calICSCalendar.prototype = {
             dailyBackupFile = null;
 
             return dailyBackupFileName;
         }
 
         function purgeBackupsByType(files, type) {
             // filter out backups of the type we care about.
             var filteredFiles = files.filter(
-                function f(v) {
-                    return (v.name.indexOf("calBackupData_"+pseudoID+"_"+type) != -1)
-                });
+                v => v.name.includes("calBackupData_"+pseudoID+"_"+type));
             // Sort by lastmodifed
             filteredFiles.sort(
                 function s(a,b) {
                     return (a.lastmodified - b.lastmodified);
                 });
             // And delete the oldest files, and keep the desired number of
             // old backups
             var i;
--- a/calendar/providers/wcap/calWcapCalendarItems.js
+++ b/calendar/providers/wcap/calWcapCalendarItems.js
@@ -606,17 +606,17 @@ function calWcapCalendar_tunnelXProps(de
     // tunnel alarm X-MOZ-SNOOZE only if alarm is still set:
     // TODO ALARMSUPPORT still needed when showing alarms as EMAIL for wcap?
     let hasAlarms = destItem.getAlarms({}).length;
     let enumerator = srcItem.propertyEnumerator;
     while (enumerator.hasMoreElements()) {
         try {
             var prop = enumerator.getNext().QueryInterface(Components.interfaces.nsIProperty);
             var name = prop.name;
-            if (name.indexOf("X-MOZ-") == 0) {
+            if (name.startsWith("X-MOZ-")) {
                 switch (name) {
                     // keep snooze stamps for occurrences only and if alarm is still set:
                     case "X-MOZ-SNOOZE-TIME":
                         if (!hasAlarms) {
                             break; // alarm has been reset
                         }
                         // fallthru intended
                     default:
--- a/calendar/resources/content/datetimepickers/datetimepickers.xml
+++ b/calendar/resources/content/datetimepickers/datetimepickers.xml
@@ -155,33 +155,33 @@
                return cal.dateTimeToJsDate(today);
              }
              return null;
            }
 
            // Remove commas
            val = val.replace(',', '');
 
-           if (val.indexOf(' ') == -1) {
+           if (!val.includes(' ')) {
              // Just a single word, or a single date.
              return getDateForDay(val);
            }
 
            // Replace month names with numbers
            for (var i in this.mMonthLongNames) {
-             if (val.indexOf(this.mMonthLongNames[i]) != -1) {
+             if (val.includes(this.mMonthLongNames[i])) {
                var newVal = val.replace(this.mMonthLongNames[i], Number(i)+1);
                newVal = newVal.replace(' ', '/');
                return this.parseDateTime(newVal);
              }
           }
 
           // Same for short month names
            for (var i in this.mMonthShortNames) {
-             if (val.indexOf(this.mMonthShortNames[i]) != -1) {
+             if (val.includes(this.mMonthShortNames[i])) {
                var newVal = val.replace(this.mMonthShortNames[i], Number(i)+1);
                newVal = newVal.replace(' ', '/');
                return this.parseDateTime(newVal);
              }
           }
 
           // Now for the cool 'next' and 'last'
           var words = val.split(' ');
@@ -1924,17 +1924,17 @@
             // matches the "p" character so only "m" is matched as ampm suffix.)
             //
             // digitsExpr has 6 captures, so index of first ampmExpr is 1, of last is 8.
             this.parseTimeRegExp =
               new RegExp("("+ampmExpr+")?\\s?"+digitsExpr+"("+ampmExpr+")?\\s*$");
             this.amRegExp = new RegExp("^(?:"+amExpr+")$");
             this.pmRegExp = new RegExp("^(?:"+pmExpr+")$");
             // build time display format that mimics "%x" format without seconds
-            var ampmSep = (pmProbeString.indexOf(' ') != -1? " " : "");
+            var ampmSep = (pmProbeString.includes(' ') ? " " : "");
 	          if (this.ampmIndex == PRE_INDEX)
               this.kTimeFormatString = "%p" + ampmSep + "%I:%M";
             else if (this.ampmIndex == POST_INDEX)
               this.kTimeFormatString = "%I:%M" + ampmSep + "%p";
             else
               this.kTimeFormatString = "%H:%M";
           ]]>
         </body>
--- a/calendar/test/mozmill/eventDialog/testEventDialog.js
+++ b/calendar/test/mozmill/eventDialog/testEventDialog.js
@@ -249,15 +249,15 @@ function checkTooltip(monthView, row, co
     + '{"class":"tooltipBox"}/{"class":"tooltipHeaderGrid"}/[1]/[0]/[1]');
   controller.assertJS(eventName.getNode().textContent == title);
   
   // check date and time
   // date-time string contains strings formatted in operating system language so check numeric values only
   let dateTime = new elementslib.Lookup(controller.window.document,
     '/id("messengerWindow")/id("calendar-popupset")/id("itemTooltip")/'
     + '{"class":"tooltipBox"}/{"class":"tooltipHeaderGrid"}/[1]/[2]/[1]').getNode().textContent + '';
-  controller.assertJS(dateTime.indexOf(date) != -1 && dateTime.indexOf(startTime) != -1
-    && dateTime.indexOf(endTime) != -1);
+  controller.assertJS(dateTime.includes(date) && dateTime.includes(startTime)
+    && dateTime.includes(endTime));
 }
 
 var teardownTest = function(module) {
   calUtils.deleteCalendars(controller, calendar);
 }
--- a/calendar/test/mozmill/shared-modules/calendar-utils.js
+++ b/calendar/test/mozmill/shared-modules/calendar-utils.js
@@ -418,17 +418,17 @@ function setData(controller, data) {
     dialog + 'id("event-grid-todo-status-row")/id("event-grid-todo-status-picker-box")/'
     + 'id("completed-date-picker")/' + dateInput);
   let percentCompleteInput = new elementslib.Lookup(controller.window.document, dialog
     + 'id("event-grid-todo-status-row")/id("event-grid-todo-status-picker-box")/'
     + 'id("percent-complete-textbox")/anon({"class":"textbox-input-box numberbox-input-box"})/'
     + 'anon({"anonid":"input"})');
   let dateService = Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
                               .getService(Components.interfaces.nsIScriptableDateFormat);
-  let mac = utils.appInfo.os.toLowerCase().indexOf("darwin") != -1;
+  let mac = utils.appInfo.os.toLowerCase().includes("darwin");
   // wait for input elements' values to be populated
   controller.sleep(sleep);
   
   // title
   if (data.title != undefined) {
     if (!mac) {
       controller.keypress(new elementslib.Lookup(controller.window.document, dialog
         + 'id("event-grid-title-row")/id("item-title")/anon({"class":"textbox-input-box"})/'
--- a/calendar/test/mozmill/testLocalICS.js
+++ b/calendar/test/mozmill/testLocalICS.js
@@ -88,17 +88,17 @@ var testLocalICS = function () {
 
   fstream.init(file, -1, 0, 0);
   cstream.init(fstream, "UTF-8", 0, 0);
 
   let str = {};
   cstream.readString(-1, str);
   cstream.close();
 
-  controller.assertJS(str.value.indexOf("SUMMARY:" + title) != -1);
+  controller.assertJS(str.value.includes("SUMMARY:" + title));
 }
 
 var teardownTest = function(module) {
   calUtils.deleteCalendars(controller, calendar);
 }
 
 function handleNewCalendarWizard(wizard) {
   let docEl = wizard.window.document.documentElement;
--- a/calendar/test/unit/test_alarm.js
+++ b/calendar/test/unit/test_alarm.js
@@ -153,17 +153,17 @@ function test_audio_alarm() {
     let sound2 = cal.createAttachment();
     sound2.uri = makeURL("file:///sound2.wav");
 
     // Adding an attachment should work
     alarm.addAttachment(sound);
     let addedAttachments = alarm.getAttachments({});
     equal(addedAttachments.length, 1);
     equal(addedAttachments[0], sound);
-    ok(alarm.icalString.indexOf("ATTACH:file:///sound.wav") > -1);
+    ok(alarm.icalString.includes("ATTACH:file:///sound.wav"));
 
     // Adding twice shouldn't change anything
     alarm.addAttachment(sound);
     addedAttachments = alarm.getAttachments({});
     equal(addedAttachments.length, 1);
     equal(addedAttachments[0], sound);
 
     try {
@@ -305,20 +305,20 @@ function test_xprop() {
 
     // also check X-MOZ-LASTACK prop
     let dt = cal.createDateTime();
     alarm.setProperty("X-MOZ-LASTACK", dt.icalString);
     alarm.action = "DISPLAY";
     alarm.description = "test";
     alarm.related = Ci.calIAlarm.ALARM_RELATED_START
     alarm.offset = createDuration("-PT5M");
-    ok(alarm.icalComponent.serializeToICS().indexOf(dt.icalString) > -1);
+    ok(alarm.icalComponent.serializeToICS().includes(dt.icalString));
 
     alarm.deleteProperty("X-MOZ-LASTACK");
-    ok(!alarm.icalComponent.serializeToICS().indexOf(dt.icalString) > -1);
+    ok(!alarm.icalComponent.serializeToICS().includes(dt.icalString));
     dump("Done\n");
 }
 
 function test_dates() {
     dump("Testing alarm dates...");
     let passed;
     // Initial value
     let alarm = cal.createAlarm();
--- a/calendar/test/unit/test_attendee.js
+++ b/calendar/test/unit/test_attendee.js
@@ -16,22 +16,22 @@ function test_values() {
         // Getting all attendees
         let allAttendees = event.getAttendees(countObj);
         equal(countObj.value, allAttendees.length);
 
         equal(allAttendees.length, expectedAttendees.length);
 
         // Check if all expected attendees are found
         for (let i = 0; i < expectedAttendees.length; i++) {
-            notEqual(allAttendees.indexOf(expectedAttendees[i]), -1);
+            ok(allAttendees.includes(expectedAttendees[i]));
         }
 
         // Check if all found attendees are expected
         for (let i = 0; i < allAttendees.length; i++) {
-            notEqual(expectedAttendees.indexOf(allAttendees[i]), -1);
+            ok(expectedAttendees.includes(allAttendees[i]));
         }
     }
     function findById(event, id, a) {
         let foundAttendee = event.getAttendeeById(id);
         equal(foundAttendee, a);
     }
     function testImmutability(a, properties) {
          ok(!a.isMutable);
--- a/calendar/test/unit/test_bug668222.js
+++ b/calendar/test/unit/test_bug668222.js
@@ -13,10 +13,10 @@ function run_test() {
     // Reserialize the property, this has caused the property to go away
     // in the past.
     attendee.icalProperty = attendee.icalProperty;
     equal(attendee.getProperty("SCHEDULE-AGENT"), "CLIENT");
 
     // Also make sure there are no promoted properties set. This does not
     // technically belong to this bug, but I almost caused this error while
     // writing the patch.
-    ok(attendee.icalProperty.icalString.indexOf("RSVP") < 0);
+    ok(!attendee.icalProperty.icalString.includes("RSVP"));
 }
--- a/calendar/test/unit/test_recur.js
+++ b/calendar/test/unit/test_recur.js
@@ -537,23 +537,23 @@ function test_interface() {
                                  Components.interfaces.calIRecurrenceItem));
     ok(compareObjects(ritems[1],
                                  rinfo.getRecurrenceItemAt(2),
                                  Components.interfaces.calIRecurrenceItem));
 
 
     // deleteRecurrenceItem
     rinfo.deleteRecurrenceItem(ritems[0]);
-    ok(item.icalString.indexOf("RRULE") < 0);
+    ok(!item.icalString.includes("RRULE"));
 
     // deleteRecurrenceItemAt
     rinfo.deleteRecurrenceItemAt(1);
     itemString = item.icalString;
-    ok(itemString.indexOf("EXDATE") < 0);
-    ok(!(itemString.indexOf("RDATE") < 0));
+    ok(!itemString.includes("EXDATE"));
+    ok(itemString.includes("RDATE"));
 
     // insertRecurrenceItemAt with exdate
     rinfo.insertRecurrenceItemAt(ritems[1], 1);
     ok(compareObjects(ritems[1],
                                  rinfo.getRecurrenceItemAt(1),
                                  Components.interfaces.calIRecurrenceItem));
     rinfo.deleteRecurrenceItem(ritems[1]);
 
@@ -567,19 +567,19 @@ function test_interface() {
                           "DTEND:20020402T124500Z\n" +
                           "RRULE:FREQ=WEEKLY;BYDAY=TU,WE\n");
     ok(!item2.recurrenceInfo.isFinite);
 
     // removeOccurrenceAt/restoreOccurreceAt
     let occDate1 = cal.createDateTime("20020403T114500Z");
     let occDate2 = cal.createDateTime("20020404T114500Z");
     rinfo.removeOccurrenceAt(occDate1);
-    ok(!(item.icalString.indexOf("EXDATE") < 0));
+    ok(item.icalString.includes("EXDATE"));
     rinfo.restoreOccurrenceAt(occDate1)
-    ok(item.icalString.indexOf("EXDATE") < 0);
+    ok(!item.icalString.includes("EXDATE"));
 
     // modifyException / getExceptionFor
     let occ1 = rinfo.getOccurrenceFor(occDate1);
     occ1.startDate = cal.createDateTime("20020401T114500");
     rinfo.modifyException(occ1, true);
     ok(rinfo.getExceptionFor(occDate1) != null);
 
     // modifyException immutable
@@ -838,48 +838,48 @@ function test_rrule_icalstring() {
     recRule.setComponent("BYMONTHDAY", 3, [1, 9, 17]);
     equal(recRule.icalString, "RRULE:FREQ=MONTHLY;BYMONTHDAY=1,9,17\r\n");
     deepEqual(recRule.getComponent("BYMONTHDAY", {}), [1, 9, 17]);
 
     var recRule = createRecurrenceRule();
     recRule.type = "YEARLY";
     recRule.setComponent("BYMONTH", 1, [1]);
     recRule.setComponent("BYMONTHDAY", 1, [3]);
-    notEqual(-1, [
+    ok([
         "RRULE:FREQ=YEARLY;BYMONTHDAY=3;BYMONTH=1\r\n",
         "RRULE:FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=3\r\n"
-    ].indexOf(recRule.icalString));
+    ].includes(recRule.icalString));
     deepEqual(recRule.getComponent("BYMONTH", {}), [1]);
     deepEqual(recRule.getComponent("BYMONTHDAY", {}), [3]);
 
     var recRule = createRecurrenceRule();
     recRule.type = "YEARLY";
     recRule.setComponent("BYMONTH", 1, [4]);
     recRule.setComponent("BYDAY", 1, [3]);
-    notEqual(-1, [
+    ok([
         "RRULE:FREQ=YEARLY;BYDAY=TU;BYMONTH=4\r\n",
         "RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=TU\r\n"
-    ].indexOf(recRule.icalString));
+    ].includes(recRule.icalString));
     deepEqual(recRule.getComponent("BYMONTH", {}), [4]);
     deepEqual(recRule.getComponent("BYDAY", {}), [3]);
 
     var recRule = createRecurrenceRule();
     recRule.type = "YEARLY";
     recRule.setComponent("BYMONTH", 1, [4]);
     recRule.setComponent("BYDAY", 1, [10]);
-    notEqual(-1, [
+    ok([
         "RRULE:FREQ=YEARLY;BYDAY=1MO;BYMONTH=4\r\n",
         "RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1MO\r\n"
-    ].indexOf(recRule.icalString));
+    ].includes(recRule.icalString));
     deepEqual(recRule.getComponent("BYMONTH", {}), [4]);
     deepEqual(recRule.getComponent("BYDAY", {}), [10]);
 
     var recRule = createRecurrenceRule();
     recRule.type = "YEARLY";
     recRule.setComponent("BYMONTH", 1, [4]);
     recRule.setComponent("BYDAY", 1, [-22]);
-    notEqual(-1, [
+    ok([
         "RRULE:FREQ=YEARLY;BYDAY=-2FR;BYMONTH=4\r\n",
         "RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-2FR\r\n"
-    ].indexOf(recRule.icalString));
+    ].includes(recRule.icalString));
     deepEqual(recRule.getComponent("BYMONTH", {}), [4]);
     deepEqual(recRule.getComponent("BYDAY", {}), [-22]);
 }
--- a/calendar/test/unit/test_relation.js
+++ b/calendar/test/unit/test_relation.js
@@ -44,22 +44,22 @@ function run_test() {
 function checkRelations(event, expRel) {
     let countObj = {};
     let allRel = event.getRelations(countObj);
     equal(countObj.value, allRel.length);
     equal(allRel.length, expRel.length);
 
     // check if all expacted relations are found
     for (let i = 0; i < expRel.length; i++) {
-        notEqual(allRel.indexOf(expRel[i]), -1);
+        ok(allRel.includes(expRel[i]));
     }
 
     // Check if all found relations are expected
     for (let i = 0; i < allRel.length; i++) {
-        notEqual(expRel.indexOf(allRel[i]), -1);
+        ok(expRel.includes(allRel[i]));
     }
 }
 
 function modifyRelations(event, oldRel) {
     let allRel = event.getRelations({});
     let rel = allRel[0];
 
     // modify the properties