Bug 1261665 - Remove unecessary Loader.jsm main in favor of require(). r=jryans
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 14 Apr 2016 01:40:43 -0700
changeset 331049 cd9c7f0216c4b19d79e607ca7ff04302c6375add
parent 331048 4276c4ae6d52c0cd1d69cee55d6a077b59a7dd88
child 331050 ef461673c13f81ff4bbb162f739227ab75844941
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1261665
milestone48.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 1261665 - Remove unecessary Loader.jsm main in favor of require(). r=jryans
devtools/bootstrap.js
devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
devtools/client/devtools-startup.js
devtools/client/framework/ToolboxProcess.jsm
devtools/client/framework/toolbox-process-window.js
devtools/client/main.js
devtools/client/moz.build
devtools/server/content-server.jsm
devtools/shared/Loader.jsm
devtools/shared/gcli/commands/listen.js
--- a/devtools/bootstrap.js
+++ b/devtools/bootstrap.js
@@ -93,18 +93,24 @@ function reload(event) {
 
     /* Also purge cached modules in child processes, we do it a few lines after
        in the parent process */
     if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
       Services.obs.notifyObservers(null, "devtools-unload", "reload");
     }
   }, false);
 
-  const {devtools} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
-  devtools.reload();
+  // As we can't get a reference to existing Loader.jsm instances, we send them
+  // an observer service notification to unload them.
+  Services.obs.notifyObservers(null, "devtools-unload", "reload");
+
+  // Then spawn a brand new Loader.jsm instance and start the main module
+  Cu.unload("resource://devtools/shared/Loader.jsm");
+  const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
+  devtools.require("devtools/client/framework/devtools-browser");
 
   // Go over all top level windows to reload all devtools related things
   let windowsEnum = Services.wm.getEnumerator(null);
   while (windowsEnum.hasMoreElements()) {
     let window = windowsEnum.getNext();
     let windowtype = window.document.documentElement.getAttribute("windowtype");
     if (windowtype == "navigator:browser" && window.gBrowser) {
       // Enumerate tabs on firefox windows
--- a/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
@@ -12,18 +12,17 @@ const TAB_URL = EXAMPLE_URL + "doc_inlin
 var gClient, gThreadClient;
 var gAttached = promise.defer();
 var gNewGlobal = promise.defer()
 var gNewChromeSource = promise.defer()
 
 var { DevToolsLoader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var loader = new DevToolsLoader();
 loader.invisibleToDebugger = true;
-loader.main("devtools/server/main");
-var DebuggerServer = loader.DebuggerServer;
+var { DebuggerServer } = loader.require("devtools/server/main");
 
 function test() {
   if (!DebuggerServer.initialized) {
     DebuggerServer.init();
     DebuggerServer.addBrowserActors();
   }
   DebuggerServer.allowChromeProcess = true;
 
--- a/devtools/client/devtools-startup.js
+++ b/devtools/client/devtools-startup.js
@@ -65,17 +65,17 @@ DevToolsStartup.prototype = {
     Services.obs.addObserver(onStartup, "browser-delayed-startup-finished",
                              false);
   },
 
   initDevTools: function() {
     let { loader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
     // Ensure loading main devtools module that hooks up into browser UI
     // and initialize all devtools machinery.
-    loader.main("devtools/client/main");
+    loader.require("devtools/client/framework/devtools-browser");
   },
 
   handleConsoleFlag: function(cmdLine) {
     let window = Services.wm.getMostRecentWindow("devtools:webconsole");
     if (!window) {
       this.initDevTools();
 
       let { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
@@ -149,18 +149,18 @@ DevToolsStartup.prototype = {
       // Create a separate loader instance, so that we can be sure to receive
       // a separate instance of the DebuggingServer from the rest of the
       // devtools.  This allows us to safely use the tools against even the
       // actors and DebuggingServer itself, especially since we can mark
       // serverLoader as invisible to the debugger (unlike the usual loader
       // settings).
       let serverLoader = new DevToolsLoader();
       serverLoader.invisibleToDebugger = true;
-      serverLoader.main("devtools/server/main");
-      let debuggerServer = serverLoader.DebuggerServer;
+      let { DebuggerServer: debuggerServer } =
+        serverLoader.require("devtools/server/main");
       debuggerServer.init();
       debuggerServer.addBrowserActors();
       debuggerServer.allowChromeProcess = true;
 
       let listener = debuggerServer.createListener();
       listener.portOrPath = portOrPath;
       listener.open();
       dump("Started debugger server on " + portOrPath + "\n");
--- a/devtools/client/framework/ToolboxProcess.jsm
+++ b/devtools/client/framework/ToolboxProcess.jsm
@@ -122,18 +122,18 @@ BrowserToolboxProcess.prototype = {
 
     // Create a separate loader instance, so that we can be sure to receive a
     // separate instance of the DebuggingServer from the rest of the devtools.
     // This allows us to safely use the tools against even the actors and
     // DebuggingServer itself, especially since we can mark this loader as
     // invisible to the debugger (unlike the usual loader settings).
     this.loader = new DevToolsLoader();
     this.loader.invisibleToDebugger = true;
-    this.loader.main("devtools/server/main");
-    this.debuggerServer = this.loader.DebuggerServer;
+    let { DebuggerServer } = this.loader.require("devtools/server/main");
+    this.debuggerServer = DebuggerServer;
     dumpn("Created a separate loader instance for the DebuggerServer.");
 
     // Forward interesting events.
     this.debuggerServer.on("connectionchange", this.emit.bind(this));
 
     this.debuggerServer.init();
     this.debuggerServer.addBrowserActors();
     this.debuggerServer.allowChromeProcess = true;
--- a/devtools/client/framework/toolbox-process-window.js
+++ b/devtools/client/framework/toolbox-process-window.js
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 var { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
 // Require this module to setup core modules
-loader.main("devtools/client/main");
+loader.require("devtools/client/framework/devtools-browser");
 
 var { gDevTools } = require("devtools/client/framework/devtools");
 var { TargetFactory } = require("devtools/client/framework/target");
 var { Toolbox } = require("devtools/client/framework/toolbox");
 var Services = require("Services");
 var { DebuggerClient } = require("devtools/shared/client/main");
 var { PrefsHelper } = require("devtools/client/shared/prefs");
 var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
deleted file mode 100644
--- a/devtools/client/main.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/**
- * This module could have been devtools-browser.js.
- * But we need this wrapper in order to define precisely what we are exporting
- * out of client module loader (Loader.jsm): only Toolbox and TargetFactory.
- */
-
-// For compatiblity reasons, exposes these symbols on "devtools":
-Object.defineProperty(exports, "Toolbox", {
-  get: () => require("devtools/client/framework/toolbox").Toolbox
-});
-Object.defineProperty(exports, "TargetFactory", {
-  get: () => require("devtools/client/framework/target").TargetFactory
-});
-
-// Load the main browser module
-require("devtools/client/framework/devtools-browser");
--- a/devtools/client/moz.build
+++ b/devtools/client/moz.build
@@ -46,11 +46,10 @@ EXTRA_COMPONENTS += [
     'devtools-startup.js',
     'devtools-startup.manifest',
 ]
 
 JAR_MANIFESTS += ['jar.mn']
 
 DevToolsModules(
     'definitions.js',
-    'main.js',
     'menus.js',
 )
--- a/devtools/server/content-server.jsm
+++ b/devtools/server/content-server.jsm
@@ -14,18 +14,17 @@ const { DevToolsLoader } = Cu.import("re
 this.EXPORTED_SYMBOLS = ["init"];
 
 function init(msg) {
   // Init a custom, invisible DebuggerServer, in order to not pollute
   // the debugger with all devtools modules, nor break the debugger itself with using it
   // in the same process.
   let devtools = new DevToolsLoader();
   devtools.invisibleToDebugger = true;
-  devtools.main("devtools/server/main");
-  let { DebuggerServer, ActorPool } = devtools;
+  let { DebuggerServer, ActorPool } = devtools.require("devtools/server/main");
 
   if (!DebuggerServer.initialized) {
     DebuggerServer.init();
     DebuggerServer.isInChildProcess = true;
   }
 
   // In case of apps being loaded in parent process, DebuggerServer is already
   // initialized, but child specific actors are not registered.
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -1,28 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* globals NetUtil, FileUtils, OS */
 
 "use strict";
 
 /**
  * Manages the addon-sdk loader instance used to load the developer tools.
  */
 
 var { Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
-
 var { Loader } = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
 var promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
 
 this.EXPORTED_SYMBOLS = ["DevToolsLoader", "devtools", "BuiltinProvider",
                          "require", "loader"];
 
 /**
  * Providers are different strategies for loading the devtools.
@@ -130,29 +125,28 @@ BuiltinProvider.prototype = {
     Loader.unload(this.loader, reason);
     delete this.loader;
   },
 };
 
 var gNextLoaderID = 0;
 
 /**
- * The main devtools API.
- * In addition to a few loader-related details, this object will also include all
- * exports from the main module.  The standard instance of this loader is
- * exported as |devtools| below, but if a fresh copy of the loader is needed,
- * then a new one can also be created.
+ * The main devtools API. The standard instance of this loader is exported as
+ * |devtools| below, but if a fresh copy of the loader is needed, then a new
+ * one can also be created.
  */
 this.DevToolsLoader = function DevToolsLoader() {
   this.require = this.require.bind(this);
   this.lazyGetter = XPCOMUtils.defineLazyGetter.bind(XPCOMUtils);
   this.lazyImporter = XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils);
   this.lazyServiceGetter = XPCOMUtils.defineLazyServiceGetter.bind(XPCOMUtils);
   this.lazyRequireGetter = this.lazyRequireGetter.bind(this);
-  this.main = this.main.bind(this);
+
+  Services.obs.addObserver(this, "devtools-unload", false);
 };
 
 DevToolsLoader.prototype = {
   get provider() {
     if (!this._provider) {
       this._loadProvider();
     }
     return this._provider;
@@ -214,56 +208,16 @@ DevToolsLoader.prototype = {
         return value;
       },
       configurable: true,
       enumerable: true
     });
   },
 
   /**
-   * Add a URI to the loader.
-   * @param string id
-   *    The module id that can be used within the loader to refer to this module.
-   * @param string uri
-   *    The URI to load as a module.
-   * @returns The module's exports.
-   */
-  loadURI: function(id, uri) {
-    let module = Loader.Module(id, uri);
-    return Loader.load(this.provider.loader, module).exports;
-  },
-
-  /**
-   * Let the loader know the ID of the main module to load.
-   *
-   * The loader doesn't need a main module, but it's nice to have.  This
-   * will be called by the browser devtools to load the devtools/main module.
-   *
-   * When only using the server, there's no main module, and this method
-   * can be ignored.
-   */
-  main: function(id) {
-    // Ensure the main module isn't loaded twice, because it may have observable
-    // side-effects.
-    if (this._mainid) {
-      return;
-    }
-    this._mainid = id;
-    this._main = Loader.main(this.provider.loader, id);
-
-    // Mirror the main module's exports on this object.
-    Object.getOwnPropertyNames(this._main).forEach(key => {
-      XPCOMUtils.defineLazyGetter(this, key, () => this._main[key]);
-    });
-
-    var events = this.require("sdk/system/events");
-    events.emit("devtools-loaded", {});
-  },
-
-  /**
    * Override the provider used to load the tools.
    */
   setProvider: function(provider) {
     if (provider === this._provider) {
       return;
     }
 
     if (this._provider) {
@@ -281,18 +235,17 @@ DevToolsLoader.prototype = {
       atob: atob,
       btoa: btoa,
       _Iterator: Iterator,
       loader: {
         lazyGetter: this.lazyGetter,
         lazyImporter: this.lazyImporter,
         lazyServiceGetter: this.lazyServiceGetter,
         lazyRequireGetter: this.lazyRequireGetter,
-        id: this.id,
-        main: this.main
+        id: this.id
       },
       // Make sure `define` function exists.  This allows defining some modules
       // in AMD format while retaining CommonJS compatibility through this hook.
       // JSON Viewer needs modules in AMD format, as it currently uses RequireJS
       // from a content document and can't access our usual loaders.  So, any
       // modules shared with the JSON Viewer should include a define wrapper:
       //
       //   // Make this available to both AMD and CJS environments
@@ -318,28 +271,31 @@ DevToolsLoader.prototype = {
   /**
    * Choose a default tools provider based on the preferences.
    */
   _loadProvider: function() {
     this.setProvider(new BuiltinProvider());
   },
 
   /**
-   * Reload the current provider.
+   * Handles "devtools-unload" event
+   *
+   * @param String data
+   *    reason passed to modules when unloaded
    */
-  reload: function() {
-    var events = this.require("sdk/system/events");
-    events.emit("startupcache-invalidate", {});
+  observe: function(subject, topic, data) {
+    if (topic != "devtools-unload") {
+      return;
+    }
+    Services.obs.removeObserver(this, "devtools-unload");
 
-    this._provider.unload("reload");
-    delete this._provider;
-    let mainid = this._mainid;
-    delete this._mainid;
-    this._loadProvider();
-    this.main(mainid);
+    if (this._provider) {
+      this._provider.unload(data);
+      delete this._provider;
+    }
   },
 
   /**
    * Sets whether the compartments loaded by this instance should be invisible
    * to the debugger.  Invisibility is needed for loaders that support debugging
    * of chrome code.  This is true of remote target environments, like Fennec or
    * B2G.  It is not the default case for desktop Firefox because we offer the
    * Browser Toolbox for chrome debugging there, which uses its own, separate
@@ -348,8 +304,16 @@ DevToolsLoader.prototype = {
    */
   invisibleToDebugger: Services.appinfo.name !== "Firefox"
 };
 
 // Export the standard instance of DevToolsLoader used by the tools.
 this.devtools = this.loader = new DevToolsLoader();
 
 this.require = this.devtools.require.bind(this.devtools);
+
+// For compatibility reasons, expose these symbols on "devtools":
+Object.defineProperty(this.devtools, "Toolbox", {
+  get: () => this.require("devtools/client/framework/toolbox").Toolbox
+});
+Object.defineProperty(this.devtools, "TargetFactory", {
+  get: () => this.require("devtools/client/framework/target").TargetFactory
+});
--- a/devtools/shared/gcli/commands/listen.js
+++ b/devtools/shared/gcli/commands/listen.js
@@ -20,18 +20,17 @@ XPCOMUtils.defineLazyGetter(this, "debug
   // Create a separate loader instance, so that we can be sure to receive
   // a separate instance of the DebuggingServer from the rest of the
   // devtools.  This allows us to safely use the tools against even the
   // actors and DebuggingServer itself, especially since we can mark
   // serverLoader as invisible to the debugger (unlike the usual loader
   // settings).
   let serverLoader = new DevToolsLoader();
   serverLoader.invisibleToDebugger = true;
-  serverLoader.main("devtools/server/main");
-  let debuggerServer = serverLoader.DebuggerServer;
+  let { DebuggerServer: debuggerServer } = serverLoader.require("devtools/server/main");
   debuggerServer.init();
   debuggerServer.addBrowserActors();
   debuggerServer.allowChromeProcess = !l10n.hiddenByChromePref();
   return debuggerServer;
 });
 
 exports.items = [
   {