Bug 1354186 - Change managerListeners, installListeners, addonListeners and typeListeners from Array to Set. r=aswan
authortiago <tiago.paez11@gmail.com>
Fri, 19 May 2017 01:56:05 -0300
changeset 414806 287690a1fedccf65eafe6e26366794c1231a7cb9
parent 414805 114fb8a5f56cdff35784193d3143039aa43b48c8
child 414807 ec3b803e1b911a738fd47afa83224fdaff101a9d
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1354186
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1354186 - Change managerListeners, installListeners, addonListeners and typeListeners from Array to Set. r=aswan MozReview-Commit-ID: CZ5HlhWihHO
toolkit/mozapps/extensions/AddonManager.jsm
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -630,20 +630,20 @@ var gPluginPageListener = null;
 var gBrowserUpdated = null;
 var gNonMpcDisabled = false;
 
 /**
  * This is the real manager, kept here rather than in AddonManager to keep its
  * contents hidden from API users.
  */
 var AddonManagerInternal = {
-  managerListeners: [],
-  installListeners: [],
-  addonListeners: [],
-  typeListeners: [],
+  managerListeners: new Set(),
+  installListeners: new Set(),
+  addonListeners: new Set(),
+  typeListeners: new Set(),
   pendingProviders: new Set(),
   providers: new Set(),
   providerShutdowns: new Map(),
   types: {},
   startupChanges: {},
   // Store telemetry details per addon provider
   telemetryDetails: {},
   upgradeListeners: new Map(),
@@ -959,17 +959,17 @@ var AddonManagerInternal = {
             return;
           }
 
           this.types[type.id] = {
             type,
             providers: [aProvider]
           };
 
-          let typeListeners = this.typeListeners.slice(0);
+          let typeListeners = new Set(this.typeListeners);
           for (let listener of typeListeners)
             safeCall(() => listener.onTypeAdded(type));
         } else {
           this.types[type.id].providers.push(aProvider);
         }
       }
     }
 
@@ -1000,17 +1000,17 @@ var AddonManagerInternal = {
     this.pendingProviders.delete(aProvider);
 
     for (let type in this.types) {
       this.types[type].providers = this.types[type].providers.filter(p => p != aProvider);
       if (this.types[type].providers.length == 0) {
         let oldType = this.types[type].type;
         delete this.types[type];
 
-        let typeListeners = this.typeListeners.slice(0);
+        let typeListeners = new Set(this.typeListeners);
         for (let listener of typeListeners)
           safeCall(() => listener.onTypeRemoved(oldType));
       }
     }
 
     // If we're unregistering after startup but before shutting down,
     // remove the blocker for this provider's shutdown and call it.
     // If we're already shutting down, just let gShutdownBarrier call it to avoid races.
@@ -1145,20 +1145,20 @@ var AddonManagerInternal = {
       gRepoShutdownState = "done";
     } catch (err) {
       savedError = err;
       logger.error("Failure during AddonRepository shutdown", err);
       AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonRepository", err);
     }
 
     logger.debug("Async provider shutdown done");
-    this.managerListeners.splice(0, this.managerListeners.length);
-    this.installListeners.splice(0, this.installListeners.length);
-    this.addonListeners.splice(0, this.addonListeners.length);
-    this.typeListeners.splice(0, this.typeListeners.length);
+    this.managerListeners.clear();
+    this.installListeners.clear();
+    this.addonListeners.clear();
+    this.typeListeners.clear();
     this.providerShutdowns.clear();
     for (let type in this.startupChanges)
       delete this.startupChanges[type];
     gStarted = false;
     gStartupComplete = false;
     gShutdownBarrier = null;
     gShutdownInProgress = false;
     if (savedError) {
@@ -1595,17 +1595,17 @@ var AddonManagerInternal = {
     if (!gStarted)
       throw Components.Exception("AddonManager is not initialized",
                                  Cr.NS_ERROR_NOT_INITIALIZED);
 
     if (!aMethod || typeof aMethod != "string")
       throw Components.Exception("aMethod must be a non-empty string",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let managerListeners = this.managerListeners.slice(0);
+    let managerListeners = new Set(this.managerListeners);
     for (let listener of managerListeners) {
       try {
         if (aMethod in listener)
           listener[aMethod].apply(listener, aArgs);
       } catch (e) {
         logger.warn("AddonManagerListener threw exception when calling " + aMethod, e);
       }
     }
@@ -1633,19 +1633,19 @@ var AddonManagerInternal = {
 
     if (aExtraListeners && !Array.isArray(aExtraListeners))
       throw Components.Exception("aExtraListeners must be an array or null",
                                  Cr.NS_ERROR_INVALID_ARG);
 
     let result = true;
     let listeners;
     if (aExtraListeners)
-      listeners = aExtraListeners.concat(this.installListeners);
+      listeners = new Set(aExtraListeners.concat(Array.from(this.installListeners)));
     else
-      listeners = this.installListeners.slice(0);
+      listeners = new Set(this.installListeners);
 
     for (let listener of listeners) {
       try {
         if (aMethod in listener) {
           if (listener[aMethod].apply(listener, aArgs) === false)
             result = false;
         }
       } catch (e) {
@@ -1666,17 +1666,17 @@ var AddonManagerInternal = {
     if (!gStarted)
       throw Components.Exception("AddonManager is not initialized",
                                  Cr.NS_ERROR_NOT_INITIALIZED);
 
     if (!aMethod || typeof aMethod != "string")
       throw Components.Exception("aMethod must be a non-empty string",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let addonListeners = this.addonListeners.slice(0);
+    let addonListeners = new Set(this.addonListeners);
     for (let listener of addonListeners) {
       try {
         if (aMethod in listener)
           listener[aMethod].apply(listener, aArgs);
       } catch (e) {
         logger.warn("AddonListener threw exception when calling " + aMethod, e);
       }
     }
@@ -2184,40 +2184,31 @@ var AddonManagerInternal = {
    * @param  aListener
    *         The InstallListener to add
    */
   addInstallListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be a InstallListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    if (!this.installListeners.some(function(i) {
-      return i == aListener;
-}))
-      this.installListeners.push(aListener);
+      this.installListeners.add(aListener);
   },
 
   /**
    * Removes an InstallListener if the listener is registered.
    *
    * @param  aListener
    *         The InstallListener to remove
    */
   removeInstallListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be a InstallListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let pos = 0;
-    while (pos < this.installListeners.length) {
-      if (this.installListeners[pos] == aListener)
-        this.installListeners.splice(pos, 1);
-      else
-        pos++;
-    }
+    this.installListeners.delete(aListener);
   },
   /*
    * Adds new or overrides existing UpgradeListener.
    *
    * @param  aInstanceID
    *         The instance ID of an addon to register a listener for.
    * @param  aCallback
    *         The callback to invoke when updates are available for this addon.
@@ -2589,108 +2580,87 @@ var AddonManagerInternal = {
    * @param  aListener
    *         The listener to add
    */
   addManagerListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be an AddonManagerListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    if (!this.managerListeners.some(i => i == aListener))
-      this.managerListeners.push(aListener);
+    this.managerListeners.add(aListener);
   },
 
   /**
    * Removes an AddonManagerListener if the listener is registered.
    *
    * @param  aListener
    *         The listener to remove
    */
   removeManagerListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be an AddonManagerListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let pos = 0;
-    while (pos < this.managerListeners.length) {
-      if (this.managerListeners[pos] == aListener)
-        this.managerListeners.splice(pos, 1);
-      else
-        pos++;
-    }
+    this.managerListeners.delete(aListener);
   },
 
   /**
    * Adds a new AddonListener if the listener is not already registered.
    *
    * @param  aListener
    *         The AddonListener to add
    */
   addAddonListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be an AddonListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    if (!this.addonListeners.some(i => i == aListener))
-      this.addonListeners.push(aListener);
+    this.addonListeners.add(aListener);
   },
 
   /**
    * Removes an AddonListener if the listener is registered.
    *
    * @param  aListener
    *         The AddonListener to remove
    */
   removeAddonListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be an AddonListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let pos = 0;
-    while (pos < this.addonListeners.length) {
-      if (this.addonListeners[pos] == aListener)
-        this.addonListeners.splice(pos, 1);
-      else
-        pos++;
-    }
+    this.addonListeners.delete(aListener);
   },
 
   /**
    * Adds a new TypeListener if the listener is not already registered.
    *
    * @param  aListener
    *         The TypeListener to add
    */
   addTypeListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be a TypeListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    if (!this.typeListeners.some(i => i == aListener))
-      this.typeListeners.push(aListener);
+    this.typeListeners.add(aListener);
   },
 
   /**
    * Removes an TypeListener if the listener is registered.
    *
    * @param  aListener
    *         The TypeListener to remove
    */
   removeTypeListener(aListener) {
     if (!aListener || typeof aListener != "object")
       throw Components.Exception("aListener must be a TypeListener object",
                                  Cr.NS_ERROR_INVALID_ARG);
 
-    let pos = 0;
-    while (pos < this.typeListeners.length) {
-      if (this.typeListeners[pos] == aListener)
-        this.typeListeners.splice(pos, 1);
-      else
-        pos++;
-    }
+    this.typeListeners.delete(aListener);
   },
 
   get addonTypes() {
     // A read-only wrapper around the types dictionary
     return new Proxy(this.types, {
       defineProperty(target, property, descriptor) {
         // Not allowed to define properties
         return false;