Bug 970605 - Use node.remove(), especially instead of node.parentNode.removeChild(node): mail. r=mkmelin
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 25 Feb 2014 14:59:19 +0100
changeset 15802 6b9c9c7190e8560a5689261aee930108f1c38aa7
parent 15801 245701d317e79ff215239a47721a67797a399549
child 15803 c167539f1169b28797e58b16d8415aa5753dd140
push id9896
push userryanvm@gmail.com
push dateTue, 25 Feb 2014 18:36:59 +0000
treeherdercomm-central@44bf03090cf6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs970605
Bug 970605 - Use node.remove(), especially instead of node.parentNode.removeChild(node): mail. r=mkmelin
mail/base/content/FilterListDialog.js
mail/base/content/glodaFacetBindings.xml
mail/base/content/glodaFacetView.js
mail/base/content/mailCore.js
mail/base/content/mailWidgets.xml
mail/base/content/mailWindowOverlay.js
mail/base/content/msgHdrViewOverlay.js
mail/base/content/selectionsummaries.js
mail/base/content/tabmail.xml
mail/base/content/threadPaneColumnPicker.xml
mail/base/content/webSearchTab.js
mail/base/modules/quickFilterManager.js
mail/components/about-support/content/export.js
mail/components/activity/content/activity.js
mail/components/addrbook/content/abCardViewOverlay.js
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/addressingWidgetOverlay.js
mail/components/compose/content/cloudAttachmentLinkManager.js
mail/components/migration/content/migration.js
mail/components/preferences/applications.js
mail/components/preferences/compose.js
mail/components/preferences/permissions.js
mail/components/preferences/sendoptions.js
mail/extensions/mailviews/content/mailViewList.js
mail/extensions/mailviews/content/msgViewPickerOverlay.js
mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
mail/test/mozmill/folder-display/test-tooltip-multimessage.js
--- a/mail/base/content/FilterListDialog.js
+++ b/mail/base/content/FilterListDialog.js
@@ -631,17 +631,17 @@ function rebuildFilterList()
 
     if (selectedNames.indexOf(filter.filterName) != -1)
       gFilterListbox.addItemToSelection(listitem);
 
     listitemIndex++;
   }
   // Remove any superfluous listitems, if the number of filters shrunk.
   for (let i = listitemCount - 1; i >= listitemIndex; i--) {
-    gFilterListbox.removeChild(gFilterListbox.lastChild);
+    gFilterListbox.lastChild.remove();
   }
 
   updateViewPosition(firstVisibleRowIndex);
   updateCountBox();
 
   // If before rebuilding the list the searchbox was focused, focus it again.
   // In any other case, focus the list.
   if (searchBoxFocus)
--- a/mail/base/content/glodaFacetBindings.xml
+++ b/mail/base/content/glodaFacetBindings.xml
@@ -19,18 +19,18 @@
   <implementation>
     <constructor><![CDATA[
       Components.utils.import("resource:///modules/mailServices.js");
     ]]></constructor>
     <!-- Indicate that we are based on a fulltext search-->
     <method name="setFulltext">
       <parameter name="aMsgSearcher" />
       <body><![CDATA[
-        while (this.lastChild)
-          this.removeChild(this.lastChild);
+        while (this.hasChildNodes())
+          this.lastChild.remove();
 
         let dis = this;
         function spanify(aText, aClass) {
           let span = document.createElement("span");
           span.setAttribute("class", aClass);
           span.textContent = aText;
           dis.appendChild(span);
           return span;
@@ -49,18 +49,18 @@
           spanify(term, "explanation-fulltext-term");
         }
       ]]></body>
     </method>
     <method name="setQuery">
       <parameter name="aMsgQuery" />
       <body><![CDATA[
       try {
-        while (this.lastChild)
-          this.removeChild(this.lastChild);
+        while (this.hasChildNodes())
+          this.lastChild.remove();
 
         let dis = this;
         function spanify(aText, aClass) {
           let span = document.createElement("span");
           span.setAttribute("class", aClass);
           span.textContent = aText;
           dis.appendChild(span);
           return span;
@@ -102,18 +102,18 @@
 <!-- ===== Facets ===== -->
 
 <binding id="facets">
   <content>
   </content>
   <implementation>
     <method name="clearFacets">
       <body><![CDATA[
-        while (this.lastChild != null)
-          this.removeChild(this.lastChild);
+        while (this.hasChildNodes())
+          this.lastChild.remove();
       ]]></body>
     </method>
     <method name="addFacet">
       <parameter name="aType" />
       <parameter name="aAttrDef" />
       <parameter name="aArgs" />
       <body><![CDATA[
         let facets = this;
@@ -359,18 +359,18 @@
           for each (let [, groupPair] in Iterator(this.orderedGroups)) {
             if (groupPair[0] != null)
               count += groupPair[1].length;
           }
           this.countNode.textContent = count.toLocaleString();
           return;
         }
 
-        while (this.filterNode.lastChild)
-          this.filterNode.removeChild(this.filterNode.lastChild);
+        while (this.filterNode.hasChildNodes())
+          this.filterNode.lastChild.remove();
         let allNode = document.createElement("option");
         allNode.textContent =
           glodaFacetStrings.get("glodaFacetView.facets.filter." +
                                 this.attrDef.attributeName + ".allLabel");
         allNode.setAttribute("value", "all");
         if (this.selectedValue == "all")
           allNode.setAttribute("selected", "selected");
         this.filterNode.appendChild(allNode);
@@ -816,23 +816,23 @@
         // should we just rely on automatic string coercion?
         this.moreButton.setAttribute("needed",
                                      (this.mode == "top") ? "true" : "false");
 
         let constraint = this.faceter.constraint;
 
         // -- empty all of our display buckets...
         let remainderList = this.remainderList;
-        while (remainderList.lastChild)
-          remainderList.removeChild(remainderList.lastChild);
+        while (remainderList.hasChildNodes())
+          remainderList.lastChild.remove();
         let includeList = this.includeList, excludeList = this.excludeList;
-        while (includeList.lastChild)
-          includeList.removeChild(includeList.lastChild);
-        while (excludeList.lastChild)
-          excludeList.removeChild(excludeList.lastChild);
+        while (includeList.hasChildNodes())
+          includeList.lastChild.remove();
+        while (excludeList.hasChildNodes())
+          excludeList.lastChild.remove();
 
         // -- first pass, check for ambiguous labels
         // It's possible that multiple groups are identified by the same short
         //  string, in which case we want to use the longer string to
         //  disambiguate.  For example, un-merged contacts can result in
         //  multiple identities having contacts with the same name.  In that
         //  case we want to display both the contact name and the identity
         //  name.
@@ -1296,18 +1296,18 @@
     <method name="build">
       <parameter name="aDoSize" />
       <body><![CDATA[
         if (!this.vis) {
           this.vis = new DateFacetVis(this, this.canvasNode);
           this.vis.build();
         }
         else {
-          while (this.canvasNode.lastChild)
-            this.canvasNode.removeChild(this.canvasNode.lastChild);
+          while (this.canvasNode.hasChildNodes())
+            this.canvasNode.lastChild.remove();
           if (aDoSize)
             this.vis.build()
           else
             this.vis.rebuild();
         }
       ]]></body>
     </method>
     <method name="brushItems">
@@ -1431,18 +1431,18 @@
             event.preventDefault();
           }
         }
 
         this.updateSortLabels(FacetContext.sortBy);
 
         let messagesNode = document.getAnonymousElementByAttribute(
                              this, "anonid", "messages");
-        while (messagesNode.lastChild)
-          messagesNode.removeChild(messagesNode.lastChild);
+        while (messagesNode.hasChildNodes())
+          messagesNode.lastChild.remove();
       try {
         // -- Messages
         for each (let [, message] in Iterator(aMessages)) {
           let msgNode = document.createElement("message");
           msgNode.message = message;
           msgNode.setAttribute("class", "message");
           messagesNode.appendChild(msgNode);
         }
--- a/mail/base/content/glodaFacetView.js
+++ b/mail/base/content/glodaFacetView.js
@@ -434,17 +434,17 @@ var FacetContext = {
   },
 
   /**
    * Clean up the UI in preparation for a new query to come in.
    */
   _resetUI: function() {
     for each (let [, faceter] in Iterator(this.faceters)) {
       if (faceter.xblNode && !faceter.xblNode.explicit)
-        faceter.xblNode.parentNode.removeChild(faceter.xblNode);
+        faceter.xblNode.remove();
       faceter.xblNode = null;
       faceter.constraint = null;
     }
   },
 
   _groupCountComparator: function(a, b) {
     return b.groupCount - a.groupCount;
   },
--- a/mail/base/content/mailCore.js
+++ b/mail/base/content/mailCore.js
@@ -238,17 +238,17 @@ function MailToolboxCustomizeDone(aEvent
         popup._teardown();
       } else {
         for (let i = popup.childNodes.length - 1; i >= 0; i--) {
           let child = popup.childNodes[i];
           if (child.getAttribute("generated") != "true")
             continue;
           if ("_teardown" in child)
             child._teardown();
-          popup.removeChild(child);
+          child.remove();
         }
       }
     }
   }
 }
 
 function onViewToolbarsPopupShowing(aEvent, toolboxIds, aInsertPoint)
 {
@@ -259,17 +259,17 @@ function onViewToolbarsPopupShowing(aEve
 
   // Empty the menu
   for (let i = popup.childNodes.length - 1; i >= 0; --i) {
     let deadItem = popup.childNodes[i];
 
     // Remove all of the nodes with the iscollapsible
     // attribute.
     if (deadItem.hasAttribute("iscollapsible"))
-      popup.removeChild(deadItem);
+      deadItem.remove();
   }
 
   // We'll insert the menuitems before the first item in the list if no insert
   // point is defined.
   let firstMenuItem = aInsertPoint || popup.firstChild;
 
   for (let [, toolboxId] in Iterator(toolboxIds)) {
     let toolbox = document.getElementById(toolboxId);
--- a/mail/base/content/mailWidgets.xml
+++ b/mail/base/content/mailWidgets.xml
@@ -943,18 +943,18 @@
 
             // We want to keep around the first maxAddressesBeforeMore email
             // address nodes as well as any intervening comma nodes.
             var numItemsToPreserve = this.maxAddressesBeforeMore * 2 - 1;
             var numItemsInNode = aParentNode.childNodes.length;
 
             while (numItemsInNode && (numItemsInNode > numItemsToPreserve))
             {
-              aParentNode.removeChild(aParentNode.childNodes[numItemsInNode-1]);
-              numItemsInNode = numItemsInNode - 1;
+              aParentNode.lastChild.remove();
+              numItemsInNode--;
             }
           ]]>
         </body>
       </method>
 
       <method name="clearHeaderValues">
         <body>
           <![CDATA[
@@ -1088,18 +1088,18 @@
           }
         ]]></body>
       </method>
 
       <!-- clear the current view and internal list of newsgroups -->
       <method name="clearHeaderValues">
         <body><![CDATA[
           this.mNewsgroups = new Array;
-          while(this.newsgroups.childNodes.length)
-            this.newsgroups.removeChild(this.newsgroups.firstChild);
+          while(this.newsgroups.hasChildNodes())
+            this.newsgroups.lastChild.remove();
         ]]></body>
       </method>
     </implementation>
   </binding>
 
   <binding id="mail-messageids-headerfield">
     <content>
       <xul:hbox class="headerNameBox" align="start" pack="end">
@@ -1167,17 +1167,17 @@
         <body>
           <![CDATA[
             var headerValue    = this.headerValue;
             var messageIdNodes = headerValue.childNodes;
             var numMessageIds  = this.mMessageIds.length;
             var index = 0;
 
             while (messageIdNodes.length > numMessageIds * 2 - 1)
-              headerValue.removeChild(headerValue.lastChild);
+              headerValue.lastChild.remove();
 
             this.toggleIcon.hidden = numMessageIds <= 1;
 
             for (var index = 0; index < numMessageIds; index++)
             {
               if (index * 2 <= messageIdNodes.length - 1)
               {
                 this.updateMessageIdNode(messageIdNodes[index * 2], index + 1,
@@ -1280,18 +1280,18 @@
         <parameter name="aTags"/>
         <body>
           <![CDATA[
             // aTags contains a list of actual tag names (not the keys), delimited by spaces
             // each tag name is encoded.
 
             // remove any existing tag items we've appended to the list
             var headerValueNode = document.getAnonymousElementByAttribute(this, 'anonid', 'headerValue');
-            for (var i = headerValueNode.childNodes.length - 1; i >= 0; --i)
-              headerValueNode.removeChild(headerValueNode.childNodes[i]);
+            while (headerValueNode.hasChildNodes())
+              headerValueNode.lastChild.remove();
 
             // tokenize the keywords based on ' '
             var tagsArray = aTags.split(' ');
             for (var index = 0; index < tagsArray.length; index++)
             {
               // for each tag, create a label, give it the font color that corresponds to the
               // color of the tag and append it.
               var tagName;
@@ -1479,17 +1479,17 @@
 
             // save our old "value" so we can restore it later
             var oldData;
             if (!dontRestore)
               oldData = menulist.value;
 
             // remove the old popup children
             while (popup.hasChildNodes())
-              popup.removeChild(popup.lastChild);
+              popup.lastChild.remove();
 
             var newSelection;
             var customizePos=-1;
             for (var i = 0; i < menuItemIds.length; ++i)
             {
               // create the menuitem
               if (Components.interfaces.nsMsgSearchAttrib.OtherHeader == menuItemIds[i].toString())
                 customizePos = i;
@@ -2582,17 +2582,17 @@
         </body>
       </method>
 
       <method name="clear">
         <body>
           <![CDATA[
             var containingBox = document.getAnonymousNodes(this)[0];
             while (containingBox.hasChildNodes())
-              containingBox.removeChild(containingBox.lastChild);
+              containingBox.lastChild.remove();
           ]]>
         </body>
       </method>
       <constructor>
         <![CDATA[
           Components.utils.import("resource:///modules/mailServices.js");
           Components.utils.import("resource://gre/modules/Services.jsm", this);
         ]]>
--- a/mail/base/content/mailWindowOverlay.js
+++ b/mail/base/content/mailWindowOverlay.js
@@ -891,17 +891,17 @@ function InitMessageTags(menuPopup)
 {
   let tagArray = MailServices.tags.getAllTags({});
   var tagCount = tagArray.length;
 
   // Remove any existing non-static entries... (clear tags list before rebuilding it)
   // "5" is the number of menu items (including separators) on the top of the menu
   // that should not be cleared.
   for (let i = menuPopup.childNodes.length; i > 5; --i)
-    menuPopup.removeChild(menuPopup.lastChild);
+    menuPopup.lastChild.remove();
 
   // create label and accesskey for the static remove item
   var tagRemoveLabel = document.getElementById("bundle_messenger")
                                .getString("mailnews.tags.remove");
   SetMessageTagLabel(menuPopup.lastChild.previousSibling, 0, tagRemoveLabel);
 
   // now rebuild the list
   var msgHdr = gFolderDisplay.selectedMessage;
@@ -931,18 +931,18 @@ function InitRecentlyClosedTabsPopup(men
 {
   let tabs = document.getElementById("tabmail").recentlyClosedTabs;
 
   // show Popup only when there are restorable tabs.
   if( !tabs.length )
     return false;
 
   // Clear the list before rebulding it.     
-  while (menuPopup.childNodes.length > 0)
-    menuPopup.removeChild(menuPopup.firstChild);
+  while (menuPopup.hasChildNodes())
+    menuPopup.lastChild.remove();
     
   // Rebuild the recently closed tab list
   for (let i = 0; i < tabs.length; i++ ) {
     
     let menuItem = document.createElement("menuitem");
     menuItem.setAttribute("label",tabs[i].title);    
     menuItem.setAttribute('oncommand',
         'document.getElementById("tabmail").undoCloseTab('+i+');');
@@ -992,18 +992,18 @@ function navDebug(str)
 {
   if (gNavDebug)
     dump(str);
 }
 
 function populateHistoryMenu(menuPopup, isBackMenu)
 {
   // remove existing entries
-  while (menuPopup.firstChild)
-    menuPopup.removeChild(menuPopup.firstChild);
+  while (menuPopup.hasChildNodes())
+    menuPopup.lastChild.remove();
   var curPos = new Object;
   var numEntries = new Object;
   var historyEntries = new Object;
   messenger.getNavigateHistory(curPos, numEntries, historyEntries);
   curPos.value = curPos.value * 2;
   navDebug("curPos = " + curPos.value + " numEntries = " + numEntries.value + "\n");
   var historyArray = historyEntries.value;
   var folder;
--- a/mail/base/content/msgHdrViewOverlay.js
+++ b/mail/base/content/msgHdrViewOverlay.js
@@ -1037,17 +1037,17 @@ function createNewHeaderView(headerName,
  * Removes all non-predefined header nodes from the view.
  *
  * @param aHeaderTable  Table of header entries.
  */
 function RemoveNewHeaderViews(aHeaderTable)
 {
   for each (let [, headerEntry] in Iterator(aHeaderTable)) {
     if (headerEntry.isNewHeader)
-      headerEntry.enclosingRow.parentNode.removeChild(headerEntry.enclosingRow);
+      headerEntry.enclosingRow.remove();
   }
 }
 
 /**
  * UpdateExpandedMessageHeaders: Iterate through all the current header data
  * we received from mime for this message for the expanded header entry table,
  * and see if we have a corresponding entry for that header (i.e.
  * whether the expanded header view cares about this header value)
@@ -2418,18 +2418,18 @@ function FillAttachmentListPopup(aEvent,
 
   goUpdateAttachmentCommands();
 }
 
 // Public method used to clear the file attachment menu
 function ClearAttachmentMenu(popup)
 {
   if (popup) {
-    while (popup.childNodes[0].localName == "menu")
-      popup.removeChild(popup.childNodes[0]);
+    while (popup.firstChild.localName == "menu")
+      popup.firstChild.remove();
   }
 }
 
 /**
  * Create a menu for a single attachment.
  *
  * @param popup  the popup to add the menu to
  * @param attachment  the AttachmentInfo object to add
@@ -2693,17 +2693,17 @@ function ClearAttachmentList()
   if (appmenunode)
     appmenunode.setAttribute("disabled", "true");
 
   // clear selection
   var list = document.getElementById("attachmentList");
   list.selectedItems.length = 0;
 
   while (list.hasChildNodes())
-    list.removeChild(list.lastChild);
+    list.lastChild.remove();
 }
 
 var attachmentListDNDObserver = {
   onDragStart: function (aEvent, aAttachmentData, aDragAction)
   {
     let target = aEvent.target;
 
     if (target.localName == "attachmentitem")
--- a/mail/base/content/selectionsummaries.js
+++ b/mail/base/content/selectionsummaries.js
@@ -192,18 +192,18 @@ MultiMessageSummary.prototype = {
     heading.textContent = messagesTitle;
 
     // Enable/disable the archive button as appropriate.
     let archiveBtn = contentDocument.getElementById("hdrArchiveButton");
     archiveBtn.collapsed = !gFolderDisplay.canArchiveSelectedMessages;
 
     // Clear the messages list.
     let messagesElt = contentDocument.getElementById("messagelist");
-    while (messagesElt.firstChild)
-      messagesElt.removeChild(messagesElt.firstChild);
+    while (messagesElt.hasChildNodes())
+      messagesElt.lastChild.remove();
 
     const MAX_MESSAGES = 100;
     const SNIPPET_LENGTH = 300;
     let count = 0;
     let maxCountExceeded = false;
     var parser = new DOMParser();
 
     for (let [thread, msgs] in Iterator(threads)) {
@@ -299,18 +299,18 @@ MultiMessageSummary.prototype = {
       // get the subject node.
       let subjectNode = msgNode.querySelector(".subject");
       subjectNode.msgs = msgs;
       subjectNode.addEventListener("click", function() {
         gFolderDisplay.selectMessages(this.msgs);
       }, true);
 
       let tagsNode = msgNode.querySelector(".tags");
-      while (tagsNode.firstChild)
-        tagsNode.removeChild(tagsNode.firstChild);
+      while (tagsNode.hasChildNodes())
+        tagsNode.lastChild.remove();
       this._addTagNodes(msgs, tagsNode);
       for (let [,msgHdr] in Iterator(msgs)) {
         this._msgNodes[msgHdr.messageKey + msgHdr.folder.URI] = msgNode;
       }
       messagesElt.appendChild(msgNode);
     }
     this.computeSize(contentDocument);
     this.notifyMaxCountExceeded(
@@ -422,18 +422,18 @@ MultiMessageSummary.prototype = {
 
       headerNode.flags["unread"] = !glodaMsg.read;
       headerNode.flags["starred"] = glodaMsg.starred;
 
       // For tags, there's a minor problem in that if _some_ of the items in a
       // thread got modified.
       let key = messageKey + glodaMsg.folder.uri;
       let tagsNode = headerNode.querySelector(".tags");
-      while (tagsNode.firstChild)
-        tagsNode.removeChild(tagsNode.firstChild);
+      while (tagsNode.hasChildNodes())
+        tagsNode.lastChild.remove();
       this._addTagNodes([msg.folderMessage for ([,msg] in Iterator(aItems))],
                         tagsNode);
     }
 
     for (let headerNode of knownMessageNodes) {
       headerNode.classList.toggle("unread", headerNode.flags["unread"]);
       headerNode.classList.toggle("starred", headerNode.flags["starred"]);
       headerNode.flags = null;
@@ -488,18 +488,18 @@ ThreadSummary.prototype = {
     let firstMsgHdr = this._msgHdrs[0];
     let numMessages = this._msgHdrs.length;
 
     // Enable/disable the archive button as appropriate.
     let archiveBtn = contentDocument.getElementById("hdrArchiveButton");
     archiveBtn.collapsed = !gFolderDisplay.canArchiveSelectedMessages;
 
     let messagesElt = contentDocument.getElementById("messagelist");
-    while (messagesElt.firstChild)
-      messagesElt.removeChild(messagesElt.firstChild);
+    while (messagesElt.hasChildNodes())
+      messagesElt.lastChild.remove();
 
     let count = 0;
     let ignoredCount = 0;
     const MAX_THREADS = 100;
     const SNIPPET_LENGTH = 300;
     let maxCountExceeded = false;
     for (let i = 0; i < numMessages; ++i) {
       let msgHdr = this._msgHdrs[i];
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -716,17 +716,17 @@
               }
             }
 
             let closeFunc = tab.mode.closeTab || tab.mode.tabType.closeTab;
             closeFunc.call(tab.mode.tabType, tab);
 
             this.tabInfo.splice(iTab, 1);
             tab.mode.tabs.splice(tab.mode.tabs.indexOf(tab), 1);
-            this.tabContainer.removeChild(tabNode);
+            tabNode.remove();
 
             if (this.tabContainer.selectedIndex == -1) {
               let lastTabOpenerIndex = this.tabInfo.indexOf(this.mLastTabOpener);
 
               if (this.mLastTabOpener && (lastTabOpenerIndex != -1)) {
                 this.tabContainer.selectedIndex = this.tabInfo.indexOf(this.mLastTabOpener);
               } else {
                 this.tabContainer.selectedIndex =
@@ -737,17 +737,17 @@
 
             // Clear the last tab opener - we don't need this anymore.
             this.mLastTabOpener = null;
 
             if (this.currentTabInfo == tab)
               this.updateCurrentTab();
 
             if (tab.panel) {
-              this.panelContainer.removeChild(tab.panel);
+              tab.panel.remove();
               delete tab.panel;
 
               // Ensure current tab is still selecte and displayed in the
               // panelContainer.
               this.panelContainer.selectedPanel =
                 this.currentTabInfo.panel || this.currentTabInfo.mode.tabType.panel;
             }
             if (this.tabContainer.childNodes.length == 1 &&
@@ -832,17 +832,17 @@
           let tab = this.tabInfo[oldIdx]
 
           if (!tab)
             return -1;
 
           // remove the entries form tabInfo, tabMode and the tabContainer
           this.tabInfo.splice(oldIdx, 1);
           tab.mode.tabs.splice(tab.mode.tabs.indexOf(tab), 1);
-          this.tabContainer.removeChild(aTab);
+          aTab.remove();
 
 
           // as we removed items, we might need to update indices
           if (oldIdx < aIndex)
             aIndex --;
 
           // Read it into tabInfo and the tabContainer
           this.tabInfo.splice(aIndex, 0, tab);
@@ -2395,17 +2395,17 @@
         ]]></body>
       </method>
 
       <method name="_tabOnTabClose">
         <parameter name="aEvent"/>
         <body><![CDATA[
           var menuItem = aEvent.target.mCorrespondingMenuitem;
           if (menuItem)
-            this.removeChild(menuItem);
+            menuItem.remove();
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           if (!aEvent.isTrusted)
             return;
@@ -2533,17 +2533,17 @@
       <handler event="popuphiding">
       <![CDATA[
         // clear out the menu popup and remove the listeners
         while (this.hasChildNodes()) {
           var menuItem = this.lastChild;
           menuItem.removeEventListener("command", this, false);
           menuItem.tab.removeEventListener("TabClose", this, false);
           menuItem.tab.mCorrespondingMenuitem = null;
-          this.removeChild(menuItem);
+          menuItem.remove();
         }
         this._mutationObserver.disconnect();
 
         var tabcontainer = document.getElementById('tabmail').tabContainer;
         tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
         tabcontainer.tabmail.removeEventListener("TabOpen", this, false);
       ]]></handler>
     </handlers>
--- a/mail/base/content/threadPaneColumnPicker.xml
+++ b/mail/base/content/threadPaneColumnPicker.xml
@@ -55,17 +55,17 @@
     </content>
 
     <implementation>
       <method name="buildPopup">
         <parameter name="aPopup"/>
         <body>
           <![CDATA[
             while (aPopup.childNodes.length > 3)
-              aPopup.removeChild(aPopup.firstChild);
+              aPopup.firstChild.remove();
 
             var refChild = aPopup.firstChild;
 
             var tree = this.parentNode.parentNode;
             for (var currCol = tree.columns.getFirstColumn(); currCol;
                  currCol = currCol.getNext()) {
               // Construct an entry for each column in the row, unless
               // it is not being shown.
--- a/mail/base/content/webSearchTab.js
+++ b/mail/base/content/webSearchTab.js
@@ -160,17 +160,17 @@ let webSearchTabType = {
     let checkedEngine = currentEngineName;
 
     // Clear out any existing search engine buttons
     let ch = null;
     while ((ch = aTab.engines.lastChild)) {
       if (ch.getAttribute("checked")) {
         checkedEngine = ch.getAttribute("tooltiptext");
       }
-      aTab.engines.removeChild(ch);
+      ch.remove();
     }
 
     // Register new buttons for all the search engines
     for each (let engine in Services.search.getVisibleEngines()) {
       let button = document.createElement("toolbarbutton");
       button.setAttribute("type", "radio");
       button.setAttribute("group", "engines");
       button.setAttribute("image",
--- a/mail/base/modules/quickFilterManager.js
+++ b/mail/base/modules/quickFilterManager.js
@@ -860,18 +860,18 @@ let TagFacetingFilter = {
           aEvent.target.removeAttribute("inverted");
         aMuxer.updateSearch();
         aEvent.stopPropagation();
         aEvent.preventDefault();
       }
     }
 
     // -- nuke existing exposed tags, but not the mode selector (which is first)
-    while (tagbar.lastChild && tagbar.lastChild !== tagbar.firstChild) {
-      tagbar.removeChild(tagbar.lastChild);
+    while (tagbar.childNodes.length > 1) {
+      tagbar.lastChild.remove();
     }
 
     let addCount = 0;
 
     // -- create an element for each tag
     let tags = MailServices.tags.getAllTags({});
     let tagCount = tags.length;
     for (let iTag = 0; iTag < tagCount; iTag++) {
--- a/mail/components/about-support/content/export.js
+++ b/mail/components/about-support/content/export.js
@@ -107,19 +107,19 @@ function cleanUpText(aElem, aHidePrivate
   let node = aElem.firstChild;
   let copyData = aElem.dataset.copyData;
   delete aElem.dataset.copyData;
   while (node) {
     let classList = "classList" in node && node.classList;
     // Delete uionly nodes.
     if (classList && classList.contains(CLASS_DATA_UIONLY)) {
       // Advance to the next node before removing the current node, since
-      // node.nextSibling is null after removeChild
+      // node.nextSibling is null after remove()
       let nextNode = node.nextSibling;
-      aElem.removeChild(node);
+      node.remove();
       node = nextNode;
       continue;
     }
     // Replace private data with a blank string
     else if (aHidePrivateData && classList && classList.contains(CLASS_DATA_PRIVATE)) {
       node.textContent = "";
     }
     // Replace public data with a blank string
--- a/mail/components/activity/content/activity.js
+++ b/mail/components/activity/content/activity.js
@@ -161,37 +161,37 @@ var activityObject =
 
       if (!item.isGroup) {
         this._activityLogger.debug("is not a group, ")
         if (item.getAttribute('actID') == aID) {
           // since XBL dtors are not working properly when we remove the
           // element, we have to explicitly remove the binding from
           // activities' listeners list. See bug 230086 for details.
           item.detachFromActivity();
-          this._activitiesView.removeChild(item);
+          item.remove();
           break;
         }
       }
       else {
         let actbinding = document.getAnonymousElementByAttribute(item, 'actID',
                                                                  aID);
         if (actbinding) {
           let groupView = document.getAnonymousElementByAttribute(item,
                                                  "anonid", "activityGroupView");
           // since XBL dtors are not working properly when we remove the
           // element, we have to explicitly remove the binding from
           // activities' listeners list. See bug 230086 for details.
           actbinding.detachFromActivity();
-          groupView.removeChild(actbinding);
+          actbinding.remove();
 
           // if the group becomes empty after the removal,
           // get rid of the group as well
           if (groupView.getRowCount() == 0) {
             delete this._groupCache[item.contextType + ":" + item.contextObj];
-            this._activitiesView.removeChild(item);
+            item.remove();
           }
 
           break;
         }
       }
     }
   },
 
@@ -261,17 +261,17 @@ var activityObject =
       let item = activities[i];
       if (!item.isGroup)
         item.detachFromActivity();
       else {
         let actbinding = document.getAnonymousElementByAttribute(item,
                                                                  'actID', '*');
         while (actbinding) {
           actbinding.detachFromActivity();
-          actbinding.parentNode.removeChild(actbinding);
+          actbinding.remove();
           actbinding = document.getAnonymousElementByAttribute(item,
                                                                'actID', '*');
         }
       }
     }
 
     let (empty = this._activitiesView.cloneNode(false)) {
       this._activitiesView.parentNode.replaceChild(empty, this._activitiesView);
--- a/mail/components/addrbook/content/abCardViewOverlay.js
+++ b/mail/components/addrbook/content/abCardViewOverlay.js
@@ -505,17 +505,17 @@ function cvAddAddressNodes(node, uri)
   if (node) {
     var editList = GetDirectoryFromURI(uri);
     var addressList = editList.addressLists;
 
     if (addressList) {
       var total = addressList.length;
       if (total > 0) {
         while (node.hasChildNodes()) {
-          node.removeChild(node.lastChild);
+          node.lastChild.remove();
         }
         for (i = 0;  i < total; i++ ) {
           var descNode = document.createElement("description");
           var card = addressList.queryElementAt(i, Components.interfaces.nsIAbCard);
 
           descNode.setAttribute("class", "CardViewLink");
           node.appendChild(descNode);
 
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -1110,17 +1110,17 @@ function updateSendCommands(aHaveControl
     goSetCommandEnabled("cmd_sendLater",     defaultController.isCommandEnabled("cmd_sendLater"));
     goSetCommandEnabled("cmd_sendWithCheck", defaultController.isCommandEnabled("cmd_sendWithCheck"));
   }
 }
 
 function addAttachCloudMenuItems(aParentMenu)
 {
   while (aParentMenu.hasChildNodes())
-    aParentMenu.removeChild(aParentMenu.lastChild);
+    aParentMenu.lastChild.remove();
 
   for (let [,cloudProvider] in Iterator(cloudFileAccounts.accounts)) {
     let item = document.createElement("menuitem");
     let iconClass = cloudProvider.iconClass;
     item.cloudProvider = cloudProvider;
     item.setAttribute("label", cloudFileAccounts.getDisplayName(cloudProvider));
 
     if (iconClass) {
@@ -1131,17 +1131,17 @@ function addAttachCloudMenuItems(aParent
   }
 }
 
 function addConvertCloudMenuItems(aParentMenu, aAfterNodeId, aRadioGroup)
 {
   let attachment = document.getElementById("attachmentBucket").selectedItem;
   let afterNode = document.getElementById(aAfterNodeId);
   while (afterNode.nextSibling)
-    aParentMenu.removeChild(afterNode.nextSibling);
+    afterNode.nextSibling.remove();
 
   if (!attachment.sendViaCloud) {
     let item = document.getElementById("convertCloudMenuItems_popup_convertAttachment");
     item.setAttribute("checked", "true");
   }
 
   for (let [,cloudProvider] in Iterator(cloudFileAccounts.accounts)) {
     let item = document.createElement("menuitem");
@@ -1898,30 +1898,30 @@ function ShouldShowAttachmentNotificatio
       Components.interfaces.nsIPrefLocalizedString).data;
     let mailBody = document.getElementById("content-frame")
                            .contentDocument.querySelector("body");
     let mailBodyNode = mailBody.cloneNode(true);
 
     // Don't check quoted text from reply.
     let blockquotes = mailBodyNode.getElementsByTagName("blockquote");
     for (let i = blockquotes.length - 1; i >= 0; i--) {
-      blockquotes[i].parentNode.removeChild(blockquotes[i]);
+      blockquotes[i].remove();
     }
 
     // For plaintext composition the quotes we need to find and exclude are
     // <span _moz_quote="true">.
     let spans = mailBodyNode.querySelectorAll("span[_moz_quote]");
     for (let i = spans.length - 1; i >= 0; i--) {
-      spans[i].parentNode.removeChild(spans[i]);
+      spans[i].remove();
     }
 
     // Ignore signature (html compose mode).
     let sigs = mailBodyNode.getElementsByClassName("moz-signature");
     for (let i = sigs.length - 1; i >= 0; i--) {
-      sigs[i].parentNode.removeChild(sigs[i]);
+      sigs[i].remove();
     }
 
     // Replace brs with line breaks so node.textContent won't pull foo<br>bar
     // together to foobar.
     let brs = mailBodyNode.getElementsByTagName("br");
     for (let i = brs.length - 1; i >= 0; i--) {
       brs[i].parentNode.replaceChild(mailBodyNode.ownerDocument.createTextNode("\n"), brs[i]);
     }
@@ -3108,17 +3108,17 @@ function InitLanguageMenu()
     function compareFn(a, b)
     {
       return a[0].localeCompare(b[0]);
     }
   );
 
   // Remove any languages from the list.
   while (languageMenuList.hasChildNodes())
-    languageMenuList.removeChild(languageMenuList.firstChild);
+    languageMenuList.lastChild.remove();
 
   for (let i = 0; i < count; i++)
   {
     var item = document.createElement("menuitem");
     item.setAttribute("label", dictList[i][0]);
     item.setAttribute("value", dictList[i][1]);
     item.setAttribute('type', 'radio');
     languageMenuList.appendChild(item);
@@ -3206,17 +3206,17 @@ function toggleAttachmentReminder(aState
   if (aState && notification)
     nBox.removeNotification(notification);
 }
 
 function ClearIdentityListPopup(popup)
 {
   if (popup)
     while (popup.hasChildNodes())
-      popup.removeChild(popup.lastChild);
+      popup.lastChild.remove();
 }
 
 function FillIdentityList(menulist)
 {
   let accounts = allAccountsSorted(true);
 
   let accountHadSeparator = false;
   let firstAccountWithIdentities = true;
--- a/mail/components/compose/content/addressingWidgetOverlay.js
+++ b/mail/components/compose/content/addressingWidgetOverlay.js
@@ -646,28 +646,22 @@ function awCopyNode(node, parentNode, be
 
     return newNode;
 }
 
 // remove row
 
 function awRemoveRow(row)
 {
-  var listbox = document.getElementById('addressingWidget');
-
-  awRemoveNodeAndChildren(listbox, awGetListItem(row));
+  awGetListItem(row).remove();
   awFitDummyRows();
 
   top.MAX_RECIPIENTS --;
 }
 
-function awRemoveNodeAndChildren(parent, nodeToRemove)
-{
-  nodeToRemove.parentNode.removeChild(nodeToRemove);
-}
 
 function awSetFocus(row, inputElement)
 {
   top.awRow = row;
   top.awInputElement = inputElement;
   setTimeout(_awSetFocus, 0);
 }
 
@@ -927,17 +921,17 @@ function awCreateOrRemoveDummyRows()
 {
   let listbox = document.getElementById("addressingWidget");
   let listboxHeight = listbox.boxObject.height;
 
   // remove rows to remove scrollbar
   let kids = listbox.querySelectorAll('[_isDummyRow]');
   for (let i = kids.length - 1; gAWContentHeight > listboxHeight && i >= 0; --i) {
     gAWContentHeight -= gAWRowHeight;
-    listbox.removeChild(kids[i]);
+    kids[i].remove();
   }
 
   // add rows to fill space
   if (gAWRowHeight) {
     while (gAWContentHeight + gAWRowHeight < listboxHeight) {
       awCreateDummyItem(listbox);
       gAWContentHeight += gAWRowHeight;
     }
--- a/mail/components/compose/content/cloudAttachmentLinkManager.js
+++ b/mail/components/compose/content/cloudAttachmentLinkManager.js
@@ -45,21 +45,18 @@ var gCloudAttachmentLinkManager = {
     let editor = GetCurrentEditor();
     let selection = editor.selection;
 
     let container = editor.createElementWithDefaults("div");
     container.setAttribute("class", "moz-forward-container");
 
     editor.enableUndo(false);
 
-    if (mailBody.hasChildNodes()) {
-      while (mailBody.childNodes.length > 0) {
-        let removedChild = mailBody.removeChild(mailBody.firstChild);
-        container.appendChild(removedChild);
-      }
+    while (mailBody.hasChildNodes()) {
+      container.appendChild(mailBody.removeChild(mailBody.firstChild));
     }
     editor.insertLineBreak();
     selection.collapse(mailBody, 1);
     editor.insertElementAtSelection(container, false);
     editor.insertLineBreak();
     editor.beginningOfDocument();
 
     editor.enableUndo(true);
@@ -88,43 +85,43 @@ var gCloudAttachmentLinkManager = {
         items = list.getElementsByClassName("cloudAttachmentItem");
 
       for (let attachment in fixIterator(
            event.detail, Components.interfaces.nsIMsgAttachment)) {
         // Remove the attachment from the message body.
         if (list)
           for (let i = 0; i < items.length; i++)
             if (items[i].contentLocation == attachment.contentLocation)
-              list.removeChild(items[i]);
+              items[i].remove();
 
         // Now, remove the attachment from our internal list.
         let index = this.cloudAttachments.indexOf(attachment);
         if (index != -1)
           this.cloudAttachments.splice(index, 1);
       }
 
       this._updateAttachmentCount(mailDoc);
 
       if (items.length == 0) {
         if (list)
-          list.parentNode.removeChild(list);
+          list.remove();
         this._removeRoot(mailDoc);
       }
     }
   },
 
   /**
    * Removes the root node for an attachment list in an HTML email.
    *
    * @param aDocument the document to remove the root node from.
    */
   _removeRoot: function(aDocument) {
     let header = aDocument.getElementById("cloudAttachmentListRoot");
     if (header)
-      header.parentNode.removeChild(header);
+      header.remove();
   },
 
   /**
    * Given some node, returns the textual HTML representation for the node
    * and its children.
    *
    * @param aDocument the document that the node is embedded in
    * @param aNode the node to get the textual representation from
--- a/mail/components/migration/content/migration.js
+++ b/mail/components/migration/content/migration.js
@@ -134,17 +134,17 @@ var MigrationWizard = {
   {
     // Disabling this for now, since we ask about import sources in automigration
     // too and don't want to disable the back button
     // if (this._autoMigrate)
     //   document.documentElement.getButton("back").disabled = true;
 
     var profiles = document.getElementById("profiles");
     while (profiles.hasChildNodes())
-      profiles.removeChild(profiles.firstChild);
+      profiles.lastChild.remove();
 
     var sourceProfiles = this._migrator.sourceProfiles;
     var count = sourceProfiles.length;
     for (var i = 0; i < count; ++i) {
       var item = document.createElement("radio");
       item.id = sourceProfiles.queryElementAt(i, nsISupportsString).data;
       item.setAttribute("label", item.id);
       profiles.appendChild(item);
@@ -169,17 +169,17 @@ var MigrationWizard = {
       this._wiz.currentPage.next = "migrating";
   },
 
   // 3 - ImportItems
   onImportItemsPageShow: function ()
   {
     var dataSources = document.getElementById("dataSources");
     while (dataSources.hasChildNodes())
-      dataSources.removeChild(dataSources.firstChild);
+      dataSources.lastChild.remove();
 
     var bundle = document.getElementById("bundle");
 
     var items = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
     for (var i = 0; i < 16; ++i) {
       var itemID = (items >> i) & 0x1 ? Math.pow(2, i) : 0;
       if (itemID > 0) {
         var checkbox = document.createElement("checkbox");
@@ -240,17 +240,17 @@ var MigrationWizard = {
   {
     aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile);
   },
 
   _listItems: function (aID)
   {
     var items = document.getElementById(aID);
     while (items.hasChildNodes())
-      items.removeChild(items.firstChild);
+      items.lastChild.remove();
 
     var bundle = document.getElementById("bundle");
     var itemID;
     for (var i = 0; i < 16; ++i) {
       var itemID = (this._itemsFlags >> i) & 0x1 ? Math.pow(2, i) : 0;
       if (itemID > 0) {
         var label = document.createElement("label");
         label.id = itemID + "_migrated";
--- a/mail/components/preferences/applications.js
+++ b/mail/components/preferences/applications.js
@@ -586,18 +586,18 @@ var gCloudFileTab = {
       this._accountCache[aAccount.accountKey].listItem = rli;
     }
 
     return rli;
   },
 
   clearEntries: function CFT_clearEntries() {
     // Clear the list of entries.
-    while (this._list.childNodes.length > 0)
-      this._list.removeChild(this._list.lastChild);
+    while (this._list.hasChildNodes())
+      this._list.lastChild.remove();
   },
 
   rebuildView: function CFT_rebuildView() {
     this.clearEntries();
     let accounts = cloudFileAccounts.accounts;
 
     // Sort the accounts by displayName.
     function sortAccounts(a, b) {
@@ -716,20 +716,20 @@ var gCloudFileTab = {
   },
 
   _showAccountManagement: function CFT__showAccountManagement(aProvider) {
     let iframe = document.createElement('iframe');
 
     iframe.setAttribute("src", aProvider.managementURL);
     iframe.setAttribute("flex", "1");
 
-    // If we have a past iframe, we replace it.  Else, append
+    // If we have a past iframe, we replace it. Else append
     // to the wrapper.
-    if (this._settings && this._settings.parentNode)
-      this._settings.parentNode.removeChild(this._settings);
+    if (this._settings)
+      this._settings.remove();
 
     this._settingsPanelWrap.appendChild(iframe);
     this._settings = iframe;
 
     // When the iframe loads, populate it with the provider.
     this._settings.contentWindow
                   .addEventListener("load", function(e) {
 
@@ -1098,17 +1098,17 @@ var gApplicationsPane = {
       else
         this._visibleTypeDescriptionCount[handlerInfo.description] = 1;
     }
   },
 
   rebuildView: function() {
     // Clear the list of entries.
     while (this._list.childNodes.length > 1)
-      this._list.removeChild(this._list.lastChild);
+      this._list.lastChild.remove();
     var visibleTypes = this._visibleTypes;
 
     // If the user is filtering the list, then only show matching types.
     if (this._filter.value)
       visibleTypes = visibleTypes.filter(this._matchesFilter, this);
 
     for each (let visibleType in visibleTypes) {
       let item = document.createElement("richlistitem");
@@ -1321,17 +1321,17 @@ var gApplicationsPane = {
 
     var handlerInfo = this._handledTypes[typeItem.type];
     var menu =
       document.getAnonymousElementByAttribute(typeItem, "class", "actionsMenu");
     var menuPopup = menu.menupopup;
 
     // Clear out existing items.
     while (menuPopup.hasChildNodes())
-      menuPopup.removeChild(menuPopup.lastChild);
+      menuPopup.lastChild.remove();
 
     var askMenuItem = document.createElement("menuitem");
     askMenuItem.setAttribute("alwaysAsk", "true");
     {
       let label = this._prefsBundle.getString("alwaysAsk");
       askMenuItem.setAttribute("label", label);
       askMenuItem.setAttribute("tooltiptext", label);
       askMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
--- a/mail/components/preferences/compose.js
+++ b/mail/components/preferences/compose.js
@@ -172,17 +172,17 @@ var gComposePane = {
       {
         return a[0].localeCompare(b[0]);
       }
     );
 
     // Remove any languages from the list.
     var languageMenuPopup = languageMenuList.firstChild;
     while (languageMenuPopup.hasChildNodes())
-      languageMenuPopup.removeChild(languageMenuPopup.firstChild);
+      languageMenuPopup.lastChild.remove();
 
     // append the dictionaries to the menu list...
     for (i = 0; i < count; i++)
       languageMenuList.appendItem(dictList[i][0], dictList[i][1]);
 
     languageMenuList.setInitialSelection();
   },
 
--- a/mail/components/preferences/permissions.js
+++ b/mail/components/preferences/permissions.js
@@ -139,17 +139,17 @@ var gPermissionManager = {
       this.uninit();
     }
 
     this._type = aParams.permissionType;
     this._manageCapability = aParams.manageCapability;
 
     var permissionsText = document.getElementById("permissionsText");
     while (permissionsText.hasChildNodes())
-      permissionsText.removeChild(permissionsText.firstChild);
+      permissionsText.lastChild.remove();
     permissionsText.appendChild(document.createTextNode(aParams.introText));
 
     document.title = aParams.windowTitle;
 
     document.getElementById("btnBlock").hidden    = !aParams.blockVisible;
     document.getElementById("btnSession").hidden  = !aParams.sessionVisible;
     document.getElementById("btnAllow").hidden    = !aParams.allowVisible;
 
--- a/mail/components/preferences/sendoptions.js
+++ b/mail/components/preferences/sendoptions.js
@@ -61,17 +61,17 @@ var gSendOptionsDialog = {
 
   removeDomains: function(aHTML)
   {
     var listbox = aHTML ? this.mHTMLListBox : this.mPlainTextListBox;
 
     var currentIndex = listbox.currentIndex;
 
     while (listbox.selectedItems.length > 0) 
-      listbox.removeChild(listbox.selectedItems[0]);
+      listbox.selectedItems[0].remove();
 
     document.getElementById('SendOptionsDialogPane').userChangedValue(listbox);
   },
 
   addDomain: function (aHTML)
   {
     var listbox = aHTML ? this.mHTMLListBox : this.mPlainTextListBox;
 
--- a/mail/extensions/mailviews/content/mailViewList.js
+++ b/mail/extensions/mailviews/content/mailViewList.js
@@ -22,17 +22,17 @@ function mailViewListOnLoad()
 
   updateButtons();
 }
 
 function refreshListView(aSelectedMailView)
 {
   // remove any existing items in the view...
   for (var index = gListBox.getRowCount(); index > 0; index--)
-    gListBox.removeChild(gListBox.getItemAtIndex(index - 1));
+    gListBox.getItemAtIndex(index - 1).remove();
 
   var numItems = gMailListView.mailViewCount;
   var mailView; 
   for (index = 0; index < numItems; index++)
   {
     mailView = gMailListView.getMailViewAt(index);
     gListBox.appendItem(mailView.prettyName, index);
     if (aSelectedMailView && (mailView.prettyName == aSelectedMailView.prettyName) )
@@ -56,17 +56,17 @@ function onDeleteMailView()
   var selectedIndex = gListBox.selectedIndex;
   if (selectedIndex >= 0)
   {
     var mailView = gMailListView.getMailViewAt(selectedIndex);
     if (mailView)
     {
       gMailListView.removeMailView(mailView);
       // now remove it from the view...
-      gListBox.removeChild(gListBox.selectedItem);
+      gListBox.selectedItem.remove();
 
       // select the next item in the list..
       if (selectedIndex < gListBox.getRowCount())
         gListBox.selectedIndex = selectedIndex;
       else
         gListBox.selectedIndex = gListBox.getRowCount() - 1;
 
       gMailListView.save();
--- a/mail/extensions/mailviews/content/msgViewPickerOverlay.js
+++ b/mail/extensions/mailviews/content/msgViewPickerOverlay.js
@@ -201,17 +201,17 @@ function RefreshViewPopup(aViewPopup)
 function RefreshCustomViewsPopup(aMenupopup)
 {
   // for each mail view in the msg view list, add an entry in our combo box
   if (!gMailViewList)
     gMailViewList = Components.classes["@mozilla.org/messenger/mailviewlist;1"]
                               .getService(Components.interfaces.nsIMsgMailViewList);
   // remove all menuitems
   while (aMenupopup.hasChildNodes())
-    aMenupopup.removeChild(aMenupopup.lastChild);
+    aMenupopup.lastChild.remove();
 
   // now rebuild the list
   var currentView = ViewPickerBinding.currentViewValue;
   var numItems = gMailViewList.mailViewCount;
   for (var i = 0; i < numItems; ++i)
   {
     var viewInfo = gMailViewList.getMailViewAt(i);
     var menuitem = document.createElement("menuitem");
@@ -224,17 +224,17 @@ function RefreshCustomViewsPopup(aMenupo
   }
 }
 
 
 function RefreshTagsPopup(aMenupopup)
 {
   // remove all menuitems
   while (aMenupopup.hasChildNodes())
-    aMenupopup.removeChild(aMenupopup.lastChild);
+    aMenupopup.lastChild.remove();
 
   // create tag menuitems
   let currentTagKey = gFolderDisplay.view.mailViewIndex == kViewItemTags ?
                         gFolderDisplay.view.mailViewData : "";
   let tagArray = MailServices.tags.getAllTags({});
   for (let i = 0; i < tagArray.length; ++i)
   {
     let tagInfo = tagArray[i];
--- a/mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
+++ b/mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
@@ -767,18 +767,17 @@ function subtest_filelinks_work_after_ma
   let provider = new MockCloudfileAccount();
   provider.init("someKey");
   let cw = open_compose_new_mail();
   cw.window.attachToCloud(provider);
 
   let [root, list, urls] = wait_for_attachment_urls(cw, kFiles.length);
 
   // Now remove the root node from the document body
-  let mailBody = get_compose_body(cw);
-  mailBody.removeChild(root);
+  root.remove();
 
   gMockFilePicker.returnFiles = collectFiles(["./data/testFile3"], __file__);
   cw.window.attachToCloud(provider);
   [root, list, urls] = wait_for_attachment_urls(cw, 1);
 
   close_window(cw);
 }
 
--- a/mail/test/mozmill/folder-display/test-tooltip-multimessage.js
+++ b/mail/test/mozmill/folder-display/test-tooltip-multimessage.js
@@ -45,10 +45,10 @@ function test_tooltips() {
   // Test an HTML element.
   let a = mmDoc.createElement("a");
   a.setAttribute("href", "#");
   a.setAttribute("title", "Title2");
   a.setAttribute("tooltiptext", "TTT2");
   mm.appendChild(a);
   tooltip.fillInPageTooltip(a);
   assert_equals(tooltip.getAttribute("label"), "Title2", "This HTML element had its tooltiptext taken as the tooltip instead of the title attribute.");
-  mm.removeChild(a);
+  a.remove();
 }