[Pkg-mozext-commits] [firebug] 14/82: Issue 5873: Base of the closure inspector

David Prévot taffit at moszumanska.debian.org
Mon Mar 31 22:45:36 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to tag fbtest-1.11.2
in repository firebug.

commit bfc376d844c1c8fc08ed9cebb90f8e6836c4b8cf
Author: Simon Lindholm <simon.lindholm10 at gmail.com>
Date:   Tue Dec 18 01:01:35 2012 +0100

    Issue 5873: Base of the closure inspector
---
 extension/content/firebug/chrome/reps.js           |  35 ++-
 .../content/firebug/console/closureInspector.js    | 295 +++++++++++++++++++++
 extension/content/firebug/lib/wrapper.js           |   9 +-
 extension/locale/en-US/firebug.properties          |   3 +
 extension/skin/classic/console.css                 |   4 +
 5 files changed, 335 insertions(+), 11 deletions(-)

diff --git a/extension/content/firebug/chrome/reps.js b/extension/content/firebug/chrome/reps.js
index 71e124f..dd9df92 100644
--- a/extension/content/firebug/chrome/reps.js
+++ b/extension/content/firebug/chrome/reps.js
@@ -24,12 +24,13 @@ define([
     "firebug/lib/xml",
     "firebug/dom/toggleBranch",
     "firebug/console/eventMonitor",
+    "firebug/console/closureInspector",
     "firebug/chrome/menu",
     "arch/compilationunit",
 ],
 function(Obj, Arr, Firebug, Domplate, Firefox, Xpcom, Locale, HTMLLib, Events, Wrapper, Options,
     Url, SourceLink, StackFrame, Css, Dom, Win, System, Xpath, Str, Xml, ToggleBranch,
-    EventMonitor, Menu, CompilationUnit) {
+    EventMonitor, ClosureInspector, Menu, CompilationUnit) {
 
 with (Domplate) {
 
@@ -58,10 +59,10 @@ catch (err)
 
 // use pre here to keep line breaks while copying multiline strings 
 var OBJECTBOX = FirebugReps.OBJECTBOX =
-    PRE({"class": "objectBox inline objectBox-$className", role : "presentation"});
+    PRE({"class": "objectBox inline objectBox-$className", role: "presentation"});
 
 var OBJECTBLOCK = FirebugReps.OBJECTBLOCK =
-    DIV({"class": "objectBox objectBox-$className focusRow subLogRow", role : "listitem"});
+    DIV({"class": "objectBox objectBox-$className focusRow subLogRow", role: "listitem"});
 
 var OBJECTLINK = FirebugReps.OBJECTLINK =
     A({
@@ -209,7 +210,7 @@ FirebugReps.Caption = domplate(Firebug.Rep,
 
 FirebugReps.Warning = domplate(Firebug.Rep,
 {
-    tag: DIV({"class": "warning focusRow", role : 'listitem'}, "$object|STR")
+    tag: DIV({"class": "warning focusRow", role: "listitem"}, "$object|STR")
 });
 
 // ********************************************************************************************* //
@@ -2331,7 +2332,7 @@ FirebugReps.StackTrace = domplate(Firebug.Rep,
     frameIterator: function(frames)
     {
         // Skip Firebug internal frames.
-        // xxxHonza: this is anoter place where stack frame is peeling off.
+        // xxxHonza: this is another place where we peel off stack frames.
         var result = [];
         for (var i=0; frames && i<frames.length; i++)
         {
@@ -3320,6 +3321,27 @@ FirebugReps.ErrorCopy = function(message)
 };
 
 // ********************************************************************************************* //
+
+FirebugReps.OptimizedAway = domplate(Firebug.Rep,
+{
+    tag: OBJECTBOX({_repObject: "$object"}, "$object|getTitle"),
+
+    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+    className: "optimizedAway",
+
+    getTitle: function(object)
+    {
+        return Locale.$STR("firebug.reps.optimizedAway");
+    },
+
+    supportsObject: function(object, type)
+    {
+        return ClosureInspector.isOptimizedAway(object);
+    }
+});
+
+// ********************************************************************************************* //
 // Registration
 
 Firebug.registerRep(
@@ -3354,7 +3376,8 @@ Firebug.registerRep(
     FirebugReps.Date,
     FirebugReps.NamedNodeMap,
     FirebugReps.Reference,
-    FirebugReps.EventLog
+    FirebugReps.EventLog,
+    FirebugReps.OptimizedAway
 );
 
 Firebug.setDefaultReps(FirebugReps.Func, FirebugReps.Obj);
diff --git a/extension/content/firebug/console/closureInspector.js b/extension/content/firebug/console/closureInspector.js
new file mode 100644
index 0000000..2de3909
--- /dev/null
+++ b/extension/content/firebug/console/closureInspector.js
@@ -0,0 +1,295 @@
+/* See license.txt for terms of usage */
+/*jshint esnext:true, es5:true, curly:false */
+/*global FBTrace:true, Components:true, Proxy:true, define:true */
+
+// A note on terminology: here a "closure" is generally thought of as a container of "scopes".
+
+define([
+    "firebug/lib/object",
+    "firebug/firebug",
+    "firebug/lib/wrapper"
+],
+function(Obj, Firebug, Wrapper) {
+"use strict";
+
+// ********************************************************************************************* //
+// Constants
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+const OptimizedAway = Object.create(null);
+Object.freeze(OptimizedAway);
+
+// ********************************************************************************************* //
+
+var ClosureInspector =
+{
+    hasInit: false,
+    Debugger: null,
+
+    getInactiveDebuggerForContext: function(context)
+    {
+        if (context.inactiveDebugger)
+            return context.inactiveDebugger;
+
+        if (!this.hasInit)
+        {
+            this.hasInit = true;
+            try
+            {
+                Cu.import("resource://gre/modules/jsdebugger.jsm");
+                window.addDebuggerToGlobal(window);
+                this.Debugger = window.Debugger;
+            }
+            catch (exc)
+            {
+                if (FBTrace.DBG_COMMANDLINE)
+                    FBTrace.sysout("ClosureInspector; Debugger not found", exc);
+            }
+        }
+        if (!this.Debugger)
+            return;
+
+        var dbg = new this.Debugger();
+        dbg.enabled = false;
+        context.inactiveDebugger = dbg;
+        return dbg;
+    },
+
+    getVariableOrOptimizedAway: function(env, name)
+    {
+        try
+        {
+            var ret = env.getVariable(name);
+            if (ret !== undefined)
+                return ret;
+
+            // The variable is either optimized away or actually set to undefined.
+            // Optimized-away ones are apparantly not settable, so try to detect
+            // them by that (it seems rather safe).
+            env.setVariable(name, 0);
+            if (env.getVariable(name) === undefined)
+                return OptimizedAway;
+            env.setVariable(name, undefined);
+            return undefined;
+        }
+        catch (exc)
+        {
+            // E.g. optimized-away "arguments" can throw "Debugger scope is not live".
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; getVariableOrOptimizedAway caught an exception", exc);
+            return OptimizedAway;
+        }
+    },
+
+    isOptimizedAway: function(obj)
+    {
+        return obj === OptimizedAway;
+    },
+
+    isSimple: function(dobj)
+    {
+        return (typeof dobj !== "object" || dobj === OptimizedAway);
+    },
+
+    unwrap: function(global, dglobal, obj)
+    {
+        dglobal.defineProperty("_firebugUnwrappedDebuggerObject", {
+            value: obj,
+            writable: true,
+            configurable: true
+        });
+        return global._firebugUnwrappedDebuggerObject;
+    },
+
+    scopeIsInteresting: function(env)
+    {
+        return !!env.parent;
+    },
+
+    getFunctionFromObject: function(obj)
+    {
+        var first = true;
+        while (obj)
+        {
+            var names = obj.getOwnPropertyNames(), pd;
+
+            // "constructor" is boring, use it last
+            var ind = names.indexOf("constructor");
+            if (ind !== -1)
+            {
+                names.splice(ind, 1);
+                names.push("constructor");
+            }
+
+            for (var i = 0; i < names.length; ++i)
+            {
+                // We assume that the first own property, or the first
+                // enumerable property of the prototype (or "constructor"),
+                // that is a function with some scope (i.e., it is interpreted,
+                // JSScript-backed, and without optimized-away scope) shares
+                // this scope with 'obj'.
+
+                var name = names[i];
+                try
+                {
+                    pd = obj.getOwnPropertyDescriptor(name);
+                }
+                catch (e)
+                {
+                    // getOwnPropertyDescriptor sometimes fails with
+                    // "Illegal operation on WrappedNative prototype object",
+                    // for instance on [window].proto.gopd("localStorage").
+                    continue;
+                }
+                if (!pd || (!first && !pd.enumerable && name !== "constructor"))
+                    continue;
+
+                var toTest = [pd.get, pd.set, pd.value];
+                for (var j = 0; j < toTest.length; ++j)
+                {
+                    var f = toTest[j];
+                    if (f && f.environment && this.scopeIsInteresting(f.environment))
+                        return f;
+                }
+            }
+
+            if (!first)
+                break;
+            first = false;
+            obj = obj.proto;
+        }
+
+        // None found. :(
+        return undefined;
+    },
+
+    getVariableFromClosureRaw: function(env, mem)
+    {
+        try
+        {
+            env = env.find(mem);
+            if (env)
+                return this.getVariableOrOptimizedAway(env, mem);
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; getVariableFromClosureRaw didn't find anything");
+        }
+        catch (exc)
+        {
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; getVariableFromClosureRaw failed", exc);
+        }
+
+        // Nothing found, for whatever reason.
+        return undefined;
+    },
+
+    setScopedVariableRaw: function(env, mem, to)
+    {
+        try
+        {
+            env = env.find(mem);
+            if (env)
+            {
+                env.setVariable(mem, to);
+                return;
+            }
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; setScopedVariableRaw didn't find anything");
+        }
+        catch (exc)
+        {
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; setScopedVariableRaw failed", exc);
+            throw exc;
+        }
+        throw new Error("can't create new closure variables");
+    },
+
+    getClosureVariablesListRaw: function(env)
+    {
+        var ret = [];
+        try
+        {
+            while (env)
+            {
+                if (env.type === "with" && env.getVariable("profileEnd"))
+                {
+                    // Almost certainly the with(_FirebugCommandLine) block,
+                    // which is at the top of the scope chain on objects
+                    // defined through the console. Hide it for a nicer display.
+                    break;
+                }
+                if (!this.scopeIsInteresting(env))
+                    break;
+
+                ret.push.apply(ret, env.names());
+                env = env.parent;
+            }
+        }
+        catch (exc)
+        {
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; getScopedVariablesRaw failed", exc);
+        }
+        return ret;
+    },
+
+    // Within the security context of the (wrapped) window 'win', find a relevant
+    // closure for the content object 'obj' (may be from another frame).
+    // Throws exceptions on error.
+    getEnvironmentForObject: function(win, obj, context)
+    {
+        var dbg = this.getInactiveDebuggerForContext(context);
+        if (!dbg)
+            throw new Error("debugger not available");
+
+        if (!obj || !(typeof obj === "object" || typeof obj === "function"))
+            throw new TypeError("can't get scope of non-object");
+
+        var objGlobal = Cu.getGlobalForObject(obj);
+        if (win !== objGlobal && !(win.document && objGlobal.document &&
+            win.document.nodePrincipal.subsumes(objGlobal.document.nodePrincipal)))
+        {
+            throw new Error("permission denied to access cross origin scope");
+        }
+
+        var dglobal = dbg.addDebuggee(objGlobal);
+
+        var dobj = dglobal.makeDebuggeeValue(obj);
+
+        if (typeof obj === "object")
+            dobj = this.getFunctionFromObject(dobj);
+
+        if (!dobj || !dobj.environment || !this.scopeIsInteresting(dobj.environment))
+            throw new Error("missing closure");
+
+        return dobj.environment;
+    },
+
+    getClosureVariablesList: function(obj, context)
+    {
+        // Avoid 'window' and 'document' getting associated with closures.
+        var win = context.baseWindow || context.window;
+        if (obj === win || obj === win.document)
+            return [];
+
+        try
+        {
+            var env = this.getEnvironmentForObject(win, obj, context);
+            return this.getClosureVariablesListRaw(env);
+        }
+        catch (exc)
+        {
+            if (FBTrace.DBG_COMMANDLINE)
+                FBTrace.sysout("ClosureInspector; getClosureVariablesList failed", exc);
+            return [];
+        }
+    }
+};
+
+return ClosureInspector;
+
+// ********************************************************************************************* //
+});
diff --git a/extension/content/firebug/lib/wrapper.js b/extension/content/firebug/lib/wrapper.js
index 232365a..4728d60 100644
--- a/extension/content/firebug/lib/wrapper.js
+++ b/extension/content/firebug/lib/wrapper.js
@@ -16,10 +16,10 @@ var Wrapper = {};
 
 Wrapper.getContentView = function(object)
 {
-    if (typeof(object) === "undefined" || object == null)
-        return false;
+    if (typeof object !== "object" && typeof object !== "function")
+        return object;
 
-    return (object.wrappedJSObject);
+    return object.wrappedJSObject;
 }
 
 Wrapper.unwrapObject = function(object)
@@ -111,9 +111,8 @@ Wrapper.ignoreVars =
 
     // internal firebug things XXXjjb todo we should privatize these
     "_firebug": 1,
-    "_createFirebugConsole": 1,
+    "_firebugUnwrappedDebuggerObject": 1,
     "_FirebugCommandLine": 1,
-    "loadFirebugConsole": 1,
 };
 
 Wrapper.shouldIgnore = function(name)
diff --git a/extension/locale/en-US/firebug.properties b/extension/locale/en-US/firebug.properties
index 765791f..48c459a 100644
--- a/extension/locale/en-US/firebug.properties
+++ b/extension/locale/en-US/firebug.properties
@@ -222,6 +222,9 @@ html.tip.Break_On_Element_Removal=Stop JavaScript execution when the element is
 # or collapse it.
 html.label.Expand/Contract_All=Expand/Contract All
 html.tip.Expand/Contract_All=Expand/collapse all the children recursively
+# LOCALIZATION NOTE (firebug.reps.optimizedAway): Label shown to denote a closure variable that has
+# been optimized away.
+firebug.reps.optimizedAway=(optimized away)
 # LOCALIZATION NOTE (dom.label.breakOnPropertyChange, dom.tip.Break_On_Property_Change):
 # Used within the DOM panel to create a 'property breakpoint'. Right-click on an property of an object.
 # The label is also used for the 'Break On Property Change' button (available on the toolbar).
diff --git a/extension/skin/classic/console.css b/extension/skin/classic/console.css
index 289cfaf..18ba6b5 100644
--- a/extension/skin/classic/console.css
+++ b/extension/skin/classic/console.css
@@ -166,6 +166,10 @@
     color: #787878;
 }
 
+.objectBox-optimizedAway {
+    color: #909090;
+}
+
 .objectLink-sourceLink {
     position: absolute;
     right: 4px;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/firebug.git



More information about the Pkg-mozext-commits mailing list