Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Handle newScript event and persist breakpoints on the client side (no…

…t finished, breakpoints are not send to the server after Firebug starts)
  • Loading branch information...
commit a55946e8633d75a3423861108e9537a34a98b756 1 parent 09a062f
@janodvarko janodvarko authored
View
106 extension/content/firebug/debugger/debuggerClient.js
@@ -3,11 +3,11 @@
define([
"firebug/lib/object",
"firebug/lib/options",
- "firebug/debugger/sourceFile",
+ "firebug/debugger/sourceScripts",
"firebug/debugger/rdp",
"firebug/debugger/threadClient",
],
-function (Obj, Options, SourceFile, RDP, ThreadClient) {
+function (Obj, Options, SourceScripts, RDP, ThreadClient) {
// ********************************************************************************************* //
// Constants and Services
@@ -124,6 +124,14 @@ DebuggerClient.prototype = Obj.extend(new Firebug.EventSource(),
this.threadClients[packet.from].onThreadState(packet);
},
+ onNewScript: function(type, packet)
+ {
+ FBTrace.sysout("debuggerClient.onNewScript", arguments);
+
+ if (this.scripts)
+ this.scripts.onNewScript(packet);
+ },
+
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
startDebugging: function(tabGrip, callback)
@@ -146,6 +154,8 @@ DebuggerClient.prototype = Obj.extend(new Firebug.EventSource(),
return;
}
+ FBTrace.sysout("debuggerClient.onAttachThread; Thread attached.");
+
this.activeThread = threadClient;
// Connect script manager
@@ -184,98 +194,6 @@ DebuggerClient.prototype = Obj.extend(new Firebug.EventSource(),
});
// ********************************************************************************************* //
-// Source Scripts
-
-//xxxHonza: This entire object should be refactored.
-
-/**
- * Keeps the source script list up-to-date, using the thread client's
- * source script cache.
- */
-function SourceScripts(debuggerClient)
-{
- this.context = debuggerClient.context;
- this.debuggerClient = debuggerClient;
- this.connection = debuggerClient.connection;
- this.thread = debuggerClient.activeThread;
-}
-
-SourceScripts.prototype =
-{
- connect: function(callback)
- {
- this.thread.addListener(this);
-
- // Retrieve the list of scripts known to the server from before the client
- // was ready to handle new script notifications.
- this.thread.fillScripts();
-
- this.onNewScript = this.onNewScript.bind();
-
- this.debuggerClient.addListener("newScript", this.onNewScript);
- },
-
- disconnect: function()
- {
- this.thread.removeListener(this);
- this.debuggerClient.removeListener("newScript", this.onNewScript);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
- onNewScript: function(notification, packet)
- {
- // Ignore scripts generated from 'clientEvaluate' packets. These scripts are
- // create as the user is evaluating expressions in the watch window.
- if (aPacket.url == "debugger eval code")
- return;
-
- FBTrace.sysout("SourceScripts.onNewScript; " + notification, packet);
- },
-
- onScriptsAdded: function(scriptCache)
- {
- FBTrace.sysout("SourceScripts.onScriptsAdded; ", scriptCache);
-
- for (var p in scriptCache)
- {
- var script = scriptCache[p];
- var sourceFile = new SourceFile(script.url, script.startLine, script.lineCount);
- this.watchSourceFile(sourceFile);
- }
- },
-
- onScriptsCleared: function()
- {
- },
-
- watchSourceFile: function(sourceFile)
- {
- // @hack
- // xxxHonza: the Script panel update should happen from within the Script panel
- // The DebuggerClient (or SourceScripts) should just fire an event to the panel.
-
- var context = Firebug.currentContext;
-
- // store in the context and notify listeners
- context.addSourceFile(sourceFile);
-
- // Update the Script panel, this script could have been loaded asynchronously
- // and perhaps is the only one that should be displayed (otherwise the panel
- // would show: No Javascript on this page). See issue 4932
- var panel = context.getPanel("jsd2script", true);
- if (!panel)
- return;
-
- context.invalidatePanels("jsd2script");
- context.invalidatePanels("jsd2breakpoints");
-
- if (!panel.location)
- panel.navigate(null);
- },
-};
-
-// ********************************************************************************************* //
// Registration
return DebuggerClient;
View
49 extension/content/firebug/debugger/debuggerTool.js
@@ -52,7 +52,7 @@ var DebuggerTool = Obj.extend(Firebug.Module,
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Connection
- attach: function(context, connection, listener)
+ attach: function(context, connection, listener, callback)
{
this.addListener(listener);
@@ -66,6 +66,9 @@ var DebuggerTool = Obj.extend(Firebug.Module,
context.debuggerClient.attach(function(activeThread)
{
activeThread.addListener(self);
+
+ if (callback)
+ callback(activeThread);
});
},
@@ -73,6 +76,9 @@ var DebuggerTool = Obj.extend(Firebug.Module,
{
this.removeListener(listener);
+ // More panels using this tool can call detach. So, check first if we are
+ // detached already before sending the 'detach' packet.
+ // xxxHonza: we need to count listeners and detach when there is none.
if (!context.debuggerClient)
return;
@@ -80,6 +86,8 @@ var DebuggerTool = Obj.extend(Firebug.Module,
{
activeThread.removeListener(this);
});
+
+ context.debuggerClient = null;
},
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -141,6 +149,11 @@ var DebuggerTool = Obj.extend(Firebug.Module,
this.dispatch("onStackCleared");
},
+ newScript: function(sourceFile)
+ {
+ this.dispatch("newScript", [sourceFile]);
+ },
+
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Breakpoint API
@@ -148,20 +161,44 @@ var DebuggerTool = Obj.extend(Firebug.Module,
{
if (!context.debuggerClient.activeThread)
{
- FBTrace.sysout("debuggerTool.setBreakpoint; Can't set a braekpoint.");
+ FBTrace.sysout("debuggerTool.setBreakpoint; Can't set a breakpoint.");
return;
}
return context.debuggerClient.activeThread.setBreakpoint({
url: url,
- line: lineNumber + 1
+ line: lineNumber
}, callback);
},
- clearBreakpoint: function(context, url, lineNumber)
+ setBreakpoints: function(context, arr, callback)
+ {
+ if (!context.debuggerClient.activeThread)
+ {
+ FBTrace.sysout("debuggerTool.setBreakpoints; Can't set breakpoints.");
+ return;
+ }
+
+ return context.debuggerClient.activeThread.setBreakpoints(arr, callback);
+ },
+
+ removeBreakpoint: function(context, bp, callback)
{
- // This is more correct, but bypasses Debugger
- //JSDebugger.fbs.clearBreakpoint(url, lineNumber);
+ if (!context.debuggerClient.activeThread)
+ {
+ FBTrace.sysout("debuggerTool.removeBreakpoint; Can't remove breakpoints.");
+ return;
+ }
+
+ if (!bp)
+ {
+ FBTrace.sysout("debuggerTool.removeBreakpoint; No breakpoint specified.");
+ return;
+ }
+
+ var actor = bp.params.actor;
+ if (actor)
+ return context.debuggerClient.activeThread.removeBreakpoints(arr, callback);
},
enableBreakpoint: function(context, url, lineNumber)
View
39 extension/content/firebug/debugger/scriptPanel.js
@@ -5,6 +5,7 @@ define([
"firebug/lib/locale",
"firebug/lib/events",
"firebug/lib/dom",
+ "firebug/lib/array",
"firebug/debugger/scriptView",
"arch/compilationunit",
"firebug/debugger/debuggerTool",
@@ -14,7 +15,7 @@ define([
"firebug/debugger/breakpoint",
"firebug/debugger/breakpointStore",
],
-function (Obj, Locale, Events, Dom, ScriptView, CompilationUnit, DebuggerTool, Menu,
+function (Obj, Locale, Events, Dom, Arr, ScriptView, CompilationUnit, DebuggerTool, Menu,
StackFrame, SourceLink, Breakpoint, BreakpointStore) {
// ********************************************************************************************* //
@@ -80,7 +81,10 @@ ScriptPanel.prototype = Obj.extend(BasePanel,
// Depending on the current tool the communication can be local or remote.
// Access to the back-end debugger service (JSD2) must always be done through the tool.
this.tool = this.context.getTool("debugger");
- this.tool.attach(this.context, proxy.connection, this);
+ this.tool.attach(this.context, proxy.connection, this, function(activeThread)
+ {
+ // Backend thread attached.
+ });
},
onDisconnect: function(proxy)
@@ -309,7 +313,10 @@ ScriptPanel.prototype = Obj.extend(BasePanel,
onBreakpointAdd: function(bp)
{
var url = this.location.href;
- var line = bp.line;
+ var line = bp.line + 1;
+
+ // Persist the breakpoint on the client side
+ var bp = BreakpointStore.addBreakpoint(url, line);
function callback(response)
{
@@ -320,8 +327,7 @@ ScriptPanel.prototype = Obj.extend(BasePanel,
return;
}
- // Persist the breakpoint on the client side
- BreakpointStore.addBreakpoint(url, line, {actor: response.actor});
+ bp.params.actor = {actor: response.actor};
if (FBTrace.DBG_BP)
FBTrace.sysout("scriptPanel.onBreakpointAdd; breakpoint added", bp);
@@ -333,7 +339,19 @@ ScriptPanel.prototype = Obj.extend(BasePanel,
onBreakpointRemove: function(bp)
{
- FBTrace.sysout("scriptPanel.onBreakpointRemove " + bp, bp);
+ var url = this.location.href;
+ var line = bp.line + 1;
+
+ function callback(response)
+ {
+ FBTrace.sysout("scriptPanel.onBreakpointRemoved; ", response);
+ }
+
+ var bp = BreakpointStore.findBreakpoint(url, line);
+ this.tool.removeBreakpoint(this.context, bp, callback);
+
+ // Remove the breakpoint from the client side store.
+ BreakpointStore.removeBreakpoint(url, line);
},
onContextMenu: function(items)
@@ -734,6 +752,15 @@ ScriptPanel.prototype = Obj.extend(BasePanel,
}
},
+ newScript: function(sourceFile)
+ {
+ FBTrace.sysout("scriptPanel.newScript; " + sourceFile.href, sourceFile);
+
+ // Initialize existing breakpoints
+ //var bps = BreakpointStore.getBreakpoints(sourceFile.href);
+ //self.tool.setBreakpoints(self.context, bps, function(response){});
+ },
+
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Info Tips
View
29 extension/content/firebug/debugger/scriptView.js
@@ -83,12 +83,7 @@ ScriptView.prototype = Obj.extend(new Firebug.EventSource(),
if (this.defaultSource)
this.showSource(this.defaultSource);
- // xxxHonza: Breakpoints appear and disappear if it's done without
- // a timeout, why? Ask Mihai.
- var self = this;
- setTimeout(function() {
- self.initBreakpoints();
- }, 500);
+ this.initBreakpoints();
},
destroy: function()
@@ -109,10 +104,22 @@ ScriptView.prototype = Obj.extend(new Firebug.EventSource(),
showSource: function(source)
{
- if (this.initialized)
- this.editor.setText(source);
- else
+ FBTrace.sysout("scriptView.showSource; initialized: " + this.initialized, source);
+
+ if (!this.initialized)
+ {
this.defaultSource = source;
+ return;
+ }
+
+ var text = this.editor.getText();
+ if (text == source)
+ return;
+
+ this.editor.setText(source);
+
+ // Breakpoints and annotations in general must be set again after setText.
+ this.initBreakpoints();
},
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -238,8 +245,6 @@ ScriptView.prototype = Obj.extend(new Firebug.EventSource(),
var bps = [];
this.dispatch("onGetBreakpoints", [bps]);
- FBTrace.sysout("scriptView.initBreakpoints; " + bps.length, bps);
-
if (!bps.length)
return;
@@ -249,7 +254,7 @@ ScriptView.prototype = Obj.extend(new Firebug.EventSource(),
for (var i=0; i<bps.length; i++)
{
var bp = bps[i];
- this.editor.addBreakpoint(bp.lineNo);
+ this.editor.addBreakpoint(bp.lineNo - 1);
}
this.skipEditorBreakpointChange = false;
View
114 extension/content/firebug/debugger/sourceScripts.js
@@ -0,0 +1,114 @@
+/* See license.txt for terms of usage */
+
+define([
+ "firebug/lib/trace",
+ "firebug/lib/object",
+ "firebug/debugger/sourceFile",
+],
+function (FBTrace, Obj, SourceFile) {
+
+// ********************************************************************************************* //
+// Constants
+
+FBTrace = FBTrace.to("DBG_SCRIPTVIEW");
+
+// ********************************************************************************************* //
+// Source Scripts
+
+//xxxHonza: This entire object should be refactored.
+
+/**
+ * Keeps the source script list up-to-date, using the thread client's
+ * source script cache.
+ */
+function SourceScripts(debuggerClient)
+{
+ this.context = debuggerClient.context;
+ this.debuggerClient = debuggerClient;
+ this.connection = debuggerClient.connection;
+ this.thread = debuggerClient.activeThread;
+}
+
+SourceScripts.prototype =
+{
+ connect: function(callback)
+ {
+ this.thread.addListener(this);
+
+ // Retrieve the list of scripts known to the server from before the client
+ // was ready to handle new script notifications.
+ this.thread.fillScripts();
+
+ this.onNewScript = this.onNewScript.bind(this);
+ this.connection.addListener("newScript", this.onNewScript);
+ },
+
+ disconnect: function()
+ {
+ this.thread.removeListener(this);
+ this.connection.removeListener("newScript", this.onNewScript);
+ },
+
+ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+ onNewScript: function(notification, script)
+ {
+ // Ignore scripts generated from 'clientEvaluate' packets. These scripts are
+ // create as the user is evaluating expressions in the watch window.
+ if (script.url == "debugger eval code")
+ return;
+
+ FBTrace.sysout("SourceScripts.onNewScript; " + notification, script);
+
+ var sourceFile = new SourceFile(script.url, script.startLine, script.lineCount);
+ this.watchSourceFile(sourceFile);
+
+ this.thread.dispatch("newScript", [sourceFile]);
+ },
+
+ onScriptsAdded: function(scriptCache)
+ {
+ for (var p in scriptCache)
+ {
+ var script = scriptCache[p];
+ this.onNewScript("newScript", script);
+ }
+ },
+
+ onScriptsCleared: function()
+ {
+ },
+
+ watchSourceFile: function(sourceFile)
+ {
+ // @hack
+ // xxxHonza: the Script panel update should happen from within the Script panel
+ // The DebuggerClient (or SourceScripts) should just fire an event to the panel.
+
+ var context = Firebug.currentContext;
+
+ // store in the context and notify listeners
+ context.addSourceFile(sourceFile);
+
+ // Update the Script panel, this script could have been loaded asynchronously
+ // and perhaps is the only one that should be displayed (otherwise the panel
+ // would show: No Javascript on this page). See issue 4932
+ var panel = context.getPanel("jsd2script", true);
+ if (!panel)
+ return;
+
+ context.invalidatePanels("jsd2script");
+ context.invalidatePanels("jsd2breakpoints");
+
+ if (!panel.location)
+ panel.navigate(null);
+ },
+};
+
+// ********************************************************************************************* //
+// Registration
+
+return SourceScripts;
+
+// ********************************************************************************************* //
+});
Please sign in to comment.
Something went wrong with that request. Please try again.