Bug 1387898: Remove unnecessary uses of EventEmitter.decorate. r?mixedpuppy draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 06 Aug 2017 15:38:59 -0700
changeset 641399 502eab2879b44db9cbfe7c67b25638fbd54dadc4
parent 641398 8cced6430d30ae701d44987a30ffdda51ce05553
child 641401 094d227a2f6ea2aa357b2c29925a5737a398c0c8
push id72505
push usermaglione.k@gmail.com
push dateSun, 06 Aug 2017 22:49:19 +0000
reviewersmixedpuppy
bugs1387898
milestone57.0a1
Bug 1387898: Remove unnecessary uses of EventEmitter.decorate. r?mixedpuppy MozReview-Commit-ID: FRCdXHc3S4K
browser/components/extensions/ext-bookmarks.js
browser/components/extensions/ext-browser.js
browser/components/extensions/ext-browserAction.js
browser/components/extensions/ext-c-devtools-panels.js
browser/components/extensions/ext-commands.js
browser/components/extensions/ext-history.js
browser/components/extensions/ext-pageAction.js
browser/components/extensions/ext-utils.js
toolkit/components/extensions/ExtensionAPI.jsm
toolkit/components/extensions/ext-downloads.js
toolkit/components/extensions/ext-idle.js
toolkit/components/extensions/ext-management.js
toolkit/components/extensions/ext-notifications.js
--- a/browser/components/extensions/ext-bookmarks.js
+++ b/browser/components/extensions/ext-bookmarks.js
@@ -75,22 +75,26 @@ const convertBookmarks = result => {
     node.url = result.url.href; // Output is always URL object.
   } else {
     node.dateGroupModified = result.lastModified.getTime();
   }
 
   return node;
 };
 
-let observer = {
-  skipTags: true,
-  skipDescendantsOnItemRemoval: true,
+let observer = new class extends EventEmitter {
+  constructor() {
+    super();
 
-  onBeginUpdateBatch() {},
-  onEndUpdateBatch() {},
+    this.skipTags = true;
+    this.skipDescendantsOnItemRemoval = true;
+  }
+
+  onBeginUpdateBatch() {}
+  onEndUpdateBatch() {}
 
   onItemAdded(id, parentId, index, itemType, uri, title, dateAdded, guid, parentGuid, source) {
     if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
       return;
     }
 
     let bookmark = {
       id: guid,
@@ -102,33 +106,33 @@ let observer = {
 
     if (itemType == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
       bookmark.url = uri.spec;
     } else {
       bookmark.dateGroupModified = bookmark.dateAdded;
     }
 
     this.emit("created", bookmark);
-  },
+  }
 
-  onItemVisited() {},
+  onItemVisited() {}
 
   onItemMoved(id, oldParentId, oldIndex, newParentId, newIndex, itemType, guid, oldParentGuid, newParentGuid, source) {
     if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
       return;
     }
 
     let info = {
       parentId: newParentGuid,
       index: newIndex,
       oldParentId: oldParentGuid,
       oldIndex,
     };
     this.emit("moved", {guid, info});
-  },
+  }
 
   onItemRemoved(id, parentId, index, itemType, uri, guid, parentGuid, source) {
     if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
       return;
     }
 
     let node = {
       id: guid,
@@ -136,17 +140,17 @@ let observer = {
       index,
     };
 
     if (itemType == PlacesUtils.bookmarks.TYPE_BOOKMARK) {
       node.url = uri.spec;
     }
 
     this.emit("removed", {guid, info: {parentId: parentGuid, index, node}});
-  },
+  }
 
   onItemChanged(id, prop, isAnno, val, lastMod, itemType, parentId, guid, parentGuid, oldVal, source) {
     if (itemType == PlacesUtils.bookmarks.TYPE_SEPARATOR) {
       return;
     }
 
     let info = {};
     if (prop == "title") {
@@ -154,19 +158,18 @@ let observer = {
     } else if (prop == "uri") {
       info.url = val;
     } else {
       // Not defined yet.
       return;
     }
 
     this.emit("changed", {guid, info});
-  },
-};
-EventEmitter.decorate(observer);
+  }
+}();
 
 const decrementListeners = () => {
   listenerCount -= 1;
   if (!listenerCount) {
     PlacesUtils.bookmarks.removeObserver(observer);
   }
 };
 
--- a/browser/components/extensions/ext-browser.js
+++ b/browser/components/extensions/ext-browser.js
@@ -1,15 +1,14 @@
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-utils.js */
 
-XPCOMUtils.defineLazyModuleGetter(global, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
+global.EventEmitter = ExtensionUtils.EventEmitter;
 
 // This function is pretty tightly tied to Extension.jsm.
 // Its job is to fill in the |tab| property of the sender.
 const getSender = (extension, target, sender) => {
   let tabId;
   if ("tabId" in sender) {
     // The message came from a privileged extension page running in a tab. In
     // that case, it should include a tabId property (which is filled in by the
--- a/browser/components/extensions/ext-browserAction.js
+++ b/browser/components/extensions/ext-browserAction.js
@@ -100,18 +100,16 @@ this.browserAction = class extends Exten
     if (options.browser_style === null) {
       this.extension.logger.warn("Please specify whether you want browser_style " +
                                  "or not in your browser_action options.");
     }
 
     this.tabContext = new TabContext(tab => Object.create(this.defaults),
                                      extension);
 
-    EventEmitter.decorate(this);
-
     this.build();
     browserActionMap.set(extension, this);
   }
 
   onShutdown(reason) {
     browserActionMap.delete(this.extension);
 
     this.tabContext.shutdown();
--- a/browser/components/extensions/ext-c-devtools-panels.js
+++ b/browser/components/extensions/ext-c-devtools-panels.js
@@ -1,34 +1,32 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ../../../toolkit/components/extensions/ext-c-toolkit.js */
 
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionChildDevToolsUtils",
                                   "resource://gre/modules/ExtensionChildDevToolsUtils.jsm");
 
 var {
   promiseDocumentLoaded,
 } = ExtensionUtils;
 
 /**
  * Represents an addon devtools panel in the child process.
  *
  * @param {DevtoolsExtensionContext}
  *   A devtools extension context running in a child process.
  * @param {object} panelOptions
  * @param {string} panelOptions.id
  *   The id of the addon devtools panel registered in the main process.
  */
-class ChildDevToolsPanel extends EventEmitter {
+class ChildDevToolsPanel extends ExtensionUtils.EventEmitter {
   constructor(context, {id}) {
     super();
 
     this.context = context;
     this.context.callOnClose(this);
 
     this.id = id;
     this._panelContext = null;
--- a/browser/components/extensions/ext-commands.js
+++ b/browser/components/extensions/ext-commands.js
@@ -20,17 +20,16 @@ this.commands = class extends ExtensionA
 
     // Map[{String} commandName -> {Object} commandProperties]
     this.commands = this.loadCommandsFromManifest(this.extension.manifest);
 
     // WeakMap[Window -> <xul:keyset>]
     this.keysetsMap = new WeakMap();
 
     this.register();
-    EventEmitter.decorate(this);
   }
 
   onShutdown(reason) {
     this.unregister();
   }
 
   /**
    * Registers the commands to all open windows and to any which
--- a/browser/components/extensions/ext-history.js
+++ b/browser/components/extensions/ext-history.js
@@ -87,47 +87,46 @@ const convertNavHistoryContainerResultNo
   container.containerOpen = false;
   return results;
 };
 
 var _observer;
 
 const getHistoryObserver = () => {
   if (!_observer) {
-    _observer = {
-      onDeleteURI: function(uri, guid, reason) {
+    _observer = new class extends EventEmitter {
+      onDeleteURI(uri, guid, reason) {
         this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
-      },
-      onVisit: function(uri, visitId, time, sessionId, referringId, transitionType, guid, hidden, visitCount, typed, lastKnownTitle) {
+      }
+      onVisit(uri, visitId, time, sessionId, referringId, transitionType, guid, hidden, visitCount, typed, lastKnownTitle) {
         let data = {
           id: guid,
           url: uri.spec,
           title: lastKnownTitle || "",
           lastVisitTime: time / 1000,  // time from Places is microseconds,
           visitCount,
           typedCount: typed,
         };
         this.emit("visited", data);
-      },
-      onBeginUpdateBatch: function() {},
-      onEndUpdateBatch: function() {},
-      onTitleChanged: function(uri, title) {
+      }
+      onBeginUpdateBatch() {}
+      onEndUpdateBatch() {}
+      onTitleChanged(uri, title) {
         this.emit("titleChanged", {url: uri.spec, title: title});
-      },
-      onClearHistory: function() {
+      }
+      onClearHistory() {
         this.emit("visitRemoved", {allHistory: true, urls: []});
-      },
-      onPageChanged: function() {},
-      onFrecencyChanged: function() {},
-      onManyFrecenciesChanged: function() {},
-      onDeleteVisits: function(uri, time, guid, reason) {
+      }
+      onPageChanged() {}
+      onFrecencyChanged() {}
+      onManyFrecenciesChanged() {}
+      onDeleteVisits(uri, time, guid, reason) {
         this.emit("visitRemoved", {allHistory: false, urls: [uri.spec]});
-      },
-    };
-    EventEmitter.decorate(_observer);
+      }
+    }();
     PlacesUtils.history.addObserver(_observer);
   }
   return _observer;
 };
 
 this.history = class extends ExtensionAPI {
   getAPI(context) {
     return {
--- a/browser/components/extensions/ext-pageAction.js
+++ b/browser/components/extensions/ext-pageAction.js
@@ -58,18 +58,16 @@ this.pageAction = class extends Extensio
     this.tabContext = new TabContext(tab => Object.create(this.defaults),
                                      extension);
 
     this.tabContext.on("location-change", this.handleLocationChange.bind(this)); // eslint-disable-line mozilla/balanced-listeners
 
     // WeakMap[ChromeWindow -> <xul:image>]
     this.buttons = new WeakMap();
 
-    EventEmitter.decorate(this);
-
     pageActionMap.set(extension, this);
   }
 
   onShutdown(reason) {
     pageActionMap.delete(this.extension);
 
     this.tabContext.shutdown();
 
--- a/browser/components/extensions/ext-utils.js
+++ b/browser/components/extensions/ext-utils.js
@@ -27,74 +27,74 @@ let windowTracker;
 global.makeWidgetId = id => {
   id = id.toLowerCase();
   // FIXME: This allows for collisions.
   return id.replace(/[^a-z0-9_-]/g, "_");
 };
 
 // Manages tab-specific context data, and dispatching tab select events
 // across all windows.
-global.TabContext = function TabContext(getDefaults, extension) {
-  this.extension = extension;
-  this.getDefaults = getDefaults;
+global.TabContext = class extends EventEmitter {
+  constructor(getDefaults, extension) {
+    super();
 
-  this.tabData = new WeakMap();
-  this.lastLocation = new WeakMap();
+    this.extension = extension;
+    this.getDefaults = getDefaults;
 
-  windowTracker.addListener("progress", this);
-  windowTracker.addListener("TabSelect", this);
+    this.tabData = new WeakMap();
+    this.lastLocation = new WeakMap();
 
-  EventEmitter.decorate(this);
-};
+    windowTracker.addListener("progress", this);
+    windowTracker.addListener("TabSelect", this);
+  }
 
-TabContext.prototype = {
   get(nativeTab) {
     if (!this.tabData.has(nativeTab)) {
       this.tabData.set(nativeTab, this.getDefaults(nativeTab));
     }
 
     return this.tabData.get(nativeTab);
-  },
+  }
 
   clear(nativeTab) {
     this.tabData.delete(nativeTab);
-  },
+  }
 
   handleEvent(event) {
     if (event.type == "TabSelect") {
       let nativeTab = event.target;
       this.emit("tab-select", nativeTab);
       this.emit("location-change", nativeTab);
     }
-  },
+  }
 
   onStateChange(browser, webProgress, request, stateFlags, statusCode) {
     let flags = Ci.nsIWebProgressListener;
 
     if (!(~stateFlags & (flags.STATE_IS_WINDOW | flags.STATE_START) ||
           this.lastLocation.has(browser))) {
       this.lastLocation.set(browser, request.URI);
     }
-  },
+  }
 
   onLocationChange(browser, webProgress, request, locationURI, flags) {
     let gBrowser = browser.ownerGlobal.gBrowser;
     let lastLocation = this.lastLocation.get(browser);
     if (browser === gBrowser.selectedBrowser &&
         !(lastLocation && lastLocation.equalsExceptRef(browser.currentURI))) {
       let nativeTab = gBrowser.getTabForBrowser(browser);
       this.emit("location-change", nativeTab, true);
     }
     this.lastLocation.set(browser, browser.currentURI);
-  },
+  }
 
   shutdown() {
     windowTracker.removeListener("progress", this);
     windowTracker.removeListener("TabSelect", this);
-  },
+  }
 };
 
 
 class WindowTracker extends WindowTrackerBase {
   addProgressListener(window, listener) {
     window.gBrowser.addTabsProgressListener(listener);
   }
 
--- a/toolkit/components/extensions/ExtensionAPI.jsm
+++ b/toolkit/components/extensions/ExtensionAPI.jsm
@@ -13,20 +13,24 @@ const {classes: Cc, interfaces: Ci, util
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPI",
                                   "resource://gre/modules/Console.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 
+Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+
 const global = this;
 
-class ExtensionAPI {
+class ExtensionAPI extends ExtensionUtils.EventEmitter {
   constructor(extension) {
+    super();
+
     this.extension = extension;
 
     extension.once("shutdown", () => {
       if (this.onShutdown) {
         this.onShutdown(extension.shutdownReason);
       }
       this.extension = null;
     });
--- a/toolkit/components/extensions/ext-downloads.js
+++ b/toolkit/components/extensions/ext-downloads.js
@@ -8,20 +8,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
                                   "resource://gre/modules/Downloads.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadPaths",
                                   "resource://gre/modules/DownloadPaths.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
 
 var {
+  EventEmitter,
   normalizeTime,
 } = ExtensionUtils;
 
 var {
   ignoreEvent,
 } = ExtensionCommon;
 
 const DOWNLOAD_ITEM_FIELDS = ["id", "url", "referrer", "filename", "incognito",
@@ -137,29 +136,32 @@ class DownloadItem {
     }
   }
 }
 
 
 // DownloadMap maps back and forth betwen the numeric identifiers used in
 // the downloads WebExtension API and a Download object from the Downloads jsm.
 // todo: make id and extension info persistent (bug 1247794)
-const DownloadMap = {
-  currentId: 0,
-  loadPromise: null,
+const DownloadMap = new class extends EventEmitter {
+  constructor() {
+    super();
+
+    this.currentId = 0;
+    this.loadPromise = null;
 
-  // Maps numeric id -> DownloadItem
-  byId: new Map(),
+    // Maps numeric id -> DownloadItem
+    this.byId = new Map();
 
-  // Maps Download object -> DownloadItem
-  byDownload: new WeakMap(),
+    // Maps Download object -> DownloadItem
+    this.byDownload = new WeakMap();
+  }
 
   lazyInit() {
     if (this.loadPromise == null) {
-      EventEmitter.decorate(this);
       this.loadPromise = Downloads.getList(Downloads.ALL).then(list => {
         let self = this;
         return list.addView({
           onDownloadAdded(download) {
             const item = self.newFromDownload(download, null);
             self.emit("create", item);
             item._storePrechange();
           },
@@ -187,54 +189,54 @@ const DownloadMap = {
             downloads.forEach(download => {
               this.newFromDownload(download, null);
             });
           })
           .then(() => list);
       });
     }
     return this.loadPromise;
-  },
+  }
 
   getDownloadList() {
     return this.lazyInit();
-  },
+  }
 
   getAll() {
     return this.lazyInit().then(() => this.byId.values());
-  },
+  }
 
   fromId(id) {
     const download = this.byId.get(id);
     if (!download) {
       throw new Error(`Invalid download id ${id}`);
     }
     return download;
-  },
+  }
 
   newFromDownload(download, extension) {
     if (this.byDownload.has(download)) {
       return this.byDownload.get(download);
     }
 
     const id = ++this.currentId;
     let item = new DownloadItem(id, download, extension);
     this.byId.set(id, item);
     this.byDownload.set(download, item);
     return item;
-  },
+  }
 
   erase(item) {
     // This will need to get more complicated for bug 1255507 but for now we
     // only work with downloads in the DownloadList from getAll()
     return this.getDownloadList().then(list => {
       list.remove(item.download);
     });
-  },
-};
+  }
+}();
 
 // Create a callable function that filters a DownloadItem based on a
 // query object of the type passed to search() or erase().
 const downloadQuery = query => {
   let queryTerms = [];
   let queryNegativeTerms = [];
   if (query.query != null) {
     for (let term of query.query) {
--- a/toolkit/components/extensions/ext-idle.js
+++ b/toolkit/components/extensions/ext-idle.js
@@ -1,15 +1,13 @@
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "idleService",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
 
 // WeakMap[Extension -> Object]
 let observersMap = new WeakMap();
 
 const getIdleObserverInfo = (extension, context) => {
@@ -32,24 +30,23 @@ const getIdleObserverInfo = (extension, 
   }
   return observerInfo;
 };
 
 const getIdleObserver = (extension, context) => {
   let observerInfo = getIdleObserverInfo(extension, context);
   let {observer, detectionInterval} = observerInfo;
   if (!observer) {
-    observer = {
-      observe: function(subject, topic, data) {
+    observer = new class extends ExtensionUtils.EventEmitter {
+      observe(subject, topic, data) {
         if (topic == "idle" || topic == "active") {
           this.emit("stateChanged", topic);
         }
-      },
-    };
-    EventEmitter.decorate(observer);
+      }
+    }();
     idleService.addIdleObserver(observer, detectionInterval);
     observerInfo.observer = observer;
     observerInfo.detectionInterval = detectionInterval;
   }
   return observer;
 };
 
 const setDetectionInterval = (extension, context, newInterval) => {
--- a/toolkit/components/extensions/ext-management.js
+++ b/toolkit/components/extensions/ext-management.js
@@ -9,18 +9,16 @@ XPCOMUtils.defineLazyGetter(this, "strBu
   const stringSvc = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
   return stringSvc.createBundle("chrome://global/locale/extensions.properties");
 });
 XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                   "resource://gre/modules/AddonManager.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "promptService",
                                    "@mozilla.org/embedcomp/prompt-service;1",
                                    "nsIPromptService");
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
-                                  "resource://gre/modules/EventEmitter.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "GlobalManager", () => {
   const {GlobalManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
   return GlobalManager;
 });
 
 var {
   ExtensionError,
@@ -86,20 +84,19 @@ const getExtensionInfoForAddon = (extens
   }
   return extInfo;
 };
 
 const listenerMap = new WeakMap();
 // Some management APIs are intentionally limited.
 const allowedTypes = ["theme", "extension"];
 
-class AddonListener {
+class AddonListener extends ExtensionUtils.EventEmitter {
   constructor() {
     AddonManager.addAddonListener(this);
-    EventEmitter.decorate(this);
   }
 
   release() {
     AddonManager.removeAddonListener(this);
   }
 
   getExtensionInfo(addon) {
     let ext = addon.isWebExtension && GlobalManager.extensionMap.get(addon.id);
--- a/toolkit/components/extensions/ext-notifications.js
+++ b/toolkit/components/extensions/ext-notifications.js
@@ -1,14 +1,16 @@
 "use strict";
 
 // The ext-* files are imported into the same scopes.
 /* import-globals-from ext-toolkit.js */
 
-XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
+const ToolkitModules = {};
+
+XPCOMUtils.defineLazyModuleGetter(ToolkitModules, "EventEmitter",
                                   "resource://gre/modules/EventEmitter.jsm");
 
 var {
   ignoreEvent,
 } = ExtensionCommon;
 
 // WeakMap[Extension -> Map[id -> Notification]]
 let notificationsMap = new WeakMap();
@@ -93,17 +95,17 @@ this.notifications = class extends Exten
       notificationsMap.delete(extension);
     }
   }
 
   getAPI(context) {
     let {extension} = context;
 
     let map = new Map();
-    EventEmitter.decorate(map);
+    ToolkitModules.EventEmitter.decorate(map);
     notificationsMap.set(extension, map);
 
     return {
       notifications: {
         create: (notificationId, options) => {
           if (!notificationId) {
             notificationId = String(this.nextId++);
           }