Bug 1003095 - Refactor script.js to be worker friendly;r=past
authorEddy Bruel <ejpbruel@mozilla.com>
Fri, 30 May 2014 16:42:55 +0200
changeset 185932 238b0a021b585d4153aff553cd2033528fc34406
parent 185931 2f439b950c81763b77201fa15f087ba3556a6441
child 185933 cb60fbdfd0e10158e627abf150914f784c4007bc
push id44197
push userryanvm@gmail.com
push dateFri, 30 May 2014 20:24:52 +0000
treeherdermozilla-inbound@c57a20e0c95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs1003095
milestone32.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 1003095 - Refactor script.js to be worker friendly;r=past
toolkit/devtools/Loader.jsm
toolkit/devtools/server/actors/script.js
toolkit/devtools/server/main.js
toolkit/devtools/worker-loader.js
--- a/toolkit/devtools/Loader.jsm
+++ b/toolkit/devtools/Loader.jsm
@@ -47,17 +47,18 @@ let loaderGlobals = {
   console: console,
   promise: promise,
   _Iterator: Iterator,
   ChromeWorker: ChromeWorker,
   loader: {
     lazyGetter: XPCOMUtils.defineLazyGetter.bind(XPCOMUtils),
     lazyImporter: XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils),
     lazyServiceGetter: XPCOMUtils.defineLazyServiceGetter.bind(XPCOMUtils)
-  }
+  },
+  reportError: Cu.reportError,
 };
 
 // Used when the tools should be loaded from the Firefox package itself (the default)
 function BuiltinProvider() {}
 BuiltinProvider.prototype = {
   load: function() {
     this.loader = new loader.Loader({
       id: "fx-devtools",
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -10,19 +10,21 @@ const Debugger = require("Debugger");
 const Services = require("Services");
 const { Cc, Ci, Cu, components } = require("chrome");
 const { ActorPool } = require("devtools/server/actors/common");
 const { DebuggerServer } = require("devtools/server/main");
 const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
 const { dbg_assert, dumpn, update } = DevToolsUtils;
 const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
 const { defer, resolve, reject, all } = require("devtools/toolkit/deprecated-sync-thenables");
-const {CssLogic} = require("devtools/styleinspector/css-logic");
-
-Cu.import("resource://gre/modules/NetUtil.jsm");
+const { CssLogic } = require("devtools/styleinspector/css-logic");
+
+DevToolsUtils.defineLazyGetter(this, "NetUtil", () => {
+  return Cu.import("resource://gre/modules/NetUtil.jsm", {}).NetUtil;
+});
 
 let B2G_ID = "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}";
 
 let TYPED_ARRAY_CLASSES = ["Uint8Array", "Uint8ClampedArray", "Uint16Array",
       "Uint32Array", "Int8Array", "Int16Array", "Int32Array", "Float32Array",
       "Float64Array"];
 
 // Number of items to preview in objects, arrays, maps, sets, lists,
@@ -3067,17 +3069,24 @@ ObjectActor.prototype = {
       "class": this.obj.class,
       "actor": this.actorID,
       "extensible": this.obj.isExtensible(),
       "frozen": this.obj.isFrozen(),
       "sealed": this.obj.isSealed()
     };
 
     if (this.obj.class != "DeadObject") {
-      let raw = Cu.unwaiveXrays(this.obj.unsafeDereference());
+      let raw = this.obj.unsafeDereference();
+
+      // If Cu is not defined, we are running on a worker thread, where xrays
+      // don't exist.
+      if (Cu) {
+        raw = Cu.unwaiveXrays(raw);
+      }
+
       if (!DevToolsUtils.isSafeJSObject(raw)) {
         raw = null;
       }
 
       let previewers = DebuggerServer.ObjectActorPreviewers[this.obj.class] ||
                        DebuggerServer.ObjectActorPreviewers.Object;
       for (let fn of previewers) {
         try {
@@ -3824,48 +3833,48 @@ DebuggerServer.ObjectActorPreviewers.Obj
         };
         return true;
       default:
         return false;
     }
   },
 
   function CSSMediaRule({obj, threadActor}, aGrip, aRawObj) {
-    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMCSSMediaRule)) {
+    if (!aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMCSSMediaRule)) {
       return false;
     }
     aGrip.preview = {
       kind: "ObjectWithText",
       text: threadActor.createValueGrip(aRawObj.conditionText),
     };
     return true;
   },
 
   function CSSStyleRule({obj, threadActor}, aGrip, aRawObj) {
-    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMCSSStyleRule)) {
+    if (!aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMCSSStyleRule)) {
       return false;
     }
     aGrip.preview = {
       kind: "ObjectWithText",
       text: threadActor.createValueGrip(aRawObj.selectorText),
     };
     return true;
   },
 
   function ObjectWithURL({obj, threadActor}, aGrip, aRawObj) {
     if (!aRawObj ||
-        !(aRawObj instanceof Ci.nsIDOMCSSImportRule ||
-          aRawObj instanceof Ci.nsIDOMCSSStyleSheet ||
-          aRawObj instanceof Ci.nsIDOMLocation ||
-          aRawObj instanceof Ci.nsIDOMWindow)) {
+        Ci && !(aRawObj instanceof Ci.nsIDOMCSSImportRule ||
+                aRawObj instanceof Ci.nsIDOMCSSStyleSheet ||
+                aRawObj instanceof Ci.nsIDOMLocation ||
+                aRawObj instanceof Ci.nsIDOMWindow)) {
       return false;
     }
 
     let url;
-    if (aRawObj instanceof Ci.nsIDOMWindow && aRawObj.location) {
+    if (Ci && (aRawObj instanceof Ci.nsIDOMWindow) && aRawObj.location) {
       url = aRawObj.location.href;
     } else if (aRawObj.href) {
       url = aRawObj.href;
     } else {
       return false;
     }
 
     aGrip.preview = {
@@ -3875,24 +3884,24 @@ DebuggerServer.ObjectActorPreviewers.Obj
 
     return true;
   },
 
   function ArrayLike({obj, threadActor}, aGrip, aRawObj) {
     if (!aRawObj ||
         obj.class != "DOMStringList" &&
         obj.class != "DOMTokenList" &&
-        !(aRawObj instanceof Ci.nsIDOMMozNamedAttrMap ||
-          aRawObj instanceof Ci.nsIDOMCSSRuleList ||
-          aRawObj instanceof Ci.nsIDOMCSSValueList ||
-          aRawObj instanceof Ci.nsIDOMFileList ||
-          aRawObj instanceof Ci.nsIDOMFontFaceList ||
-          aRawObj instanceof Ci.nsIDOMMediaList ||
-          aRawObj instanceof Ci.nsIDOMNodeList ||
-          aRawObj instanceof Ci.nsIDOMStyleSheetList)) {
+        Ci && !(aRawObj instanceof Ci.nsIDOMMozNamedAttrMap ||
+                aRawObj instanceof Ci.nsIDOMCSSRuleList ||
+                aRawObj instanceof Ci.nsIDOMCSSValueList ||
+                aRawObj instanceof Ci.nsIDOMFileList ||
+                aRawObj instanceof Ci.nsIDOMFontFaceList ||
+                aRawObj instanceof Ci.nsIDOMMediaList ||
+                aRawObj instanceof Ci.nsIDOMNodeList ||
+                aRawObj instanceof Ci.nsIDOMStyleSheetList)) {
       return false;
     }
 
     if (typeof aRawObj.length != "number") {
       return false;
     }
 
     aGrip.preview = {
@@ -3911,17 +3920,17 @@ DebuggerServer.ObjectActorPreviewers.Obj
       let value = makeDebuggeeValueIfNeeded(obj, aRawObj[i]);
       items.push(threadActor.createValueGrip(value));
     }
 
     return true;
   }, // ArrayLike
 
   function CSSStyleDeclaration({obj, threadActor}, aGrip, aRawObj) {
-    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMCSSStyleDeclaration)) {
+    if (!aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMCSSStyleDeclaration)) {
       return false;
     }
 
     aGrip.preview = {
       kind: "MapLike",
       size: aRawObj.length,
     };
 
@@ -3933,86 +3942,86 @@ DebuggerServer.ObjectActorPreviewers.Obj
       let value = aRawObj.getPropertyValue(prop);
       entries.push([prop, threadActor.createValueGrip(value)]);
     }
 
     return true;
   },
 
   function DOMNode({obj, threadActor}, aGrip, aRawObj) {
-    if (obj.class == "Object" || !aRawObj || !(aRawObj instanceof Ci.nsIDOMNode)) {
+    if (obj.class == "Object" || !aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMNode)) {
       return false;
     }
 
     let preview = aGrip.preview = {
       kind: "DOMNode",
       nodeType: aRawObj.nodeType,
       nodeName: aRawObj.nodeName,
     };
 
-    if (aRawObj instanceof Ci.nsIDOMDocument && aRawObj.location) {
+    if (Ci && (aRawObj instanceof Ci.nsIDOMDocument) && aRawObj.location) {
       preview.location = threadActor.createValueGrip(aRawObj.location.href);
-    } else if (aRawObj instanceof Ci.nsIDOMDocumentFragment) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMDocumentFragment)) {
       preview.childNodesLength = aRawObj.childNodes.length;
 
       if (threadActor._gripDepth < 2) {
         preview.childNodes = [];
         for (let node of aRawObj.childNodes) {
           let actor = threadActor.createValueGrip(obj.makeDebuggeeValue(node));
           preview.childNodes.push(actor);
           if (preview.childNodes.length == OBJECT_PREVIEW_MAX_ITEMS) {
             break;
           }
         }
       }
-    } else if (aRawObj instanceof Ci.nsIDOMElement) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMElement)) {
       // Add preview for DOM element attributes.
       if (aRawObj instanceof Ci.nsIDOMHTMLElement) {
         preview.nodeName = preview.nodeName.toLowerCase();
       }
 
       let i = 0;
       preview.attributes = {};
       preview.attributesLength = aRawObj.attributes.length;
       for (let attr of aRawObj.attributes) {
         preview.attributes[attr.nodeName] = threadActor.createValueGrip(attr.value);
         if (++i == OBJECT_PREVIEW_MAX_ITEMS) {
           break;
         }
       }
-    } else if (aRawObj instanceof Ci.nsIDOMAttr) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMAttr)) {
       preview.value = threadActor.createValueGrip(aRawObj.value);
-    } else if (aRawObj instanceof Ci.nsIDOMText ||
-               aRawObj instanceof Ci.nsIDOMComment) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMText) ||
+               Ci && (aRawObj instanceof Ci.nsIDOMComment)) {
       preview.textContent = threadActor.createValueGrip(aRawObj.textContent);
     }
 
     return true;
   }, // DOMNode
 
   function DOMEvent({obj, threadActor}, aGrip, aRawObj) {
-    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMEvent)) {
+    if (!aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMEvent)) {
       return false;
     }
 
     let preview = aGrip.preview = {
       kind: "DOMEvent",
       type: aRawObj.type,
       properties: Object.create(null),
     };
 
     if (threadActor._gripDepth < 2) {
       let target = obj.makeDebuggeeValue(aRawObj.target);
       preview.target = threadActor.createValueGrip(target);
     }
 
     let props = [];
-    if (aRawObj instanceof Ci.nsIDOMMouseEvent) {
+    if (Ci && (aRawObj instanceof Ci.nsIDOMMouseEvent)) {
       props.push("buttons", "clientX", "clientY", "layerX", "layerY");
-    } else if (aRawObj instanceof Ci.nsIDOMKeyEvent) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMKeyEvent)) {
       let modifiers = [];
       if (aRawObj.altKey) {
         modifiers.push("Alt");
       }
       if (aRawObj.ctrlKey) {
         modifiers.push("Control");
       }
       if (aRawObj.metaKey) {
@@ -4020,20 +4029,20 @@ DebuggerServer.ObjectActorPreviewers.Obj
       }
       if (aRawObj.shiftKey) {
         modifiers.push("Shift");
       }
       preview.eventKind = "key";
       preview.modifiers = modifiers;
 
       props.push("key", "charCode", "keyCode");
-    } else if (aRawObj instanceof Ci.nsIDOMTransitionEvent ||
-               aRawObj instanceof Ci.nsIDOMAnimationEvent) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMTransitionEvent) ||
+               Ci && (aRawObj instanceof Ci.nsIDOMAnimationEvent)) {
       props.push("animationName", "pseudoElement");
-    } else if (aRawObj instanceof Ci.nsIDOMClipboardEvent) {
+    } else if (Ci && (aRawObj instanceof Ci.nsIDOMClipboardEvent)) {
       props.push("clipboardData");
     }
 
     // Add event-specific properties.
     for (let prop of props) {
       let value = aRawObj[prop];
       if (value && (typeof value == "object" || typeof value == "function")) {
         // Skip properties pointing to objects.
@@ -4066,17 +4075,17 @@ DebuggerServer.ObjectActorPreviewers.Obj
         }
       }
     }
 
     return true;
   }, // DOMEvent
 
   function DOMException({obj, threadActor}, aGrip, aRawObj) {
-    if (!aRawObj || !(aRawObj instanceof Ci.nsIDOMDOMException)) {
+    if (!aRawObj || Ci && !(aRawObj instanceof Ci.nsIDOMDOMException)) {
       return false;
     }
 
     aGrip.preview = {
       kind: "DOMException",
       name: threadActor.createValueGrip(aRawObj.name),
       message: threadActor.createValueGrip(aRawObj.message),
       code: threadActor.createValueGrip(aRawObj.code),
@@ -5488,20 +5497,21 @@ function convertToUnicode(aString, aChar
 /**
  * Report the given error in the error console and to stdout.
  *
  * @param Error aError
  *        The error object you wish to report.
  * @param String aPrefix
  *        An optional prefix for the reported error message.
  */
-function reportError(aError, aPrefix="") {
+let oldReportError = reportError;
+reportError = function(aError, aPrefix="") {
   dbg_assert(aError instanceof Error, "Must pass Error objects to reportError");
   let msg = aPrefix + aError.message + ":\n" + aError.stack;
-  Cu.reportError(msg);
+  oldReportError(msg);
   dumpn(msg);
 }
 
 /**
  * Make a debuggee value for the given object, if needed. Primitive values
  * are left the same.
  *
  * Use case: you have a raw JS object (after unsafe dereference) and you want to
--- a/toolkit/devtools/server/main.js
+++ b/toolkit/devtools/server/main.js
@@ -65,17 +65,17 @@ function loadSubScript(aURL)
     let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
       .getService(Ci.mozIJSSubScriptLoader);
     loader.loadSubScript(aURL, this);
   } catch(e) {
     let errorStr = "Error loading: " + aURL + ":\n" +
                    (e.fileName ? "at " + e.fileName + " : " + e.lineNumber + "\n" : "") +
                    e + " - " + e.stack + "\n";
     dump(errorStr);
-    Cu.reportError(errorStr);
+    reportError(errorStr);
     throw e;
   }
 }
 
 let events = require("sdk/event/core");
 let {defer, resolve, reject, all} = require("devtools/toolkit/deprecated-sync-thenables");
 this.defer = defer;
 this.resolve = resolve;
@@ -1021,17 +1021,17 @@ DebuggerServerConnection.prototype = {
         return pool;
       }
     }
     return null;
   },
 
   _unknownError: function DSC__unknownError(aPrefix, aError) {
     let errorString = aPrefix + ": " + DevToolsUtils.safeErrorString(aError);
-    Cu.reportError(errorString);
+    reportError(errorString);
     dumpn(errorString);
     return {
       error: "unknownError",
       message: errorString
     };
   },
 
   _queueResponse: function(from, type, response) {
--- a/toolkit/devtools/worker-loader.js
+++ b/toolkit/devtools/worker-loader.js
@@ -102,17 +102,16 @@ function createModule(id) {
 //
 // TODO: Remove this when the whitelist becomes empty
 let chromeWhitelist = [
   "devtools/toolkit/transport/transport",
   "devtools/toolkit/transport/stream-utils",
   "devtools/toolkit/transport/packets",
   "devtools/toolkit/DevToolsUtils",
   "devtools/toolkit/event-emitter",
-  "devtools/server/actors/script",
   "devtools/styleinspector/css-logic",
 ];
 
 // Create a CommonJS loader with the following options:
 // - createSandbox:
 //     A function that will be used to create sandboxes. It takes the name and
 //     prototype of the sandbox to be created, and should return the newly
 //     created sandbox as result. This option is mandatory.
@@ -194,19 +193,19 @@ function WorkerDebuggerLoader(options) {
       }
 
       // If the module to be required is the built-in chrome module, and the
       // requirer is not in the whitelist, return a vacuous object as if the
       // module was unavailable.
       //
       // TODO: Remove this when the whitelist becomes empty
       if (id === "chrome" && chromeWhitelist.indexOf(requirer.id) < 0) {
-        return { CC: undefined, Cc: undefined, ChromeWorker: undefined,
-                 Cm: undefined, Ci: undefined, Cu: undefined, Cr: undefined,
-                 components: undefined };
+        return { CC: undefined, Cc: undefined,
+                 ChromeWorker: undefined, Cm: undefined, Ci: undefined, Cu: undefined,
+                 Cr: undefined, components: undefined };
       }
 
       // Built-in modules are cached by id rather than URL, so try to find the
       // module to be required by id first.
       let module = modules[id];
       if (module === undefined) {
         // Failed to find the module to be required by id, so convert the id to
         // a URL and try again.
@@ -342,16 +341,17 @@ if (typeof Components === "object") {
                      Cr: Cr, components: Components };
     const xpcInspector = Cc["@mozilla.org/jsinspector;1"].
                          getService(Ci.nsIJSInspector);
 
     this.worker = new WorkerDebuggerLoader({
       createSandbox: createSandbox,
       globals: {
         "promise": Promise,
+        "reportError": Cu.reportError,
       },
       loadInSandbox: loadInSandbox,
       modules: {
         "Debugger": Debugger,
         "Services": Object.create(Services),
         "Timer": Object.create(Timer),
         "chrome": chrome,
         "source-map": SourceMap,