Bug 1584122 - clean out some xbl related functionality: getAnonymousElementByAttribute, getAnonymousNodes. r=pmorris
authorMagnus Melin <mkmelin+mozilla@iki.fi>
Thu, 26 Sep 2019 15:59:36 +0300
changeset 36980 aab0650cbf1de00bf9f152a2ce0381f5046e7d22
parent 36979 8ce981f703f9218f5a64fa3366eedf26921db1e0
child 36981 9ec6769e2139cf73fa6d9f1a7ae3320ed187f317
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewerspmorris
bugs1584122
Bug 1584122 - clean out some xbl related functionality: getAnonymousElementByAttribute, getAnonymousNodes. r=pmorris
mail/base/content/nsContextMenu.js
mail/base/content/tabmail-tabs.js
mail/components/activity/content/activity.js
mail/test/mozmill/message-header/test-message-header.js
mail/test/mozmill/shared-modules/WindowHelpers.jsm
mail/themes/linux/mail/tabmail.css
mail/themes/osx/mail/tabmail.css
mailnews/base/search/content/searchWidgets.js
--- a/mail/base/content/nsContextMenu.js
+++ b/mail/base/content/nsContextMenu.js
@@ -581,28 +581,25 @@ nsContextMenu.prototype = {
     // internal vars
     // We also need to do that before we possibly bail because we just clicked
     // on some XUL node. Otherwise, dictionary choices just accumulate until we
     // right-click on some HTML element again.
     gSpellChecker.clearSuggestionsFromMenu();
     gSpellChecker.clearDictionaryListFromMenu();
     gSpellChecker.uninit();
 
-    const xulNS =
-      "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-    if (aNode.namespaceURI == xulNS) {
+    if (
+      aNode.namespaceURI ==
+      "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+    ) {
       if (aNode.localName == "treecol") {
         // The column header was clicked, show the column picker.
         let treecols = aNode.parentNode;
         let treeColPicker = treecols.querySelector("treecolpicker");
-        let popup = document.getAnonymousElementByAttribute(
-          treeColPicker,
-          "anonid",
-          "popup"
-        );
+        let popup = treeColPicker.querySelector(`menupopup[anonid="popup"]`);
         treeColPicker.buildPopup(popup);
         popup.openPopup(aNode, "before_start", 0, 0, true);
         this.shouldDisplay = false;
       }
       return;
     }
     this.onImage = false;
     this.onLoadedImage = false;
--- a/mail/base/content/tabmail-tabs.js
+++ b/mail/base/content/tabmail-tabs.js
@@ -546,21 +546,16 @@
 
       this._mAutoHide = false;
 
       this.mAllTabsButton = document.getElementById(
         this.getAttribute("alltabsbutton")
       );
       this.mAllTabsPopup = this.mAllTabsButton.menu;
 
-      // this.mAllTabsBoxAnimate = document.getAnonymousElementByAttribute(this,
-      //  "anonid",
-      //  "alltabs-box-animate");
-      // TODO ^^^ alltabs-box-animate seems to be dead code. remove all refs?
-
       this.mDownBoxAnimate = this.arrowScrollbox._scrollButtonDownBoxAnimate;
 
       this._animateTimer = null;
 
       this._animateStep = -1;
 
       this._animateDelay = 25;
 
--- a/mail/components/activity/content/activity.js
+++ b/mail/components/activity/content/activity.js
@@ -155,20 +155,17 @@ var activityObject = {
       if (!item.isGroup) {
         this._activityLogger.debug("is not a group, ");
         if (item.getAttribute("actID") == aID) {
           item.detachFromActivity();
           item.remove();
           break;
         }
       } else {
-        // string to identify the activity item through actID attribute
-        // in querySelector.
-        let actIDValueStr = "[actID='" + aID + "']";
-        let actElement = item.querySelector(actIDValueStr);
+        let actElement = item.querySelector(`[actID="${aID}"]`);
         if (actElement) {
           let groupView = document.querySelector(".activitygroupbox");
           actElement.detachFromActivity();
           actElement.remove();
 
           // if the group becomes empty after the removal,
           // get rid of the group as well
           if (groupView.getRowCount() == 0) {
@@ -234,30 +231,20 @@ var activityObject = {
     activityManager.cleanUp();
 
     let activities = this._activitiesView.childNodes;
     for (let i = activities.length - 1; i >= 0; i--) {
       let item = activities[i];
       if (!item.isGroup) {
         item.detachFromActivity();
       } else {
-        let actElement = document.getAnonymousElementByAttribute(
-          item,
-          "actID",
-          "*"
-        );
-        while (actElement) {
-          actElement.detachFromActivity();
-          actElement.remove();
-          actElement = document.getAnonymousElementByAttribute(
-            item,
-            "actID",
-            "*"
-          );
-        }
+        item.querySelectorAll("[actID]").forEach(elem => {
+          elem.detachFromActivity();
+          elem.remove();
+        });
       }
     }
 
     let empty = this._activitiesView.cloneNode(false);
     this._activitiesView.parentNode.replaceChild(empty, this._activitiesView);
     this._activitiesView = empty;
 
     this._groupCache.clear();
--- a/mail/test/mozmill/message-header/test-message-header.js
+++ b/mail/test/mozmill/message-header/test-message-header.js
@@ -236,141 +236,131 @@ let headersToTest = [
         headerValueElement.textContent
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Content-Base",
     headerValueElement(mc) {
-      return mc.a("expandedcontent-baseBox", {
-        class: "headerValue text-link headerValueUrl",
-      });
+      return mc.window.document.querySelector(
+        "#expandedcontent-baseBox > .headerValue.text-link.headerValueUrl"
+      );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedcontent-baseLabel").value +
         ": " +
         headerValueElement.textContent
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "From",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.e("expandedfromBox", { tagName: "mail-emailaddress" }),
-        "class",
-        "emailDisplayButton"
+      return mc.window.document.querySelector(
+        "#expandedfromBox > mail-emailaddress.emailDisplayButton"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedfromLabel").value +
         ": " +
         headerValueElement.parentNode.getAttribute("fullAddress")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "To",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.e("expandedtoBox", { tagName: "mail-emailaddress" }),
-        "class",
-        "emailDisplayButton"
+      return mc.window.document.querySelector(
+        "#expandedtoBox > mail-emailaddress.emailDisplayButton"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedtoLabel").value +
         ": " +
         headerValueElement.parentNode.getAttribute("fullAddress")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Cc",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.e("expandedccBox", { tagName: "mail-emailaddress" }),
-        "class",
-        "emailDisplayButton"
+      return mc.window.document.querySelector(
+        "#expandedccBox > mail-emailaddress.emailDisplayButton"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedccLabel").value +
         ": " +
         headerValueElement.parentNode.getAttribute("fullAddress")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Bcc",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.e("expandedbccBox", { tagName: "mail-emailaddress" }),
-        "class",
-        "emailDisplayButton"
+      return mc.window.document.querySelector(
+        "#expandedbccBox > mail-emailaddress.emailDisplayButton"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedbccLabel").value +
         ": " +
         headerValueElement.parentNode.getAttribute("fullAddress")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Reply-To",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.e("expandedreply-toBox", { tagName: "mail-emailaddress" }),
-        "class",
-        "emailDisplayButton"
+      return mc.window.document.querySelector(
+        "#expandedreply-toBox > mail-emailaddress.emailDisplayButton"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedreply-toLabel").value +
         ": " +
         headerValueElement.parentNode.getAttribute("fullAddress")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Newsgroups",
     headerValueElement(mc) {
-      return mc.window.document.getAnonymousElementByAttribute(
-        mc.a("expandednewsgroupsBox", { tagName: "mail-newsgroup" }),
-        "class",
-        "newsgrouplabel"
+      return mc.window.document.querySelector(
+        "#expandednewsgroupsBox > mail-newsgroup.newsgrouplabel"
       );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandednewsgroupsLabel").value +
         ": " +
         headerValueElement.parentNode.parentNode.getAttribute("newsgroup")
       );
     },
     expectedRole: Ci.nsIAccessibleRole.ROLE_ENTRY,
   },
   {
     headerName: "Tags",
     headerValueElement(mc) {
-      return mc.a("expandedtagsBox", { class: "tagvalue blc-FF0000" });
+      return mc.window.document.querySelector(
+        "#expandedtagsBox > .tagvalue.blc-FF0000"
+      );
     },
     expectedName(mc, headerValueElement) {
       return (
         mc.e("expandedtagsLabel").value +
         ": " +
         headerValueElement.getAttribute("value")
       );
     },
--- a/mail/test/mozmill/shared-modules/WindowHelpers.jsm
+++ b/mail/test/mozmill/shared-modules/WindowHelpers.jsm
@@ -978,78 +978,16 @@ var AugmentEverybodyWith = {
      *
      * @param aId The DOM id of the element you want to wait to show up.
      */
     ewait: function _wait_for_element_by_id_helper(aId) {
       this.waitForElement(new elib.ID(this.window.document, aId));
     },
 
     /**
-     * Find an element in the anonymous subtree of an element in the document
-     *  identified by its id.  You would use this to dig into XBL bindings that
-     *  are not doing what you want.  For example, jerks that don't focus right.
-     *
-     * Examples:
-     *  // by class of the node
-     *  a("searchVal0", {class: "search-value-textbox"});
-     *  // when the thing is vaguely deck-like
-     *  a("searchVal0", {crazyDeck: 0});
-     *  // when you want the first descendent with the given tagName
-     *  a("threadTree", {tagName: "treechildren"})
-     *
-     * @param aId The element id or the actual element.
-     *
-     * @return the anonymous element determined by the query found in the
-     *  anonymous sub-tree of the element with the given id.
-     */
-    a: function _get_anon_element_by_id_and_query(aId, aQuery) {
-      let realElem =
-        typeof aId == "string" ? this.window.document.getElementById(aId) : aId;
-      if (aQuery.class) {
-        return this.window.document.getAnonymousElementByAttribute(
-          realElem,
-          "class",
-          aQuery.class
-        );
-      } else if (aQuery.crazyDeck != null) {
-        let anonNodes = this.window.document.getAnonymousNodes(realElem);
-        let index;
-        if (realElem.hasAttribute("selectedIndex")) {
-          index = parseInt(realElem.getAttribute("selectedIndex"));
-        } else {
-          index = aQuery.crazyDeck;
-        }
-        let elem = anonNodes[index];
-        return elem;
-      } else if (aQuery.tagName) {
-        let anonNodes = this.window.document.getAnonymousNodes(realElem);
-        for (let iNode = 0; iNode < anonNodes.length; iNode++) {
-          let node = anonNodes[iNode];
-          let named = node.querySelector(aQuery.tagName);
-          if (named) {
-            return named;
-          }
-        }
-      } else {
-        let msg = "Query constraint not implemented, query contained:";
-        for (let [key, val] of Object.entries(aQuery)) {
-          msg += " '" + key + "': " + val;
-        }
-        throw new Error(msg);
-      }
-      return null;
-    },
-    /**
-     * Wraps a call to a() in an elib.Elem.
-     */
-    aid: function _get_anon_elementid(aId, aQuery) {
-      return new elib.Elem(this.a(aId, aQuery));
-    },
-
-    /**
      * Debug helper that defers a click until the next event loop spin in order
      *  to create situations that are hard to test in isolation.  In order to
      *  fashion reliable failures, we currently use a 1-second delay to make
      *  sure things get sufficiently gummed up.
      * Only use this for locally reproducing tinderbox failures; do not commit
      *  code that uses this!
      *
      * This gets its own method rather than a generic deferring wrapper so we
--- a/mail/themes/linux/mail/tabmail.css
+++ b/mail/themes/linux/mail/tabmail.css
@@ -85,21 +85,16 @@ tabpanels {
   background: var(--toolbarbutton-active-background);
 }
 
 .tabmail-arrowscrollbox > .scrollbutton-up[disabled],
 .tabmail-arrowscrollbox > .scrollbutton-down[disabled] {
   --toolbarbutton-icon-fill-opacity: .4;
 }
 
-.tabs-alltabs-box-animate {
-  background-color: Highlight;
-  opacity: 0;
-}
-
 /**
  * All Tabs Menupopup
  */
 
 .tabs-alltabs-button {
   min-width: 24px;
   padding-right: 1px;
   padding-left: 1px;
--- a/mail/themes/osx/mail/tabmail.css
+++ b/mail/themes/osx/mail/tabmail.css
@@ -177,23 +177,16 @@ tabmail > tabbox > tabpanels {
 /**
  * All Tabs Buttons
  */
 
 .tabs-alltabs-box {
   margin: 0;
 }
 
-.tabs-alltabs-box-animate {
-  margin: 1px 0px 0px;
-  width: 25px;
-  background-color: #669CFF;
-  opacity: 0.0;
-}
-
 /**
  * All Tabs Menupopup
  */
 
 @media (min-resolution: 1.1dppx) {
   alltabs-item[busy] {
     list-style-image: url("chrome://global/skin/icons/loading@2x.png") !important;
   }
--- a/mailnews/base/search/content/searchWidgets.js
+++ b/mailnews/base/search/content/searchWidgets.js
@@ -100,25 +100,24 @@
       const menuPopup = document.createXULElement("menupopup");
 
       menulist.classList.add("ruleactionitem");
       menulist.setAttribute("flex", "1");
       menulist.appendChild(menuPopup);
 
       this.appendChild(menulist);
 
-      document
-        .getAnonymousElementByAttribute(
-          this.closest(".ruleaction"),
-          "is",
-          "ruleactiontype-menulist"
-        )
-        .getTemplates(true, menulist);
-
-      updateParentNode(this.closest(".ruleaction"));
+      let ruleaction = this.closest(".ruleaction");
+      let raMenulist = ruleaction.querySelector(
+        '[is="ruleactiontype-menulist"]'
+      );
+      for (let { label, value } of raMenulist.findTemplates()) {
+        menulist.appendItem(label, value);
+      }
+      updateParentNode(ruleaction);
     }
   }
 
   class MozRuleactiontargetForwardto extends MozXULElement {
     connectedCallback() {
       const textbox = document.createXULElement("textbox");
 
       textbox.classList.add("ruleactionitem");
@@ -1305,17 +1304,17 @@
         for (let i = 0; i < gCustomActions.length; i++) {
           elements[i].hidden = !gCustomActions[i].isValidForType(
             gFilterType,
             scope
           );
         }
 
         // Disable "Reply with Template" if there are no templates.
-        if (!this.getTemplates(false)) {
+        if (this.findTemplates().length == 0) {
           elements = menupopup.getElementsByAttribute(
             "value",
             "replytomessage"
           );
           if (elements.length == 1) {
             elements[0].hidden = true;
           }
         }
@@ -1387,41 +1386,36 @@
             }
           }
         }
         return usedActions;
       }
 
       /**
        * Check if there exist any templates in this account.
-       *
-       * @param populateTemplateList  If true, create menuitems representing
-       *                              the found templates.
-       * @param templateMenuList      The menulist element to create items in.
-       *
-       * @return {boolean}           True if at least one template was found,
-       *                              otherwise false.
+       * @return {Object[]} - An array of template headers: each has a label and
+       *                      a value.
        */
-      getTemplates(populateTemplateList, templateMenuList) {
+      findTemplates() {
         let identitiesRaw = MailServices.accounts.getIdentitiesForServer(
           gFilterList.folder.server
         );
         let identities = Array.from(
           fixIterator(identitiesRaw, Ci.nsIMsgIdentity)
         );
         // Typically if this is Local Folders.
         if (identities.length == 0) {
           if (MailServices.accounts.defaultAccount) {
             identities.push(
               MailServices.accounts.defaultAccount.defaultIdentity
             );
           }
         }
 
-        let templateFound = false;
+        let templates = [];
         let foldersScanned = [];
 
         for (let identity of identities) {
           let enumerator = null;
           let msgFolder = MailUtils.getExistingFolder(
             identity.stationeryFolder
           );
           // If we already processed this folder, do not set enumerator
@@ -1433,34 +1427,27 @@
 
           if (!enumerator) {
             continue;
           }
 
           while (enumerator.hasMoreElements()) {
             let header = enumerator.getNext();
             if (header instanceof Ci.nsIMsgDBHdr) {
-              templateFound = true;
-              if (!populateTemplateList) {
-                return true;
-              }
-              let msgTemplateUri =
+              let uri =
                 msgFolder.URI +
                 "?messageId=" +
                 header.messageId +
                 "&subject=" +
                 header.mime2DecodedSubject;
-              templateMenuList.appendItem(
-                header.mime2DecodedSubject,
-                msgTemplateUri
-              );
+              templates.push({ label: header.mime2DecodedSubject, value: uri });
             }
           }
         }
-        return templateFound;
+        return templates;
       }
     }
 
     customElements.define(
       "ruleactiontype-menulist",
       MozRuleactiontypeMenulist,
       { extends: "menulist" }
     );
@@ -1709,20 +1696,16 @@
         case "replytomessage":
           if (
             !actionTarget.ruleactiontargetElement.childNodes[0].selectedItem
           ) {
             errorString = "pickTemplateToReplyWith";
           }
           break;
         default:
-          // Some custom actions have no action value node.
-          if (!document.getAnonymousNodes(actionTarget)) {
-            return true;
-          }
           // Locate the correct custom action, and check validity.
           for (let i = 0; i < gCustomActions.length; i++) {
             if (gCustomActions[i].id == filterActionString) {
               customError = gCustomActions[i].validateActionValue(
                 actionTargetLabel,
                 gFilterList.folder,
                 gFilterType
               );