Bug 1473578 - Remove deprecated synchronous DebuggerServer.registerModule feature. r=jryans draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 05 Jul 2018 07:13:52 -0700
changeset 814539 4bf6022518841f2a2a1926330c1f68edb420d5ca
parent 813062 9c02d2ecf22050bfee5d70c04a359d8aaff6eb91
child 814542 871e9983f08546a0ea517378c807ca5881fade27
push id115257
push userbmo:poirot.alex@gmail.com
push dateThu, 05 Jul 2018 16:25:37 +0000
reviewersjryans
bugs1473578
milestone63.0a1
Bug 1473578 - Remove deprecated synchronous DebuggerServer.registerModule feature. r=jryans MozReview-Commit-ID: DTAEJyfICNz
devtools/server/actors/webbrowser.js
devtools/server/main.js
devtools/server/tests/unit/head_dbg.js
devtools/server/tests/unit/test_dbgglobal.js
devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js
devtools/server/tests/unit/test_setBreakpoint-at-the-end-of-a-line.js
devtools/server/tests/unit/test_setBreakpoint-on-column-in-gcd-script.js
devtools/server/tests/unit/test_setBreakpoint-on-column.js
devtools/server/tests/unit/test_setBreakpoint-on-line-in-gcd-script.js
devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-offsets.js
devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-statements.js
devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets-in-gcd-script.js
devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets.js
devtools/server/tests/unit/test_setBreakpoint-on-line.js
devtools/server/tests/unit/testactors.js
devtools/shared/security/tests/unit/head_dbg.js
devtools/shared/security/tests/unit/testactors.js
devtools/shared/transport/tests/unit/head_dbg.js
devtools/shared/transport/tests/unit/test_no_bulk.js
devtools/shared/transport/tests/unit/testactors-no-bulk.js
devtools/shared/transport/tests/unit/testactors.js
mobile/android/chrome/content/RemoteDebugger.js
mobile/android/modules/dbg-browser-actors.js
mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -65,28 +65,28 @@ exports.sendShutdownEvent = sendShutdown
  * - respects the factories registered with DebuggerServer.addGlobalActor,
  * - uses a BrowserTabList to supply target actors for tabs,
  * - sends all navigator:browser window documents a Debugger:Shutdown event
  *   when it exits.
  *
  * * @param connection DebuggerServerConnection
  *          The conection to the client.
  */
-function createRootActor(connection) {
+exports.createRootActor = function createRootActor(connection) {
   return new RootActor(connection, {
     tabList: new BrowserTabList(connection),
     addonList: new BrowserAddonList(connection),
     workerList: new WorkerTargetActorList(connection, {}),
     serviceWorkerRegistrationList:
       new ServiceWorkerRegistrationActorList(connection),
     processList: new ProcessActorList(),
     globalActorFactories: DebuggerServer.globalActorFactories,
     onShutdown: sendShutdownEvent
   });
-}
+};
 
 /**
  * A live list of FrameTargetActorProxys representing the current browser tabs,
  * to be provided to the root actor to answer 'listTabs' requests.
  *
  * This object also takes care of listening for TabClose events and
  * onCloseWindow notifications, and exiting the target actors concerned.
  *
@@ -752,16 +752,8 @@ BrowserAddonList.prototype._adjustListen
   } else if (this._actorByAddonId.size === 0) {
     // When the callback does not exist, we only need to keep listening
     // if the actor cache will need adjusting when add-ons change.
     AddonManager.removeAddonListener(this);
   }
 };
 
 exports.BrowserAddonList = BrowserAddonList;
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -57,71 +57,16 @@ function loadSubScript(url) {
   }
 }
 
 loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
 
 var gRegisteredModules = Object.create(null);
 
 /**
- * The ModuleAPI object is passed to modules loaded using the
- * DebuggerServer.registerModule() API.  Modules can use this
- * object to register actor factories.
- * Factories registered through the module API will be removed
- * when the module is unregistered or when the server is
- * destroyed.
- */
-function ModuleAPI() {
-  let activeTargetScopedActors = new Set();
-  let activeGlobalActors = new Set();
-
-  return {
-    // See DebuggerServer.setRootActor for a description.
-    setRootActor(factory) {
-      DebuggerServer.setRootActor(factory);
-    },
-
-    // See DebuggerServer.addGlobalActor for a description.
-    addGlobalActor(factory, name) {
-      DebuggerServer.addGlobalActor(factory, name);
-      activeGlobalActors.add(factory);
-    },
-    // See DebuggerServer.removeGlobalActor for a description.
-    removeGlobalActor(factory) {
-      DebuggerServer.removeGlobalActor(factory);
-      activeGlobalActors.delete(factory);
-    },
-
-    // See DebuggerServer.addTargetScopedActor for a description.
-    addTargetScopedActor(factory, name) {
-      DebuggerServer.addTargetScopedActor(factory, name);
-      activeTargetScopedActors.add(factory);
-    },
-    // See DebuggerServer.removeTargetScopedActor for a description.
-    removeTargetScopedActor(factory) {
-      DebuggerServer.removeTargetScopedActor(factory);
-      activeTargetScopedActors.delete(factory);
-    },
-
-    // Destroy the module API object, unregistering any
-    // factories registered by the module.
-    destroy() {
-      for (const factory of activeTargetScopedActors) {
-        DebuggerServer.removeTargetScopedActor(factory);
-      }
-      activeTargetScopedActors = null;
-      for (const factory of activeGlobalActors) {
-        DebuggerServer.removeGlobalActor(factory);
-      }
-      activeGlobalActors = null;
-    }
-  };
-}
-
-/**
  * Public API
  */
 var DebuggerServer = {
   _listeners: [],
   _initialized: false,
   // Flag to check if the content process server startup script was already loaded.
   _contentProcessServerStartupScriptLoaded: false,
   // Map of global actor names to actor constructors.
@@ -146,17 +91,17 @@ var DebuggerServer = {
   allowChromeProcess: false,
 
   /**
    * We run a special server in child process whose main actor is an instance
    * of FrameTargetActor, but that isn't a root actor. Instead there is no root
    * actor registered on DebuggerServer.
    */
   get rootlessServer() {
-    return !this.isModuleRegistered("devtools/server/actors/webbrowser");
+    return !this.createRootActor;
   },
 
   /**
    * Initialize the debugger server.
    */
   init() {
     if (this.initialized) {
       return;
@@ -234,17 +179,18 @@ var DebuggerServer = {
    *        for debugging a target context.
    */
   registerActors({ root, browser, target }) {
     if (browser) {
       this._addBrowserActors();
     }
 
     if (root) {
-      this.registerModule("devtools/server/actors/webbrowser");
+      const { createRootActor } = require("devtools/server/actors/webbrowser");
+      this.setRootActor(createRootActor);
     }
 
     if (target) {
       this._addTargetScopedActors();
     }
   },
 
   /**
@@ -264,26 +210,21 @@ var DebuggerServer = {
    */
   addActors(url) {
     loadSubScript.call(this, url);
   },
 
   /**
    * Register a CommonJS module with the debugger server.
    * @param id string
-   *        The ID of a CommonJS module.  This module must export 'register'
-   *        and 'unregister' functions if no `options` argument is given.
-   *        If `options` is set, the actor is going to be registered
-   *        immediately, but loaded only when a client starts sending packets
-   *        to an actor with the same id.
+   *        The ID of a CommonJS module.
+   *        The actor is going to be registered immediately, but loaded only
+   *        when a client starts sending packets to an actor with the same id.
    *
-   * @param options object (optional)
-   *        This parameter is still optional, but not providing it is
-   *        deprecated and will result in eagerly loading the actor module
-   *        with the memory overhead that entails.
+   * @param options object
    *        An object with 3 mandatory attributes:
    *        - prefix (string):
    *          The prefix of an actor is used to compute:
    *          - the `actorID` of each new actor instance (ex: prefix1).
    *            (See ActorPool.addActor)
    *          - the actor name in the listTabs request. Sending a listTabs
    *            request to the root actor returns actor IDs. IDs are in
    *            dictionaries, with actor names as keys and actor IDs as values.
@@ -301,56 +242,47 @@ var DebuggerServer = {
    *            registers a target-scoped actor instance, if true.
    *            A new actor will be created for each target, such as a tab.
    */
   registerModule(id, options) {
     if (id in gRegisteredModules) {
       return;
     }
 
-    if (options) {
-      // Lazy loaded actors
-      const {prefix, constructor, type} = options;
-      if (typeof (prefix) !== "string") {
-        throw new Error(`Lazy actor definition for '${id}' requires a string ` +
-                        `'prefix' option.`);
-      }
-      if (typeof (constructor) !== "string") {
-        throw new Error(`Lazy actor definition for '${id}' requires a string ` +
-                        `'constructor' option.`);
-      }
-      if (!("global" in type) && !("target" in type)) {
-        throw new Error(`Lazy actor definition for '${id}' requires a dictionary ` +
-                        `'type' option whose attributes can be 'global' or 'target'.`);
-      }
-      const name = prefix + "Actor";
-      const mod = {
-        id: id,
-        prefix: prefix,
-        constructorName: constructor,
-        type: type,
-        globalActor: type.global,
-        targetScopedActor: type.target
-      };
-      gRegisteredModules[id] = mod;
-      if (mod.targetScopedActor) {
-        this.addTargetScopedActor(mod, name);
-      }
-      if (mod.globalActor) {
-        this.addGlobalActor(mod, name);
-      }
-    } else {
-      // Deprecated actors being loaded at startup
-      const moduleAPI = ModuleAPI();
-      const mod = require(id);
-      mod.register(moduleAPI);
-      gRegisteredModules[id] = {
-        module: mod,
-        api: moduleAPI
-      };
+    if (!options) {
+      throw new Error("DebuggerServer.registerModule requires an options argument");
+    }
+    const {prefix, constructor, type} = options;
+    if (typeof (prefix) !== "string") {
+      throw new Error(`Lazy actor definition for '${id}' requires a string ` +
+                      `'prefix' option.`);
+    }
+    if (typeof (constructor) !== "string") {
+      throw new Error(`Lazy actor definition for '${id}' requires a string ` +
+                      `'constructor' option.`);
+    }
+    if (!("global" in type) && !("target" in type)) {
+      throw new Error(`Lazy actor definition for '${id}' requires a dictionary ` +
+                      `'type' option whose attributes can be 'global' or 'target'.`);
+    }
+    const name = prefix + "Actor";
+    const mod = {
+      id,
+      prefix,
+      constructorName: constructor,
+      type,
+      globalActor: type.global,
+      targetScopedActor: type.target
+    };
+    gRegisteredModules[id] = mod;
+    if (mod.targetScopedActor) {
+      this.addTargetScopedActor(mod, name);
+    }
+    if (mod.globalActor) {
+      this.addGlobalActor(mod, name);
     }
   },
 
   /**
    * Returns true if a module id has been registered.
    */
   isModuleRegistered(id) {
     return (id in gRegisteredModules);
@@ -368,22 +300,16 @@ var DebuggerServer = {
     // Lazy actors
     if (mod.targetScopedActor) {
       this.removeTargetScopedActor(mod);
     }
     if (mod.globalActor) {
       this.removeGlobalActor(mod);
     }
 
-    if (mod.module) {
-      // Deprecated non-lazy module API
-      mod.module.unregister(mod.api);
-      mod.api.destroy();
-    }
-
     delete gRegisteredModules[id];
   },
 
   /**
    * Install Firefox-specific actors.
    *
    * /!\ Be careful when adding a new actor, especially global actors.
    * Any new global actor will be exposed and returned by the root actor.
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -393,17 +393,24 @@ function attachTestTabAndResume(client, 
     });
   });
 }
 
 /**
  * Initialize the testing debugger server.
  */
 function initTestDebuggerServer(server = DebuggerServer) {
-  server.registerModule("xpcshell-test/testactors");
+  if (server === WorkerDebuggerServer) {
+    const { createRootActor } = worker.require("xpcshell-test/testactors");
+    server.setRootActor(createRootActor);
+  } else {
+    const { createRootActor } = require("xpcshell-test/testactors");
+    server.setRootActor(createRootActor);
+  }
+
   // Allow incoming connections.
   server.init(function() {
     return true;
   });
 }
 
 /**
  * Initialize the testing debugger server with a tab whose title is |title|.
--- a/devtools/server/tests/unit/test_dbgglobal.js
+++ b/devtools/server/tests/unit/test_dbgglobal.js
@@ -23,17 +23,18 @@ function run_test() {
   // implementation yet.
   Assert.throws(DebuggerServer.closeAllListeners,
     /this is undefined/,
     "closeAllListeners should throw if createRootActor hasn't been added");
   Assert.throws(DebuggerServer.connectPipe,
     /this is undefined/,
     "closeAllListeners should throw if createRootActor hasn't been added");
 
-  DebuggerServer.registerModule("xpcshell-test/testactors");
+  const { createRootActor } = require("xpcshell-test/testactors");
+  DebuggerServer.setRootActor(createRootActor);
 
   // Now they should work.
   DebuggerServer.createListener();
   DebuggerServer.closeAllListeners();
 
   // Make sure we got the test's root actor all set up.
   const client1 = DebuggerServer.connectPipe();
   client1.hooks = {
--- a/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-at-the-beginning-of-a-line.js
@@ -1,15 +1,16 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-column.js");
 
 async function run_test() {
   do_test_pending();
-  DebuggerServer.registerModule("xpcshell-test/testactors");
+  const { createRootActor } = require("xpcshell-test/testactors");
+  DebuggerServer.setRootActor(createRootActor);
   DebuggerServer.init(() => true);
   const global = createTestGlobal("test");
   DebuggerServer.addTestGlobal(global);
 
   const client = new DebuggerClient(DebuggerServer.connectPipe());
   await connect(client);
 
   const { tabs } = await listTabs(client);
--- a/devtools/server/tests/unit/test_setBreakpoint-at-the-end-of-a-line.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-at-the-end-of-a-line.js
@@ -1,16 +1,17 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-column.js");
 
 async function run_test() {
   do_test_pending();
 
-  DebuggerServer.registerModule("xpcshell-test/testactors");
+  const { createRootActor } = require("xpcshell-test/testactors");
+  DebuggerServer.setRootActor(createRootActor);
   DebuggerServer.init(() => true);
 
   const global = createTestGlobal("test");
   DebuggerServer.addTestGlobal(global);
 
   const client = new DebuggerClient(DebuggerServer.connectPipe());
   await connect(client);
 
--- a/devtools/server/tests/unit/test_setBreakpoint-on-column-in-gcd-script.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-column-in-gcd-script.js
@@ -5,17 +5,18 @@ var SOURCE_URL = getFileUrl("setBreakpoi
 function run_test() {
   return (async function() {
     do_test_pending();
 
     const global = testGlobal("test");
     loadSubScriptWithOptions(SOURCE_URL, {target: global, ignoreCache: true});
     Cu.forceGC(); Cu.forceGC(); Cu.forceGC();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
     DebuggerServer.addTestGlobal(global);
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
     const { tabs } = await listTabs(client);
     const tab = findTab(tabs, "test");
     const [, tabClient] = await attachTab(client, tab);
--- a/devtools/server/tests/unit/test_setBreakpoint-on-column.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-column.js
@@ -1,17 +1,18 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-column.js");
 
 function run_test() {
   return (async function() {
     do_test_pending();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
 
     const global = createTestGlobal("test");
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line-in-gcd-script.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-in-gcd-script.js
@@ -5,17 +5,18 @@ var SOURCE_URL = getFileUrl("setBreakpoi
 function run_test() {
   return (async function() {
     do_test_pending();
 
     const global = createTestGlobal("test");
     loadSubScriptWithOptions(SOURCE_URL, {target: global, ignoreCache: true});
     Cu.forceGC(); Cu.forceGC(); Cu.forceGC();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
     DebuggerServer.addTestGlobal(global);
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
     const { tabs } = await listTabs(client);
     const tab = findTab(tabs, "test");
     const [, tabClient] = await attachTab(client, tab);
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-offsets.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-offsets.js
@@ -1,17 +1,18 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-line-with-multiple-offsets.js");
 
 function run_test() {
   return (async function() {
     do_test_pending();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
 
     const global = createTestGlobal("test");
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-statements.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-with-multiple-statements.js
@@ -1,17 +1,18 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-line-with-multiple-statements.js");
 
 function run_test() {
   return (async function() {
     do_test_pending();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
 
     const global = createTestGlobal("test");
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets-in-gcd-script.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets-in-gcd-script.js
@@ -5,17 +5,18 @@ var SOURCE_URL = getFileUrl("setBreakpoi
 function run_test() {
   return (async function() {
     do_test_pending();
 
     const global = createTestGlobal("test");
     loadSubScriptWithOptions(SOURCE_URL, {target: global, ignoreCache: true});
     Cu.forceGC(); Cu.forceGC(); Cu.forceGC();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
     const { tabs } = await listTabs(client);
     const tab = findTab(tabs, "test");
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line-with-no-offsets.js
@@ -1,17 +1,18 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-line-with-no-offsets.js");
 
 function run_test() {
   return (async function() {
     do_test_pending();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
 
     const global = createTestGlobal("test");
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
--- a/devtools/server/tests/unit/test_setBreakpoint-on-line.js
+++ b/devtools/server/tests/unit/test_setBreakpoint-on-line.js
@@ -1,17 +1,18 @@
 "use strict";
 
 var SOURCE_URL = getFileUrl("setBreakpoint-on-line.js");
 
 function run_test() {
   return (async function() {
     do_test_pending();
 
-    DebuggerServer.registerModule("xpcshell-test/testactors");
+    const { createRootActor } = require("xpcshell-test/testactors");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.init(() => true);
 
     const global = createTestGlobal("test");
     DebuggerServer.addTestGlobal(global);
 
     const client = new DebuggerClient(DebuggerServer.connectPipe());
     await connect(client);
 
--- a/devtools/server/tests/unit/testactors.js
+++ b/devtools/server/tests/unit/testactors.js
@@ -57,25 +57,25 @@ function TestTabList(connection) {
 
 TestTabList.prototype = {
   constructor: TestTabList,
   getList: function() {
     return Promise.resolve([...this._targetActors]);
   }
 };
 
-function createRootActor(connection) {
+exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     tabList: new TestTabList(connection),
     globalActorFactories: DebuggerServer.globalActorFactories,
   });
 
   root.applicationType = "xpcshell-tests";
   return root;
-}
+};
 
 function TestTargetActor(connection, global) {
   this.conn = connection;
   this._global = global;
   this._global.wrappedJSObject = global;
   this.threadActor = new ThreadActor(this, this._global);
   this.conn.addActor(this.threadActor);
   this._attached = false;
@@ -160,16 +160,8 @@ TestTargetActor.prototype = {
   _appendExtraActors: appendExtraActors
 };
 
 TestTargetActor.prototype.requestTypes = {
   "attach": TestTargetActor.prototype.onAttach,
   "detach": TestTargetActor.prototype.onDetach,
   "reload": TestTargetActor.prototype.onReload
 };
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/devtools/shared/security/tests/unit/head_dbg.js
+++ b/devtools/shared/security/tests/unit/head_dbg.js
@@ -77,11 +77,12 @@ var listener = {
 };
 
 Services.console.registerListener(listener);
 
 /**
  * Initialize the testing debugger server.
  */
 function initTestDebuggerServer() {
-  DebuggerServer.registerModule("xpcshell-test/testactors");
+  const { createRootActor } = require("xpcshell-test/testactors");
+  DebuggerServer.setRootActor(createRootActor);
   DebuggerServer.init();
 }
--- a/devtools/shared/security/tests/unit/testactors.js
+++ b/devtools/shared/security/tests/unit/testactors.js
@@ -47,24 +47,24 @@ function TestTabList(connection) {
 
 TestTabList.prototype = {
   constructor: TestTabList,
   getList: function() {
     return promise.resolve([...this._targetActors]);
   }
 };
 
-function createRootActor(connection) {
+exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     tabList: new TestTabList(connection),
     globalActorFactories: DebuggerServer.globalActorFactories
   });
   root.applicationType = "xpcshell-tests";
   return root;
-}
+};
 
 function TestTargetActor(connection, global) {
   this.conn = connection;
   this._global = global;
   this._threadActor = new ThreadActor(this, this._global);
   this.conn.addActor(this._threadActor);
   this._attached = false;
   this._extraActors = {};
@@ -118,16 +118,8 @@ TestTargetActor.prototype = {
   _createExtraActors: createExtraActors,
   _appendExtraActors: appendExtraActors
 };
 
 TestTargetActor.prototype.requestTypes = {
   "attach": TestTargetActor.prototype.onAttach,
   "detach": TestTargetActor.prototype.onDetach
 };
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/devtools/shared/transport/tests/unit/head_dbg.js
+++ b/devtools/shared/transport/tests/unit/head_dbg.js
@@ -91,17 +91,18 @@ Services.console.registerListener(listen
  * Initialize the testing debugger server.
  */
 function initTestDebuggerServer() {
   DebuggerServer.registerModule("devtools/server/actors/thread", {
     prefix: "script",
     constructor: "ScriptActor",
     type: { global: true, target: true }
   });
-  DebuggerServer.registerModule("xpcshell-test/testactors");
+  const { createRootActor } = require("xpcshell-test/testactors");
+  DebuggerServer.setRootActor(createRootActor);
   // Allow incoming connections.
   DebuggerServer.init();
 }
 
 /**
  * Wrapper around do_get_file to prefix files with the name of current test to
  * avoid collisions when running in parallel.
  */
--- a/devtools/shared/transport/tests/unit/test_no_bulk.js
+++ b/devtools/shared/transport/tests/unit/test_no_bulk.js
@@ -1,15 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 function run_test() {
-  DebuggerServer.registerModule("xpcshell-test/testactors-no-bulk");
+  const { createRootActor } = require("xpcshell-test/testactors-no-bulk");
+  DebuggerServer.setRootActor(createRootActor);
   // Allow incoming connections.
   DebuggerServer.init();
 
   add_task(async function() {
     await test_bulk_send_error(socket_transport);
     await test_bulk_send_error(local_transport);
     DebuggerServer.destroy();
   });
--- a/devtools/shared/transport/tests/unit/testactors-no-bulk.js
+++ b/devtools/shared/transport/tests/unit/testactors-no-bulk.js
@@ -3,26 +3,18 @@
 "use strict";
 
 const { RootActor } = require("devtools/server/actors/root");
 const { DebuggerServer } = require("devtools/server/main");
 
 /**
  * Root actor that doesn't have the bulk trait.
  */
-function createRootActor(connection) {
+exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     globalActorFactories: DebuggerServer.globalActorFactories
   });
   root.applicationType = "xpcshell-tests";
   root.traits = {
     bulk: false
   };
   return root;
-}
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
 };
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/devtools/shared/transport/tests/unit/testactors.js
+++ b/devtools/shared/transport/tests/unit/testactors.js
@@ -46,24 +46,24 @@ function TestTabList(connection) {
 
 TestTabList.prototype = {
   constructor: TestTabList,
   getList: function() {
     return promise.resolve([...this._targetActors]);
   }
 };
 
-function createRootActor(connection) {
+exports.createRootActor = function createRootActor(connection) {
   const root = new RootActor(connection, {
     tabList: new TestTabList(connection),
     globalActorFactories: DebuggerServer.globalActorFactories
   });
   root.applicationType = "xpcshell-tests";
   return root;
-}
+};
 
 function TestTargetActor(connection, global) {
   this.conn = connection;
   this._global = global;
   this._threadActor = new ThreadActor(this, this._global);
   this.conn.addActor(this._threadActor);
   this._attached = false;
   this._extraActors = {};
@@ -117,16 +117,8 @@ TestTargetActor.prototype = {
   _createExtraActors: createExtraActors,
   _appendExtraActors: appendExtraActors
 };
 
 TestTargetActor.prototype.requestTypes = {
   "attach": TestTargetActor.prototype.onAttach,
   "detach": TestTargetActor.prototype.onDetach
 };
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/mobile/android/chrome/content/RemoteDebugger.js
+++ b/mobile/android/chrome/content/RemoteDebugger.js
@@ -1,17 +1,21 @@
 // -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
 /* 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 DebuggerServer */
 "use strict";
 
+XPCOMUtils.defineLazyGetter(this, "require", () => {
+  let { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
+  return require;
+});
+
 XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
-  let { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
   let { DebuggerServer } = require("devtools/server/main");
   return DebuggerServer;
 });
 
 var RemoteDebugger = {
   init(aWindow) {
     this._windowType = "navigator:browser";
 
@@ -196,17 +200,18 @@ var RemoteDebugger = {
     return this._receivingOOB;
   },
 
   initServer: function() {
     DebuggerServer.init();
 
     // Add browser and Fennec specific actors
     DebuggerServer.registerAllActors();
-    DebuggerServer.registerModule("resource://gre/modules/dbg-browser-actors.js");
+    const { createRootActor } = require("resource://gre/modules/dbg-browser-actors.js");
+    DebuggerServer.setRootActor(createRootActor);
 
     // Allow debugging of chrome for any process
     DebuggerServer.allowChromeProcess = true;
     DebuggerServer.chromeWindowType = this._windowType;
   }
 };
 
 RemoteDebugger.allowConnection =
--- a/mobile/android/modules/dbg-browser-actors.js
+++ b/mobile/android/modules/dbg-browser-actors.js
@@ -21,25 +21,25 @@ const { BrowserTabList, BrowserAddonList
  * - respects the factories registered with DebuggerServer.addGlobalActor,
  * - uses a MobileTabList to supply tab actors,
  * - sends all navigator:browser window documents a Debugger:Shutdown event
  *   when it exits.
  *
  * * @param aConnection DebuggerServerConnection
  *        The conection to the client.
  */
-function createRootActor(aConnection) {
+exports.createRootActor = function createRootActor(aConnection) {
   let parameters = {
     tabList: new MobileTabList(aConnection),
     addonList: new BrowserAddonList(aConnection),
     globalActorFactories: DebuggerServer.globalActorFactories,
     onShutdown: sendShutdownEvent
   };
   return new RootActor(aConnection, parameters);
-}
+};
 
 /**
  * A live list of BrowserTabActors representing the current browser tabs,
  * to be provided to the root actor to answer 'listTabs' requests.
  *
  * This object also takes care of listening for TabClose events and
  * onCloseWindow notifications, and exiting the BrowserTabActors concerned.
  *
@@ -62,16 +62,8 @@ MobileTabList.prototype.constructor = Mo
 
 MobileTabList.prototype._getSelectedBrowser = function(aWindow) {
   return aWindow.BrowserApp.selectedBrowser;
 };
 
 MobileTabList.prototype._getChildren = function(aWindow) {
   return aWindow.BrowserApp.tabs.map(tab => tab.browser);
 };
-
-exports.register = function(handle) {
-  handle.setRootActor(createRootActor);
-};
-
-exports.unregister = function(handle) {
-  handle.setRootActor(null);
-};
--- a/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
@@ -8,18 +8,22 @@ var EXPORTED_SYMBOLS = ["GeckoViewRemote
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   Services: "resource://gre/modules/Services.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "require", () => {
+  const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
+  return require;
+});
+
 XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
-  const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
   const { DebuggerServer } = require("devtools/server/main");
   return DebuggerServer;
 });
 
 GeckoViewUtils.initLogging("GeckoView.RemoteDebugger", this);
 
 var GeckoViewRemoteDebugger = {
   observe(aSubject, aTopic, aData) {
@@ -43,17 +47,18 @@ var GeckoViewRemoteDebugger = {
   onEnable() {
     if (this._isEnabled) {
       return;
     }
 
     debug `onEnable`;
     DebuggerServer.init();
     DebuggerServer.registerAllActors();
-    DebuggerServer.registerModule("resource://gre/modules/dbg-browser-actors.js");
+    const { createRootActor } = require("resource://gre/modules/dbg-browser-actors.js");
+    DebuggerServer.setRootActor(createRootActor);
     DebuggerServer.allowChromeProcess = true;
     DebuggerServer.chromeWindowType = "navigator:geckoview";
 
     const env = Cc["@mozilla.org/process/environment;1"]
               .getService(Ci.nsIEnvironment);
     const dataDir = env.get("MOZ_ANDROID_DATA_DIR");
 
     if (!dataDir) {