Bug 1517818 - add some guards against adding children and event listeners more than once since connectedCallback() can run many times. r=arshad a=jorgk
authorMagnus Melin <mkmelin+mozilla@iki.fi>
Thu, 28 Mar 2019 15:16:52 +0200
changeset 33971 1599c84ad552ea0ba55cc708a72cbdee25ccecb9
parent 33970 e4751d2e281f1e75367ca24b5bd11f13c925a474
child 33972 d9af5609d45e9208eada712d2b210d35db2e45d6
push id2394
push usermozilla@jorgk.com
push dateSat, 30 Mar 2019 21:10:54 +0000
treeherdercomm-beta@a07bc5354c40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarshad, jorgk
bugs1517818
Bug 1517818 - add some guards against adding children and event listeners more than once since connectedCallback() can run many times. r=arshad a=jorgk
mail/base/content/mailWidgets.js
--- a/mail/base/content/mailWidgets.js
+++ b/mail/base/content/mailWidgets.js
@@ -23,29 +23,35 @@ class MozMailHeaderfield extends MozXULE
     this.setAttribute("context", "copyPopup");
     this.classList.add("headerValue");
   }
 
   set headerValue(val) {
     return (this.textContent = val);
   }
 }
+customElements.define("mail-headerfield", MozMailHeaderfield);
 
 class MozMailUrlfield extends MozMailHeaderfield {
-  connectedCallback() {
-    super.connectedCallback();
-    this.setAttribute("context", "copyUrlPopup");
-    this.classList.add("text-link", "headerValueUrl");
+  constructor() {
+    super();
     this.addEventListener("click", (event) => {
       if (event.button != 2) {
         openUILink(encodeURI(event.target.textContent), event);
       }
     });
   }
+
+  connectedCallback() {
+    super.connectedCallback();
+    this.setAttribute("context", "copyUrlPopup");
+    this.classList.add("text-link", "headerValueUrl");
+  }
 }
+customElements.define("mail-urlfield", MozMailUrlfield);
 
 class MozMailHeaderfieldTags extends MozXULElement {
   connectedCallback() {
     this.classList.add("headerValue");
   }
 
   set headerValue(val) {
     return this.buildTags(val);
@@ -85,24 +91,26 @@ class MozMailHeaderfieldTags extends Moz
       label.setAttribute("value", tagName);
       label.className = "tagvalue";
       label.setAttribute("style", "color: " + textColor + "; background-color: " + color + ";");
 
       this.appendChild(label);
     }
   }
 }
+customElements.define("mail-tagfield", MozMailHeaderfieldTags);
 
 class MozMailNewsgroup extends MozXULElement {
   connectedCallback() {
     this.classList.add("emailDisplayButton");
     this.setAttribute("context", "newsgroupPopup");
     this.setAttribute("popup", "newsgroupPopup");
   }
 }
+customElements.define("mail-newsgroup", MozMailNewsgroup);
 
 class MozMailNewsgroupsHeaderfield extends MozXULElement {
   connectedCallback() {
     this.classList.add("headerValueBox");
     this.mNewsgroups = [];
   }
 
   addNewsgroupView(aNewsgroup) {
@@ -127,30 +135,34 @@ class MozMailNewsgroupsHeaderfield exten
 
   clearHeaderValues() {
     this.mNewsgroups = [];
     while (this.hasChildNodes()) {
       this.lastChild.remove();
     }
   }
 }
+customElements.define("mail-newsgroups-headerfield", MozMailNewsgroupsHeaderfield);
 
 class MozMailMessageid extends MozXULElement {
   static get observedAttributes() {
     return ["label"];
   }
 
+  constructor() {
+    super();
+    this.addEventListener("click", (event) => {
+      MessageIdClick(this, event);
+    });
+  }
+
   connectedCallback() {
     this.classList.add("messageIdDisplayButton");
     this.setAttribute("context", "messageIdContext");
     this._updateAttributes();
-
-    this.addEventListener("click", (event) => {
-      MessageIdClick(this, event);
-    });
   }
 
   attributeChangedCallback() {
     this._updateAttributes();
   }
 
   _updateAttributes() {
     this.textContent = this.label || "";
@@ -165,16 +177,17 @@ class MozMailMessageid extends MozXULEle
 
     return val;
   }
 
   get label() {
     return this.getAttribute("label");
   }
 }
+customElements.define("mail-messageid", MozMailMessageid);
 
 /**
  * MozMailMessageidsHeaderfield is a widget used to show/link messages in the message header.
  * Shown by default for nntp messages, not for regular emails.
  * @extends {MozXULElement}
  */
 class MozMailMessageidsHeaderfield extends MozXULElement {
   connectedCallback() {
@@ -279,16 +292,19 @@ class MozMailEmailaddress extends MozXUL
       "crop",
       "tooltipstar",
       "chatStatus",
       "presenceTooltip",
     ];
   }
 
   connectedCallback() {
+    if (this.hasChildNodes() || this.delayConnectedCallback()) {
+      return;
+    }
     this.classList.add("emailDisplayButton");
     this.setAttribute("context", "emailAddressPopup");
     this.setAttribute("popup", "emailAddressPopup");
 
     const label = document.createElement("label");
     label.classList.add("emaillabel");
 
     const emailStarImage = document.createElement("image");
@@ -297,31 +313,28 @@ class MozMailEmailaddress extends MozXUL
 
     const emailPresenceImage = document.createElement("image");
     emailPresenceImage.classList.add("emailPresence");
 
     this.appendChild(label);
     this.appendChild(emailStarImage);
     this.appendChild(emailPresenceImage);
 
-    this._areChildrenAppended = true;
-
     this._update();
     this._setupEventListeners();
   }
 
   attributeChangedCallback() {
+    if (!this.isConnectedAndReady) {
+      return;
+    }
     this._update();
   }
 
   _update() {
-    if (!this.isConnected || !this._areChildrenAppended) {
-      return;
-    }
-
     const emailLabel = this.querySelector(".emaillabel");
     const emailStarImage = this.querySelector(".emailStar");
     const emailPresenceImage = this.querySelector(".emailPresence");
 
     this._updateNodeAttributes(emailLabel, "crop");
     this._updateNodeAttributes(emailLabel, "value", "label");
 
     this._updateNodeAttributes(emailStarImage, "hascard");
@@ -360,53 +373,60 @@ class MozMailEmailaddress extends MozXUL
       event.preventDefault();
     });
 
     emailPresenceImage.addEventListener("click", (event) => {
       onClickEmailPresence(event, this);
     });
   }
 }
+customElements.define("mail-emailaddress", MozMailEmailaddress);
 
 class MozMailEmailheaderfield extends MozXULElement {
   connectedCallback() {
+    if (this.hasChildNodes() || this.delayConnectedCallback()) {
+      return;
+    }
     this._mailEmailAddress = document.createElement("mail-emailaddress");
     this._mailEmailAddress.classList.add("headerValue");
     this._mailEmailAddress.setAttribute("containsEmail", "true");
 
     this.appendChild(this._mailEmailAddress);
   }
 
   get emailAddressNode() {
     return this._mailEmailAddress;
   }
 }
+customElements.define("mail-emailheaderfield", MozMailEmailheaderfield);
 
 class MozTreecolImage extends customElements.get("treecol") {
   static get observedAttributes() {
     return ["src"];
   }
 
   connectedCallback() {
+    if (this.hasChildNodes() || this.delayConnectedCallback()) {
+      return;
+    }
     this.image = document.createElement("image");
     this.image.classList.add("treecol-icon");
 
     this.appendChild(this.image);
     this._updateAttributes();
   }
 
   attributeChangedCallback() {
+    if (!this.isConnectedAndReady) {
+      return;
+    }
     this._updateAttributes();
   }
 
   _updateAttributes() {
-    if (!this.isConnected || !this.image) {
-      return;
-    }
-
     const src = this.getAttribute("src");
 
     if (src != null) {
       this.image.setAttribute("src", src);
     } else {
       this.image.removeAttribute("src");
     }
   }
@@ -543,25 +563,16 @@ class MozThreadPaneTreeColpicker extends
       destFolder.setStringProperty(propName, colStateString(destFolder));
       // null out to avoid memory bloat
       destFolder.msgDatabase = null;
     }
   }
 }
 customElements.define("thread-pane-treecolpicker", MozThreadPaneTreeColpicker, { extends: "treecolpicker" });
 
-customElements.define("mail-headerfield", MozMailHeaderfield);
-customElements.define("mail-urlfield", MozMailUrlfield);
-customElements.define("mail-tagfield", MozMailHeaderfieldTags);
-customElements.define("mail-newsgroup", MozMailNewsgroup);
-customElements.define("mail-newsgroups-headerfield", MozMailNewsgroupsHeaderfield);
-customElements.define("mail-messageid", MozMailMessageid);
-customElements.define("mail-emailaddress", MozMailEmailaddress);
-customElements.define("mail-emailheaderfield", MozMailEmailheaderfield);
-
 customElements.whenDefined("menulist").then(() => {
   /**
    * MozMenulistEditable is a menulist widget that can be made editable by setting editable="true".
    * With an additional type="description" the list also contains an additional label that can hold
    * for instance, a description of a menu item.
    * It is typically used e.g. for the "Custom From Address..." feature to let the user chose and
    * edit the address to send from.
    * @extends {MozMenuList}