toolkit/devtools/gcli/commands/calllog.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/devtools/gcli/commands/calllog.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,213 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +const { Cc, Ci, Cu } = require("chrome");
    1.11 +const TargetFactory = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.TargetFactory;
    1.12 +const gcli = require("gcli/index");
    1.13 +
    1.14 +loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
    1.15 +
    1.16 +loader.lazyGetter(this, "Debugger", () => {
    1.17 +  let global = Cu.getGlobalForObject({});
    1.18 +  let JsDebugger = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
    1.19 +  JsDebugger.addDebuggerToGlobal(global);
    1.20 +  return global.Debugger;
    1.21 +});
    1.22 +
    1.23 +let debuggers = [];
    1.24 +let chromeDebuggers = [];
    1.25 +let sandboxes = [];
    1.26 +
    1.27 +exports.items = [
    1.28 +  {
    1.29 +    name: "calllog",
    1.30 +    description: gcli.lookup("calllogDesc")
    1.31 +  },
    1.32 +  {
    1.33 +    name: "calllog start",
    1.34 +    description: gcli.lookup("calllogStartDesc"),
    1.35 +
    1.36 +    exec: function(args, context) {
    1.37 +      let contentWindow = context.environment.window;
    1.38 +
    1.39 +      let dbg = new Debugger(contentWindow);
    1.40 +      dbg.onEnterFrame = function(frame) {
    1.41 +        // BUG 773652 -  Make the output from the GCLI calllog command nicer
    1.42 +        contentWindow.console.log("Method call: " + this.callDescription(frame));
    1.43 +      }.bind(this);
    1.44 +
    1.45 +      debuggers.push(dbg);
    1.46 +
    1.47 +      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
    1.48 +      let target = TargetFactory.forTab(gBrowser.selectedTab);
    1.49 +      gDevTools.showToolbox(target, "webconsole");
    1.50 +
    1.51 +      return gcli.lookup("calllogStartReply");
    1.52 +    },
    1.53 +
    1.54 +    callDescription: function(frame) {
    1.55 +      let name = "<anonymous>";
    1.56 +      if (frame.callee.name) {
    1.57 +        name = frame.callee.name;
    1.58 +      }
    1.59 +      else {
    1.60 +        let desc = frame.callee.getOwnPropertyDescriptor("displayName");
    1.61 +        if (desc && desc.value && typeof desc.value == "string") {
    1.62 +          name = desc.value;
    1.63 +        }
    1.64 +      }
    1.65 +
    1.66 +      let args = frame.arguments.map(this.valueToString).join(", ");
    1.67 +      return name + "(" + args + ")";
    1.68 +    },
    1.69 +
    1.70 +    valueToString: function(value) {
    1.71 +      if (typeof value !== "object" || value === null) {
    1.72 +        return uneval(value);
    1.73 +      }
    1.74 +      return "[object " + value.class + "]";
    1.75 +    }
    1.76 +  },
    1.77 +  {
    1.78 +    name: "calllog stop",
    1.79 +    description: gcli.lookup("calllogStopDesc"),
    1.80 +
    1.81 +    exec: function(args, context) {
    1.82 +      let numDebuggers = debuggers.length;
    1.83 +      if (numDebuggers == 0) {
    1.84 +        return gcli.lookup("calllogStopNoLogging");
    1.85 +      }
    1.86 +
    1.87 +      for (let dbg of debuggers) {
    1.88 +        dbg.onEnterFrame = undefined;
    1.89 +      }
    1.90 +      debuggers = [];
    1.91 +
    1.92 +      return gcli.lookupFormat("calllogStopReply", [ numDebuggers ]);
    1.93 +    }
    1.94 +  },
    1.95 +  {
    1.96 +    name: "calllog chromestart",
    1.97 +    description: gcli.lookup("calllogChromeStartDesc"),
    1.98 +    get hidden() gcli.hiddenByChromePref(),
    1.99 +    params: [
   1.100 +      {
   1.101 +        name: "sourceType",
   1.102 +        type: {
   1.103 +          name: "selection",
   1.104 +          data: ["content-variable", "chrome-variable", "jsm", "javascript"]
   1.105 +        }
   1.106 +      },
   1.107 +      {
   1.108 +        name: "source",
   1.109 +        type: "string",
   1.110 +        description: gcli.lookup("calllogChromeSourceTypeDesc"),
   1.111 +        manual: gcli.lookup("calllogChromeSourceTypeManual"),
   1.112 +      }
   1.113 +    ],
   1.114 +    exec: function(args, context) {
   1.115 +      let globalObj;
   1.116 +      let contentWindow = context.environment.window;
   1.117 +
   1.118 +      if (args.sourceType == "jsm") {
   1.119 +        try {
   1.120 +          globalObj = Cu.import(args.source);
   1.121 +        }
   1.122 +        catch (e) {
   1.123 +          return gcli.lookup("callLogChromeInvalidJSM");
   1.124 +        }
   1.125 +      } else if (args.sourceType == "content-variable") {
   1.126 +        if (args.source in contentWindow) {
   1.127 +          globalObj = Cu.getGlobalForObject(contentWindow[args.source]);
   1.128 +        } else {
   1.129 +          throw new Error(gcli.lookup("callLogChromeVarNotFoundContent"));
   1.130 +        }
   1.131 +      } else if (args.sourceType == "chrome-variable") {
   1.132 +        let chromeWin = context.environment.chromeDocument.defaultView;
   1.133 +        if (args.source in chromeWin) {
   1.134 +          globalObj = Cu.getGlobalForObject(chromeWin[args.source]);
   1.135 +        } else {
   1.136 +          return gcli.lookup("callLogChromeVarNotFoundChrome");
   1.137 +        }
   1.138 +      } else {
   1.139 +        let chromeWin = context.environment.chromeDocument.defaultView;
   1.140 +        let sandbox = new Cu.Sandbox(chromeWin,
   1.141 +                                    {
   1.142 +                                      sandboxPrototype: chromeWin,
   1.143 +                                      wantXrays: false,
   1.144 +                                      sandboxName: "gcli-cmd-calllog-chrome"
   1.145 +                                    });
   1.146 +        let returnVal;
   1.147 +        try {
   1.148 +          returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
   1.149 +          sandboxes.push(sandbox);
   1.150 +        } catch(e) {
   1.151 +          // We need to save the message before cleaning up else e contains a dead
   1.152 +          // object.
   1.153 +          let msg = gcli.lookup("callLogChromeEvalException") + ": " + e;
   1.154 +          Cu.nukeSandbox(sandbox);
   1.155 +          return msg;
   1.156 +        }
   1.157 +
   1.158 +        if (typeof returnVal == "undefined") {
   1.159 +          return gcli.lookup("callLogChromeEvalNeedsObject");
   1.160 +        }
   1.161 +
   1.162 +        globalObj = Cu.getGlobalForObject(returnVal);
   1.163 +      }
   1.164 +
   1.165 +      let dbg = new Debugger(globalObj);
   1.166 +      chromeDebuggers.push(dbg);
   1.167 +
   1.168 +      dbg.onEnterFrame = function(frame) {
   1.169 +        // BUG 773652 -  Make the output from the GCLI calllog command nicer
   1.170 +        contentWindow.console.log(gcli.lookup("callLogChromeMethodCall") +
   1.171 +                                  ": " + this.callDescription(frame));
   1.172 +      }.bind(this);
   1.173 +
   1.174 +      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
   1.175 +      let target = TargetFactory.forTab(gBrowser.selectedTab);
   1.176 +      gDevTools.showToolbox(target, "webconsole");
   1.177 +
   1.178 +      return gcli.lookup("calllogChromeStartReply");
   1.179 +    },
   1.180 +
   1.181 +    valueToString: function(value) {
   1.182 +      if (typeof value !== "object" || value === null)
   1.183 +        return uneval(value);
   1.184 +      return "[object " + value.class + "]";
   1.185 +    },
   1.186 +
   1.187 +    callDescription: function(frame) {
   1.188 +      let name = frame.callee.name || gcli.lookup("callLogChromeAnonFunction");
   1.189 +      let args = frame.arguments.map(this.valueToString).join(", ");
   1.190 +      return name + "(" + args + ")";
   1.191 +    }
   1.192 +  },
   1.193 +  {
   1.194 +    name: "calllog chromestop",
   1.195 +    description: gcli.lookup("calllogChromeStopDesc"),
   1.196 +    get hidden() gcli.hiddenByChromePref(),
   1.197 +    exec: function(args, context) {
   1.198 +      let numDebuggers = chromeDebuggers.length;
   1.199 +      if (numDebuggers == 0) {
   1.200 +        return gcli.lookup("calllogChromeStopNoLogging");
   1.201 +      }
   1.202 +
   1.203 +      for (let dbg of chromeDebuggers) {
   1.204 +        dbg.onEnterFrame = undefined;
   1.205 +        dbg.enabled = false;
   1.206 +      }
   1.207 +      for (let sandbox of sandboxes) {
   1.208 +        Cu.nukeSandbox(sandbox);
   1.209 +      }
   1.210 +      chromeDebuggers = [];
   1.211 +      sandboxes = [];
   1.212 +
   1.213 +      return gcli.lookupFormat("calllogChromeStopReply", [ numDebuggers ]);
   1.214 +    }
   1.215 +  }
   1.216 +];

mercurial