Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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
janodvarko committed Sep 21, 2012
1 parent 09a062f commit a55946e
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 118 deletions.
106 changes: 12 additions & 94 deletions extension/content/firebug/debugger/debuggerClient.js
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -146,6 +154,8 @@ DebuggerClient.prototype = Obj.extend(new Firebug.EventSource(),
return;
}

FBTrace.sysout("debuggerClient.onAttachThread; Thread attached.");

this.activeThread = threadClient;

// Connect script manager
Expand Down Expand Up @@ -183,98 +193,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

Expand Down
49 changes: 43 additions & 6 deletions extension/content/firebug/debugger/debuggerTool.js
Expand Up @@ -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);

Expand All @@ -66,20 +66,28 @@ var DebuggerTool = Obj.extend(Firebug.Module,
context.debuggerClient.attach(function(activeThread)
{
activeThread.addListener(self);

if (callback)
callback(activeThread);
});
},

detach: function(context, connection, listener)
{
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;

context.debuggerClient.detach(function(activeThread)
{
activeThread.removeListener(this);
});

context.debuggerClient = null;
},

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Expand Down Expand Up @@ -141,27 +149,56 @@ var DebuggerTool = Obj.extend(Firebug.Module,
this.dispatch("onStackCleared");
},

newScript: function(sourceFile)
{
this.dispatch("newScript", [sourceFile]);
},

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Breakpoint API

setBreakpoint: function(context, url, lineNumber, callback)
{
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)
Expand Down
39 changes: 33 additions & 6 deletions extension/content/firebug/debugger/scriptPanel.js
Expand Up @@ -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",
Expand All @@ -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) {

// ********************************************************************************************* //
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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

Expand Down
29 changes: 17 additions & 12 deletions extension/content/firebug/debugger/scriptView.js
Expand Up @@ -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()
Expand All @@ -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();
},

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down

0 comments on commit a55946e

Please sign in to comment.