[Pkg-mozext-commits] [firebug] 15/82: Issue 5873: Closure inspector command line integration
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 134e6eb24907b8b6974e34a1296ca0dac760c35c
Author: Simon Lindholm <simon.lindholm10 at gmail.com>
Date: Tue Dec 18 01:02:20 2012 +0100
Issue 5873: Closure inspector command line integration
---
extension/content/firebug/console/autoCompleter.js | 158 +++++++++++++++++----
.../content/firebug/console/closureInspector.js | 97 +++++++++++++
extension/content/firebug/console/commandLine.js | 26 ++--
extension/content/firebug/cookies/breakpoints.js | 6 +-
extension/content/firebug/lib/wrapper.js | 4 +-
extension/content/firebug/net/netDebugger.js | 6 +-
6 files changed, 245 insertions(+), 52 deletions(-)
diff --git a/extension/content/firebug/console/autoCompleter.js b/extension/content/firebug/console/autoCompleter.js
index fcb1ce1..a1b88e1 100644
--- a/extension/content/firebug/console/autoCompleter.js
+++ b/extension/content/firebug/console/autoCompleter.js
@@ -10,9 +10,10 @@ define([
"firebug/lib/dom",
"firebug/lib/string",
"firebug/lib/array",
+ "firebug/console/closureInspector",
"firebug/editor/editor"
],
-function(Obj, Firebug, Domplate, Locale, Events, Wrapper, Dom, Str, Arr, Editor) {
+function(Obj, Firebug, Domplate, Locale, Events, Wrapper, Dom, Str, Arr, ClosureInspector, Editor) {
// ********************************************************************************************* //
// Constants
@@ -890,6 +891,54 @@ Firebug.JSAutoCompleter = function(textBox, completionBox, options)
}
};
+/**
+ * Transform expressions that use .% into more JavaScript-friendly function calls.
+ * (This is unrelated to the auto-completer, but autoCompleter.js has so many nice
+ * helper functions.)
+ */
+Firebug.JSAutoCompleter.transformScopeOperator = function(expr, fname)
+{
+ var sexpr = simplifyExpr(expr);
+ if (!sexpr)
+ return expr;
+ var search = 0;
+ for (;;)
+ {
+ // Find the next occurrance of .%.
+ var end = sexpr.indexOf(".%", search);
+ if (end === -1)
+ break;
+
+ var start = getExpressionOffset(sexpr, end);
+ if (/^-?[0-9]*$/.test(expr.substring(start, end)))
+ {
+ // False alarm - the operator was actually a number and the modulo operator.
+ search = end + 1;
+ }
+ else
+ {
+ // Substitute "expr.%prop" with "scopeGetter(expr).prop", or, if used
+ // in a "new" expression, "(scopeGetter(expr)).prop" (so that the scope
+ // getter isn't used as a constructor). We don't want to use the first
+ // thing unconditionally though, because it messes with ASI.
+ var newPos = (start === 0 ? -1 : sexpr.lastIndexOf("new", start-1));
+ var hasNew = (newPos !== -1 && !/[a-zA-Z0-9_$.]/.test(sexpr.charAt(newPos-1)) &&
+ sexpr.substring(newPos + 3, start).trim() === "");
+ var subst = function(expr)
+ {
+ return expr.substr(0, start) + (hasNew ? "(" : "") + fname + "(" +
+ expr.substring(start, end) + ")" + (hasNew ? ")" : "") + "." +
+ expr.substr(end+2);
+ };
+ expr = subst(expr);
+ sexpr = subst(sexpr);
+
+ search = end + fname.length + (hasNew ? 3 : 1); // |(()).| - |.%|, or |().| - |.%|
+ }
+ }
+ return expr;
+};
+
// ********************************************************************************************* //
/**
@@ -966,15 +1015,16 @@ function EditorJSAutoCompleter(box, completionBox, options)
/**
* Try to find the position at which the expression to be completed starts.
*/
-function getExpressionOffset(command)
+function getExpressionOffset(command, start)
{
- var bracketCount = 0;
+ if (typeof start === 'undefined')
+ start = command.length;
- var start = command.length, instr = false;
+ var bracketCount = 0, instr = false;
// When completing []-accessed properties, start instead from the last [.
- var lastBr = command.lastIndexOf("[");
- if (lastBr !== -1 && /^" *$/.test(command.substr(lastBr+1)))
+ var lastBr = command.lastIndexOf("[", start);
+ if (lastBr !== -1 && /^" *$/.test(command.substring(lastBr+1, start)))
start = lastBr;
for (var i = start-1; i >= 0; --i)
@@ -998,7 +1048,10 @@ function getExpressionOffset(command)
else if (bracketCount === 0)
{
if (c === '"') instr = !instr;
- else if (!instr && !reJSChar.test(c) && c !== ".")
+ else if (instr || reJSChar.test(c) || c === "." ||
+ (c === "%" && command[i-1] === "."))
+ ;
+ else
break;
}
}
@@ -1006,7 +1059,8 @@ function getExpressionOffset(command)
// The 'new' operator has higher precedence than function calls, so, if
// present, it should be included if the expression contains a parenthesis.
- if (i-4 >= 0 && command.indexOf("(", i) !== -1 && command.substr(i-4, 4) === "new ")
+ var ind = command.indexOf("(", i+1);
+ if (i-4 >= 0 && ind !== -1 && ind < start && command.substr(i-4, 4) === "new ")
{
i -= 4;
}
@@ -1025,10 +1079,10 @@ function getPropertyOffset(expr)
return lastBr+2;
var lastDot = expr.lastIndexOf(".");
- if (lastDot !== -1)
- return lastDot+1;
+ if (lastDot !== -1 && expr.charAt(lastDot+1) === "%")
+ return lastDot+2;
- return 0;
+ return (lastDot === -1 ? 0 : lastDot+1);
}
/**
@@ -1258,7 +1312,8 @@ function killCompletions(expr, origExpr)
return true;
if (reJSChar.test(expr[expr.length-1]) ||
- expr[expr.length-1] === ".")
+ expr.slice(-1) === "." ||
+ expr.slice(-2) === ".%")
{
// An expression at the end - we're fine.
}
@@ -1516,9 +1571,10 @@ var AutoCompletionKnownTypes = {
var LinkType = {
"PROPERTY": 0,
- "INDEX": 1,
- "CALL": 2,
- "RETVAL_HEURISTIC": 3
+ "SCOPED_VARS": 1,
+ "INDEX": 2,
+ "CALL": 3,
+ "RETVAL_HEURISTIC": 4
};
function getKnownType(t)
@@ -1643,7 +1699,9 @@ function propertiesToHide(expr, obj)
);
// Hide ourselves.
- ret.push("_FirebugCommandLine", "_firebug");
+ ret.push("_FirebugCommandLine", "_firebug",
+ "_firebugUnwrappedDebuggerObject", "__fb_scopedVars"
+ );
}
// Old and ugly.
@@ -1658,7 +1716,6 @@ function propertiesToHide(expr, obj)
return ret;
}
-
function setCompletionsFromObject(out, object, context)
{
// 'object' is a user-level, non-null object.
@@ -1671,7 +1728,7 @@ function setCompletionsFromObject(out, object, context)
// to cross-window properties, nor just '!Object.getPrototypeOf(obj)'
// because of Object.create.
return !Object.getPrototypeOf(obj) && "hasOwnProperty" in obj;
- }
+ };
var obj = object;
while (obj !== null)
@@ -1716,12 +1773,36 @@ function setCompletionsFromObject(out, object, context)
catch (exc)
{
if (FBTrace.DBG_COMMANDLINE)
- FBTrace.sysout("autoCompleter.getCompletionsFromPrototypeChain failed", exc);
+ FBTrace.sysout("autoCompleter.setCompletionsFromObject failed", exc);
+ }
+}
+
+function setCompletionsFromScope(out, object, context)
+{
+ out.completions = ClosureInspector.getClosureVariablesList(object, context);
+
+ // Hide "arguments"; it almost never holds a value.
+ out.completions = Arr.unique(out.completions);
+ var ind = out.completions.indexOf("arguments");
+ if (ind !== -1)
+ {
+ out.completions.splice(ind, 1);
+ out.hiddenCompletions.push("arguments");
}
}
function propChainBuildComplete(out, context, tempExpr, result)
{
+ if (out.scopeCompletion)
+ {
+ if (tempExpr.fake)
+ return;
+ if (typeof result !== "object" && typeof result !== "function")
+ return;
+ setCompletionsFromScope(out, result, context);
+ return;
+ }
+
var done = function(result)
{
if (result !== undefined && result !== null)
@@ -1786,6 +1867,10 @@ function evalPropChainStep(step, tempExpr, evalChain, out, context)
else
return;
}
+ else
+ {
+ return;
+ }
evalPropChainStep(step+1, tempExpr, evalChain, out, context);
}
else
@@ -1800,6 +1885,11 @@ function evalPropChainStep(step, tempExpr, evalChain, out, context)
tempExpr.thisCommand = tempExpr.command;
tempExpr.command += "." + link.name;
}
+ else if (type === LinkType.SCOPED_VARS)
+ {
+ tempExpr.thisCommand = "window";
+ tempExpr.command += ".%" + link.name;
+ }
else if (type === LinkType.INDEX)
{
tempExpr.thisCommand = "window";
@@ -1986,10 +2076,15 @@ function evalPropChain(out, preExpr, origExpr, context)
if (ch === ".")
{
// Property access
- var nextLink = eatProp(preExpr, linkStart+1);
- lastProp = preExpr.substring(linkStart+1, nextLink);
+ var scope = (preExpr.charAt(linkStart+1) === "%");
+ linkStart += (scope ? 2 : 1);
+ var nextLink = eatProp(preExpr, linkStart);
+ lastProp = preExpr.substring(linkStart, nextLink);
linkStart = nextLink;
- evalChain.push({"type": LinkType.PROPERTY, "name": lastProp});
+ evalChain.push({
+ "type": (scope ? LinkType.SCOPED_VARS : LinkType.PROPERTY),
+ "name": lastProp
+ });
}
else if (ch === "(")
{
@@ -2055,24 +2150,25 @@ function autoCompleteEval(context, preExpr, spreExpr, includeCurrentScope)
// In case of array indexing, remove the bracket and set a flag to
// escape completions.
+ out.scopeCompletion = false;
var len = spreExpr.length;
if (len >= 2 && spreExpr[len-2] === "[" && spreExpr[len-1] === '"')
{
indexCompletion = true;
out.indexQuoteType = preExpr[len-1];
- spreExpr = spreExpr.substr(0, len-2);
- preExpr = preExpr.substr(0, len-2);
+ len -= 2;
+ }
+ else if (spreExpr.slice(-2) === ".%")
+ {
+ out.scopeCompletion = true;
+ len -= 2;
}
else
{
- // Remove the trailing dot (if there is one)
- var lastDot = spreExpr.lastIndexOf(".");
- if (lastDot !== -1)
- {
- spreExpr = spreExpr.substr(0, lastDot);
- preExpr = preExpr.substr(0, lastDot);
- }
+ len -= 1;
}
+ spreExpr = spreExpr.substr(0, len);
+ preExpr = preExpr.substr(0, len);
if (FBTrace.DBG_COMMANDLINE)
FBTrace.sysout("commandLine.autoCompleteEval pre:'" + preExpr +
diff --git a/extension/content/firebug/console/closureInspector.js b/extension/content/firebug/console/closureInspector.js
index 2de3909..7e5870c 100644
--- a/extension/content/firebug/console/closureInspector.js
+++ b/extension/content/firebug/console/closureInspector.js
@@ -286,6 +286,103 @@ var ClosureInspector =
FBTrace.sysout("ClosureInspector; getClosureVariablesList failed", exc);
return [];
}
+ },
+
+ getClosureWrapper: function(obj, win, context)
+ {
+ var env = this.getEnvironmentForObject(win, obj, context);
+
+ var dbg = this.getInactiveDebuggerForContext(context);
+ var dglobal = dbg.addDebuggee(win);
+
+ // Return a wrapper for its scoped variables.
+ var self = this;
+ var handler = {};
+ handler.getOwnPropertyDescriptor = function(name)
+ {
+ if (name === "__exposedProps__")
+ {
+ // Expose mostly everything, rw, through another proxy.
+ return {
+ value: Proxy.create({
+ getPropertyDescriptor: function(name)
+ {
+ if (name === "__exposedProps__" || name === "__proto__")
+ return;
+ return {value: "rw", enumerable: true};
+ }
+ })
+ };
+ }
+
+ return {
+ get: function()
+ {
+ try
+ {
+ var dval = self.getVariableFromClosureRaw(env, name);
+ if (self.isSimple(dval))
+ return dval;
+ var uwWin = Wrapper.getContentView(win);
+ return self.unwrap(uwWin, dglobal, dval);
+ }
+ catch (exc)
+ {
+ if (FBTrace.DBG_COMMANDLINE)
+ FBTrace.sysout("ClosureInspector; failed to return value from getter", exc);
+ }
+ },
+
+ set: function(value)
+ {
+ value = dglobal.makeDebuggeeValue(value);
+ self.setScopedVariableRaw(env, name, value);
+ }
+ };
+ };
+ handler.getPropertyDescriptor = handler.getOwnPropertyDescriptor;
+ return Proxy.create(handler);
+ },
+
+ extendLanguageSyntax: function (expr, win, context)
+ {
+ var fname = "__fb_scopedVars";
+
+ var newExpr = Firebug.JSAutoCompleter.transformScopeOperator(expr, fname);
+ if (expr === newExpr)
+ return expr;
+
+ if (FBTrace.DBG_COMMANDLINE)
+ {
+ FBTrace.sysout("ClosureInspector; transforming expression: `" +
+ expr + "` -> `" + newExpr + "`");
+ }
+
+ // Stick the helper function for .%-expressions on the window object.
+ // This really belongs on the command line object, but that doesn't
+ // work when stopped in the debugger (issue 5321, which depends on
+ // integrating JSD2) and we really need this to work there.
+ // To avoid leaking capabilities into arbitrary web pages, this is
+ // only injected when needed.
+ try
+ {
+ var self = this;
+ Object.defineProperty(Wrapper.getContentView(win), fname, {
+ value: function(obj)
+ {
+ return self.getClosureWrapper(obj, win, context);
+ },
+ writable: true,
+ configurable: true
+ });
+ }
+ catch (exc)
+ {
+ if (FBTrace.DBG_COMMANDLINE)
+ FBTrace.sysout("ClosureInspector; failed to inject " + fname, exc);
+ }
+
+ return newExpr;
}
};
diff --git a/extension/content/firebug/console/commandLine.js b/extension/content/firebug/console/commandLine.js
index d0dada8..3cef0a1 100644
--- a/extension/content/firebug/console/commandLine.js
+++ b/extension/content/firebug/console/commandLine.js
@@ -23,12 +23,13 @@ define([
"firebug/console/commandLineHelp",
"firebug/console/commandLineInclude",
"firebug/console/commandLineExposed",
+ "firebug/console/closureInspector",
"firebug/console/autoCompleter",
"firebug/console/commandHistory"
],
function(Obj, Firebug, FirebugReps, Locale, Events, Wrapper, Url, Css, Dom, Firefox, Win, System,
- Xpath, Str, Xml, Arr, Persist, Keywords, Console, CommandLineHelp,
- CommandLineInclude, CommandLineExposed) {
+ Xpath, Str, Xml, Arr, Persist, Keywords, Console, CommandLineHelp, CommandLineInclude,
+ CommandLineExposed, ClosureInspector) {
// ********************************************************************************************* //
// Constants
@@ -71,31 +72,33 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
}
},
- // returns user-level wrapped object I guess.
evaluate: function(expr, context, thisValue, targetWindow, successConsoleFunction,
exceptionFunction, noStateChange)
{
if (!context)
return;
+ targetWindow = targetWindow || context.baseWindow || context.window;
+
try
{
- var result = null;
var debuggerState = Firebug.Debugger.beginInternalOperation();
+ expr = ClosureInspector.extendLanguageSyntax(expr, targetWindow, context);
+
if (this.isSandbox(context))
{
- result = this.evaluateInSandbox(expr, context, thisValue, targetWindow,
+ this.evaluateInSandbox(expr, context, thisValue, targetWindow,
successConsoleFunction, exceptionFunction);
}
else if (Firebug.Debugger.hasValidStack(context))
{
- result = this.evaluateInDebugFrame(expr, context, thisValue, targetWindow,
+ this.evaluateInDebugFrame(expr, context, thisValue, targetWindow,
successConsoleFunction, exceptionFunction);
}
else
{
- result = this.evaluateByEventPassing(expr, context, thisValue, targetWindow,
+ this.evaluateByEventPassing(expr, context, thisValue, targetWindow,
successConsoleFunction, exceptionFunction);
}
@@ -115,15 +118,12 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
{
Firebug.Debugger.endInternalOperation(debuggerState);
}
-
- return result;
},
evaluateByEventPassing: function(expr, context, thisValue, targetWindow,
successConsoleFunction, exceptionFunction)
{
- var win = targetWindow ? targetWindow :
- (context.baseWindow ? context.baseWindow : context.window);
+ var win = targetWindow || context.baseWindow || context.window;
if (!win)
{
@@ -256,9 +256,7 @@ Firebug.CommandLine = Obj.extend(Firebug.Module,
{
var result = null;
- // targetWindow may be frame in HTML
- var win = targetWindow ? targetWindow :
- (context.baseWindow ? context.baseWindow : context.window);
+ var win = targetWindow || context.baseWindow || context.window;
if (!context.commandLineAPI)
context.commandLineAPI = new FirebugCommandLineAPI(context);
diff --git a/extension/content/firebug/cookies/breakpoints.js b/extension/content/firebug/cookies/breakpoints.js
index 31ee9d6..9396cac 100644
--- a/extension/content/firebug/cookies/breakpoints.js
+++ b/extension/content/firebug/cookies/breakpoints.js
@@ -349,11 +349,13 @@ Breakpoints.Breakpoint.prototype =
"; with (scope) { return " + this.condition + ";}})();"
// Evaluate condition using Firebug's command line.
- var rc = Firebug.CommandLine.evaluate(expr, context, null, context.window,
+ Firebug.CommandLine.evaluate(expr, context, null, context.window,
this.onEvaluateSucceeds, this.onEvaluateFails);
if (FBTrace.DBG_COOKIES)
- FBTrace.sysout("cookies.evaluateCondition; rc " + rc, {expr: expr, scope: scope});
+ {
+ FBTrace.sysout("cookies.evaluateCondition", {expr: expr, scope: scope});
+ }
return !!context.breakingCause;
}
diff --git a/extension/content/firebug/lib/wrapper.js b/extension/content/firebug/lib/wrapper.js
index 4728d60..aefbc9a 100644
--- a/extension/content/firebug/lib/wrapper.js
+++ b/extension/content/firebug/lib/wrapper.js
@@ -96,9 +96,6 @@ Wrapper.unwrapIValueObject = function(scope, viewChrome)
Wrapper.ignoreVars =
{
- "__firebug__": 1,
- "eval": 1,
-
// We are forced to ignore Java-related variables, because
// trying to access them causes browser freeze
"sun": 1,
@@ -112,6 +109,7 @@ Wrapper.ignoreVars =
// internal firebug things XXXjjb todo we should privatize these
"_firebug": 1,
"_firebugUnwrappedDebuggerObject": 1,
+ "__fb_scopedVars": 1,
"_FirebugCommandLine": 1,
};
diff --git a/extension/content/firebug/net/netDebugger.js b/extension/content/firebug/net/netDebugger.js
index e8bafc5..8789707 100644
--- a/extension/content/firebug/net/netDebugger.js
+++ b/extension/content/firebug/net/netDebugger.js
@@ -90,12 +90,14 @@ Breakpoint.prototype =
// The callbacks will set this if the condition is true or if the eval faults.
delete context.breakingCause;
- var rc = Firebug.CommandLine.evaluate(expr, context, null, context.window,
+ Firebug.CommandLine.evaluate(expr, context, null, context.window,
this.onEvaluateSucceeds, this.onEvaluateFails );
if (FBTrace.DBG_NET)
- FBTrace.sysout("net.evaluateCondition; rc " + rc, {expr: expr,scope: scope,
+ {
+ FBTrace.sysout("net.evaluateCondition", {expr: expr, scope: scope,
json: JSON.stringify(scope)});
+ }
return !!context.breakingCause;
}
--
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