Bug 1263629 - Use promise module invisible to the debugger for the browser toolbox server. r=jryans
authorAlexandre Poirot <poirot.alex@gmail.com>
Thu, 14 Apr 2016 14:32:21 -0700
changeset 331286 6ddb8429d92077d93cb705f5758d75e028fac86c
parent 331077 3e85a84c7d68632e1098cc9374787dc8f54ce24f
child 331287 957a0ef217ba730f3ebd795193775b7a81687c35
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
bugs1263629
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 1263629 - Use promise module invisible to the debugger for the browser toolbox server. r=jryans
devtools/shared/Loader.jsm
devtools/shared/tests/unit/test_invisible_loader.js
--- a/devtools/shared/Loader.jsm
+++ b/devtools/shared/Loader.jsm
@@ -21,17 +21,16 @@ this.EXPORTED_SYMBOLS = ["DevToolsLoader
 
 /**
  * Providers are different strategies for loading the devtools.
  */
 
 var loaderModules = {
   "Services": Object.create(Services),
   "toolkit/loader": Loader,
-  promise,
   PromiseDebugging,
   ChromeUtils,
   ThreadSafeChromeUtils,
   HeapSnapshot,
 };
 XPCOMUtils.defineLazyGetter(loaderModules, "Debugger", () => {
   // addDebuggerToGlobal only allows adding the Debugger object to a global. The
   // this object is not guaranteed to be a global (in particular on B2G, due to
@@ -77,46 +76,68 @@ XPCOMUtils.defineLazyGetter(loaderModule
 
 XPCOMUtils.defineLazyGetter(loaderModules, "URL", () => {
   let sandbox
     = Cu.Sandbox(CC('@mozilla.org/systemprincipal;1', 'nsIPrincipal')(),
                  {wantGlobalProperties: ["URL"]});
   return sandbox.URL;
 });
 
+const loaderPaths = {
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "": "resource://gre/modules/commonjs/",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "devtools": "resource://devtools",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "gcli": "resource://devtools/shared/gcli/source/lib/gcli",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "acorn": "resource://devtools/acorn",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "acorn/util/walk": "resource://devtools/acorn/walk.js",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  "source-map": "resource://devtools/shared/sourcemap/source-map.js",
+  // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
+  // Allow access to xpcshell test items from the loader.
+  "xpcshell-test": "resource://test",
+};
+
 var sharedGlobalBlocklist = ["sdk/indexed-db"];
 
 /**
  * Used when the tools should be loaded from the Firefox package itself.
  * This is the default case.
  */
 function BuiltinProvider() {}
 BuiltinProvider.prototype = {
   load: function() {
+    // Copy generic paths and modules for this loader instance
+    let paths = {};
+    for (let path in loaderPaths) {
+      paths[path] = loaderPaths[path];
+    }
+    let modules = {};
+    for (let name in loaderModules) {
+      XPCOMUtils.defineLazyGetter(modules, name, (function (name) {
+        return loaderModules[name];
+      }).bind(null, name));
+    }
+    // When creating a Loader invisible to the Debugger, we have to ensure
+    // using only modules and not depend on any JSM. As everything that is
+    // not loaded with Loader isn't going to respect `invisibleToDebugger`.
+    // But we have to keep using Promise.jsm for other loader to prevent
+    // breaking unhandled promise rejection in tests.
+    if (this.invisibleToDebugger) {
+      paths["promise"] = "resource://gre/modules/Promise-backend.js";
+    } else {
+      modules["promise"] = promise;
+    }
     this.loader = new Loader.Loader({
       id: "fx-devtools",
-      modules: loaderModules,
-      paths: {
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "": "resource://gre/modules/commonjs/",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "devtools": "resource://devtools",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "gcli": "resource://devtools/shared/gcli/source/lib/gcli",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "acorn": "resource://devtools/acorn",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "acorn/util/walk": "resource://devtools/acorn/walk.js",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        "source-map": "resource://devtools/shared/sourcemap/source-map.js",
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-        // Allow access to xpcshell test items from the loader.
-        "xpcshell-test": "resource://test"
-        // ⚠ DISCUSSION ON DEV-DEVELOPER-TOOLS REQUIRED BEFORE MODIFYING ⚠
-      },
+      modules,
+      paths,
       globals: this.globals,
       invisibleToDebugger: this.invisibleToDebugger,
       sharedGlobal: true,
       sharedGlobalBlocklist,
     });
 
     return promise.resolve(undefined);
   },
--- a/devtools/shared/tests/unit/test_invisible_loader.js
+++ b/devtools/shared/tests/unit/test_invisible_loader.js
@@ -22,25 +22,37 @@ function visible_loader() {
   let sandbox = loader._provider.loader.sharedGlobalSandbox;
 
   try {
     dbg.addDebuggee(sandbox);
     do_check_true(true);
   } catch(e) {
     do_throw("debugger could not add visible value");
   }
+
+  // Check that for common loader used for tabs, promise modules is Promise.jsm
+  // Which is required to support unhandled promises rejection in mochitests
+  const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+  do_check_eq(loader.require("promise"), promise);
 }
 
 function invisible_loader() {
   let loader = new DevToolsLoader();
   loader.invisibleToDebugger = true;
   loader.require("devtools/shared/css-color");
 
   let dbg = new Debugger();
   let sandbox = loader._provider.loader.sharedGlobalSandbox;
 
   try {
     dbg.addDebuggee(sandbox);
     do_throw("debugger added invisible value");
   } catch(e) {
     do_check_true(true);
   }
+
+  // But for browser toolbox loader, promise is loaded as a regular modules out
+  // of Promise-backend.js, that to be invisible to the debugger and not step
+  // into it.
+  const promise = loader.require("promise");
+  const promiseModule = loader._provider.loader.modules["resource://gre/modules/Promise-backend.js"];
+  do_check_eq(promise, promiseModule.exports);
 }