[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