Bug 946813 - Part 0: Backout ef84114446cc (bug 941012) for breaking browser debugger. r=bustage
authorJ. Ryan Stinnett <jryans@gmail.com>
Wed, 18 Dec 2013 12:48:38 -0600
changeset 161356 89c1a04bede15e4c9536eb789de595268e53db4b
parent 161355 29a40a25a938ff599628cec8608e4958e8361966
child 161357 af9e8e63fc8b2e254d2ab3d3b0bdace63db1babb
push id37893
push userkwierso@gmail.com
push dateFri, 20 Dec 2013 03:51:39 +0000
treeherdermozilla-inbound@0db159616654 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs946813, 941012
milestone29.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 946813 - Part 0: Backout ef84114446cc (bug 941012) for breaking browser debugger. r=bustage
toolkit/devtools/Loader.jsm
toolkit/devtools/server/dbg-server.jsm
toolkit/devtools/server/main.js
--- a/toolkit/devtools/Loader.jsm
+++ b/toolkit/devtools/Loader.jsm
@@ -30,17 +30,16 @@ this.EXPORTED_SYMBOLS = ["DevToolsLoader
 /**
  * Providers are different strategies for loading the devtools.
  */
 
 let loaderGlobals = {
   btoa: btoa,
   console: console,
   _Iterator: Iterator,
-  ChromeWorker: ChromeWorker,
   loader: {
     lazyGetter: XPCOMUtils.defineLazyGetter.bind(XPCOMUtils),
     lazyImporter: XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils),
     lazyServiceGetter: XPCOMUtils.defineLazyServiceGetter.bind(XPCOMUtils)
   }
 };
 
 // Used when the tools should be loaded from the Firefox package itself (the default)
--- a/toolkit/devtools/server/dbg-server.jsm
+++ b/toolkit/devtools/server/dbg-server.jsm
@@ -10,16 +10,36 @@
  * shield it from the debuggee. This way, when debugging chrome globals,
  * debugger and debuggee will be in separate compartments.
  */
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
-const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
-
 this.EXPORTED_SYMBOLS = ["DebuggerServer", "ActorPool"];
 
-let server = devtools.require("devtools/server/main");
+var loadSubScript =
+  "function loadSubScript(aURL)\n" +
+  "{\n" +
+  "const Ci = Components.interfaces;\n" +
+  "const Cc = Components.classes;\n" +
+  "  try {\n" +
+  "    let loader = Cc[\"@mozilla.org/moz/jssubscript-loader;1\"]\n" +
+  "      .getService(Ci.mozIJSSubScriptLoader);\n" +
+  "    loader.loadSubScript(aURL, this);\n" +
+  "  } catch(e) {\n" +
+  "    dump(\"Error loading: \" + aURL + \": \" + e + \" - \" + e.stack + \"\\n\");\n" +
+  "    throw e;\n" +
+  "  }\n" +
+  "}";
 
-this.DebuggerServer = server.DebuggerServer;
-this.ActorPool = server.ActorPool;
+// Load the debugging server in a sandbox with its own compartment.
+var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
+                      .createInstance(Ci.nsIPrincipal);
+
+var gGlobal = Cu.Sandbox(systemPrincipal);
+gGlobal.ChromeWorker = ChromeWorker;
+Cu.evalInSandbox(loadSubScript, gGlobal, "1.8");
+gGlobal.loadSubScript("resource://gre/modules/devtools/server/main.js");
+
+this.DebuggerServer = gGlobal.DebuggerServer;
+this.ActorPool = gGlobal.ActorPool;
--- a/toolkit/devtools/server/main.js
+++ b/toolkit/devtools/server/main.js
@@ -5,32 +5,46 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 /**
  * Toolkit glue for the remote debugging protocol, loaded into the
  * debugging global.
  */
 
-// Until all Debugger server code is converted to SDK modules,
-// imports Components.* alias from chrome module.
-var { Ci, Cc, CC, Cu, Cr } = require("chrome");
-// On B2G, `this` != Global scope, so `Ci` won't be binded on `this`
-// (i.e. this.Ci is undefined) Then later, when using loadSubScript,
-// Ci,... won't be defined for sub scripts.
-this.Ci = Ci;
-this.Cc = Cc;
-this.CC = CC;
-this.Cu = Cu;
-this.Cr = Cr;
-// Overload `Components` to prevent SDK loader exception on Components
-// object usage
-Object.defineProperty(this, "Components", {
-  get: function () require("chrome").components
-});
+// |this.require| is used to test if this file was loaded via the devtools
+// loader (as it is in DebuggerProcess.jsm) or via loadSubScript (as it is from
+// dbg-server.jsm).  Note that testing |require| is not safe in either
+// situation, as it causes a ReferenceError.
+var Ci, Cc, CC, Cu, Cr, Components;
+if (this.require) {
+  ({ Ci, Cc, CC, Cu, Cr, components: Components }) = require("chrome");
+} else {
+  ({
+    interfaces: Ci,
+    classes: Cc,
+    Constructor: CC,
+    utils: Cu,
+    results: Cr
+  }) = Components;
+}
+
+// On B2G, if |this.require| is undefined at this point, it remains undefined
+// later on when |DebuggerServer.registerModule| is called.  On desktop (and
+// perhaps other places), if |this.require| starts out undefined, it ends up
+// being set to some native code by the time we get to |registerModule|.  Here
+// we perform a test early on, and then cache the correct require function for
+// later use.
+var localRequire;
+if (this.require) {
+  localRequire = id => require(id);
+} else {
+  let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
+  localRequire = id => devtools.require(id);
+}
 
 const DBG_STRINGS_URI = "chrome://global/locale/devtools/debugger.properties";
 
 const nsFile = CC("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
 Cu.import("resource://gre/modules/reflect.jsm");
 Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -49,40 +63,36 @@ function loadSubScript(aURL)
   } catch(e) {
     let errorStr = "Error loading: " + aURL + ": " + e + " - " + e.stack + "\n";
     dump(errorStr);
     Cu.reportError(errorStr);
     throw e;
   }
 }
 
-let {defer, resolve, reject, promised, all} = require("sdk/core/promise");
-this.defer = defer;
-this.resolve = resolve;
-this.reject = reject;
-this.promised = promised;
-this.all = all;
+let loaderRequire = this.require;
+this.require = null;
+loadSubScript.call(this, "resource://gre/modules/commonjs/sdk/core/promise.js");
+this.require = loaderRequire;
 
 Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
 
 loadSubScript.call(this, "resource://gre/modules/devtools/DevToolsUtils.js");
 
 function dumpn(str) {
   if (wantLogging) {
     dump("DBG-SERVER: " + str + "\n");
   }
 }
-this.dumpn = dumpn;
 
 function dbg_assert(cond, e) {
   if (!cond) {
     return e;
   }
 }
-this.dbg_assert = dbg_assert;
 
 loadSubScript.call(this, "resource://gre/modules/devtools/server/transport.js");
 
 // XPCOM constructors
 const ServerSocket = CC("@mozilla.org/network/server-socket;1",
                         "nsIServerSocket",
                         "initSpecialConnection");
 const UnixDomainServerSocket = CC("@mozilla.org/network/server-socket;1",
@@ -309,17 +319,17 @@ var DebuggerServer = {
    *    'register' and 'unregister' functions.
    */
   registerModule: function(id) {
     if (id in gRegisteredModules) {
       throw new Error("Tried to register a module twice: " + id + "\n");
     }
 
     let moduleAPI = ModuleAPI();
-    let mod = require(id);
+    let mod = localRequire(id);
     mod.register(moduleAPI);
     gRegisteredModules[id] = { module: mod, api: moduleAPI };
   },
 
   /**
    * Returns true if a module id has been registered.
    */
   isModuleRegistered: function(id) {
@@ -673,18 +683,16 @@ var DebuggerServer = {
       }
     }
   }
 };
 
 if (this.exports) {
   exports.DebuggerServer = DebuggerServer;
 }
-// Needed on B2G (See header note)
-this.DebuggerServer = DebuggerServer;
 
 /**
  * Construct an ActorPool.
  *
  * ActorPools are actorID -> actor mapping and storage.  These are
  * used to accumulate and quickly dispose of groups of actors that
  * share a lifetime.
  */
@@ -693,18 +701,16 @@ function ActorPool(aConnection)
   this.conn = aConnection;
   this._cleanups = {};
   this._actors = {};
 }
 
 if (this.exports) {
   exports.ActorPool = ActorPool;
 }
-// Needed on B2G (See header note)
-this.ActorPool = ActorPool;
 
 ActorPool.prototype = {
   /**
    * Add an actor to the actor pool.  If the actor doesn't have an ID,
    * allocate one from the connection.
    *
    * @param aActor object
    *        The actor implementation.  If the object has a