Bug 723563 - Use findScripts to retrieve the list of scripts known to the debugger; r=rcampbell

This commit is contained in:
Panos Astithas 2012-03-30 11:25:52 +03:00
parent 9913ffaba0
commit 9436803818
15 changed files with 54 additions and 105 deletions

View File

@ -311,6 +311,10 @@ var StackFrames = {
paramVar.setGrip(paramVal);
this._addExpander(paramVar, paramVal);
}
// Signal that call parameters have been fetched.
let evt = document.createEvent("Event");
evt.initEvent("Debugger:FetchedParameters", true, false);
document.documentElement.dispatchEvent(evt);
}.bind(this));
}
},
@ -469,11 +473,13 @@ var SourceScripts = {
DebuggerView.Scripts.addChangeListener(this.onChange);
this.activeThread = aThreadClient;
aThreadClient.addListener("paused", this.onPaused);
aThreadClient.addListener("scriptsadded", this.onScripts);
aThreadClient.addListener("scriptscleared", this.onScriptsCleared);
this.clearLabelsCache();
this.onScriptsCleared();
// Retrieve the list of scripts known to the server from before the client
// was ready to handle new script notifications.
this.activeThread.fillScripts();
aCallback && aCallback();
},
@ -481,21 +487,10 @@ var SourceScripts = {
* Disconnect from the client.
*/
disconnect: function TS_disconnect() {
this.activeThread.removeListener("paused", this.onPaused);
this.activeThread.removeListener("scriptsadded", this.onScripts);
this.activeThread.removeListener("scriptscleared", this.onScriptsCleared);
},
/**
* Handler for the thread client's paused notification. This is triggered only
* once, to retrieve the list of scripts known to the server from before the
* client was ready to handle new script notifications.
*/
onPaused: function SS_onPaused() {
this.activeThread.removeListener("paused", this.onPaused);
this.activeThread.fillScripts();
},
/**
* Handler for the debugger client's unsolicited newScript notification.
*/
@ -657,7 +652,6 @@ var SourceScripts = {
}
};
SourceScripts.onPaused = SourceScripts.onPaused.bind(SourceScripts);
SourceScripts.onScripts = SourceScripts.onScripts.bind(SourceScripts);
SourceScripts.onNewScript = SourceScripts.onNewScript.bind(SourceScripts);
SourceScripts.onScriptsCleared = SourceScripts.onScriptsCleared.bind(SourceScripts);

View File

@ -28,7 +28,7 @@ function test()
gPane = aPane;
gDebugger = gPane.debuggerWindow;
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gPane.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
});
gDebuggee.firstCall();

View File

@ -26,7 +26,7 @@ function test()
gPane = aPane;
gDebugger = gPane.debuggerWindow;
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gPane.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0);
});
gDebuggee.firstCall();

View File

@ -32,8 +32,7 @@ function test_early_debugger_statement(aActor)
gClient.addListener("paused", paused);
// This should continue without nesting an event loop and calling
// the onPaused hook, because we haven't attached yet.
// TODO: uncomment this when bug 723563 is fixed.
//gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
gClient.removeListener("paused", paused);

View File

@ -87,7 +87,7 @@ function test_attach_removed_tab()
});
gClient.request({ to: gTab2Actor, type: "attach" }, function(aResponse) {
is(aResponse.error, "noSuchActor", "Tab should be gone.");
is(aResponse.type, "exited", "Tab should consider itself exited.");
finish_test();
});
}

View File

@ -85,6 +85,7 @@ function resumeAndFinish() {
gDebugger.StackFrames.activeThread.resume(function() {
let vs = gDebugger.DebuggerView.Scripts;
let ss = gDebugger.SourceScripts;
ss.onScriptsCleared();
is(ss._trimUrlQuery("a/b/c.d?test=1&random=4"), "a/b/c.d",
"Trimming the url query isn't done properly.");

View File

@ -25,9 +25,8 @@ function test()
function testFrameParameters()
{
// scriptsadded is fired last when switching to a paused state, so the
// property view will have had a chance to fetch the call parameters.
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.Stackframes._frames,
@ -70,7 +69,7 @@ function testFrameParameters()
resumeAndFinish();
}}, 0);
});
}, false);
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"),

View File

@ -25,9 +25,8 @@ function test()
function testFrameParameters()
{
// scriptsadded is fired last when switching to a paused state, so the
// property view will have had a chance to fetch the call parameters.
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gDebugger.addEventListener("Debugger:FetchedParameters", function test() {
gDebugger.removeEventListener("Debugger:FetchedParameters", test, false);
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.Stackframes._frames,
@ -86,7 +85,7 @@ function testFrameParameters()
resumeAndFinish();
}, 100);
}}, 0);
});
}, false);
EventUtils.synthesizeMouseAtCenter(content.document.querySelector("button"),
{},

View File

@ -31,7 +31,7 @@ function test()
}
function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gPane.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;

View File

@ -26,7 +26,7 @@ function test() {
}
function testRecurse() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gPane.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let frames = gDebugger.DebuggerView.Stackframes._frames;
let childNodes = frames.childNodes;

View File

@ -31,7 +31,7 @@ function test()
}
function testScriptsDisplay() {
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
gPane.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
gScripts = gDebugger.DebuggerView.Scripts._scripts;

View File

@ -73,7 +73,7 @@ function testCreateCommands() {
// Wait for the initial resume.
aPane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
delete aPane.onConnected;
aPane.debuggerWindow.gClient.activeThread.addOneTimeListener("scriptsadded", function() {
aPane.debuggerWindow.gClient.activeThread.addOneTimeListener("framesadded", function() {
type("break add line " + TEST_URI + " " + content.wrappedJSObject.line0);
is(requisition.getStatus().toString(), "VALID", "break add line is VALID");
requisition.exec();

View File

@ -30,7 +30,7 @@ localScope=Local
# pane as a header on the globel scope container.
globalScope=Global
# LOCALIZATION NOTE (localScope): The label that is displayed in the variables
# LOCALIZATION NOTE (withScope): The label that is displayed in the variables
# pane as a header on the container for identifiers in a with block.
withScope=With block

View File

@ -67,7 +67,6 @@ function BrowserRootActor(aConnection)
this._actorFactories = null;
this.onTabClosed = this.onTabClosed.bind(this);
this._onWindowCreated = this.onWindowCreated.bind(this);
windowMediator.addListener(this);
}
@ -76,10 +75,6 @@ BrowserRootActor.prototype = {
* Return a 'hello' packet as specified by the Remote Debugging Protocol.
*/
sayHello: function BRA_sayHello() {
// Create the tab actor for the selected tab right away so that it gets a
// chance to listen to onNewScript notifications.
this._preInitTabActor();
return { from: "root",
applicationType: "browser",
traits: [] };
@ -123,6 +118,10 @@ BrowserRootActor.prototype = {
while (e.hasMoreElements()) {
let win = e.getNext();
// Watch the window for tab closes so we can invalidate
// actors as needed.
this.watchWindow(win);
// List the tabs in this browser.
let selectedBrowser = win.getBrowser().selectedBrowser;
let browsers = win.getBrowser().browsers;
@ -183,61 +182,16 @@ BrowserRootActor.prototype = {
this.exitTabActor(aEvent.target.linkedBrowser);
},
/**
* Handle location changes, by preinitializing a tab actor.
*/
onWindowCreated: function BRA_onWindowCreated(evt) {
if (evt.target === this.browser.contentDocument) {
this._preInitTabActor();
}
},
/**
* Exit the tab actor of the specified tab.
*/
exitTabActor: function BRA_exitTabActor(aWindow) {
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
let actor = this._tabActors.get(aWindow);
if (actor) {
actor.exit();
}
},
/**
* Create the tab actor in the selected tab right away so that it gets a
* chance to listen to onNewScript notifications.
*/
_preInitTabActor: function BRA__preInitTabActor() {
let actorPool = new ActorPool(this.conn);
// Walk over open browser windows.
let e = windowMediator.getEnumerator("navigator:browser");
while (e.hasMoreElements()) {
let win = e.getNext();
// Watch the window for tab closes so we can invalidate
// actors as needed.
this.watchWindow(win);
this.browser = win.getBrowser().selectedBrowser;
let actor = this._tabActors.get(this.browser);
if (actor) {
actor._detach();
}
actor = new BrowserTabActor(this.conn, this.browser);
actor.parentID = this.actorID;
this._tabActors.set(this.browser, actor);
actorPool.addActor(actor);
}
this._tabActorPool = actorPool;
this.conn.addActorPool(this._tabActorPool);
// Watch for globals being created in this tab.
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
},
// nsIWindowMediatorListener
onWindowTitleChange: function BRA_onWindowTitleChange(aWindow, aTitle) { },
onOpenWindow: function BRA_onOpenWindow(aWindow) { },
@ -270,7 +224,6 @@ function BrowserTabActor(aConnection, aBrowser)
this._browser = aBrowser;
this._onWindowCreated = this.onWindowCreated.bind(this);
this._attach();
}
// XXX (bug 710213): BrowserTabActor attach/detach/exit/disconnect is a
@ -341,7 +294,7 @@ BrowserTabActor.prototype = {
this._pushContext();
// Watch for globals being created in this tab.
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, false);
this.browser.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
this._attached = true;
},
@ -393,7 +346,7 @@ BrowserTabActor.prototype = {
return;
}
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, false);
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
this._popContext();

View File

@ -99,19 +99,12 @@ ThreadActor.prototype = {
this._dbg = new Debugger();
}
// TODO: Remove this horrible hack when bug 723563 is fixed.
// Make sure that a chrome window is not added as a debuggee when opening
// the debugger in an empty tab or during tests.
if (aGlobal.location &&
(aGlobal.location.protocol == "about:" ||
aGlobal.location.protocol == "chrome:")) {
return;
}
this.dbg.addDebuggee(aGlobal);
this.dbg.uncaughtExceptionHook = this.uncaughtExceptionHook.bind(this);
this.dbg.onDebuggerStatement = this.onDebuggerStatement.bind(this);
this.dbg.onNewScript = this.onNewScript.bind(this);
// Keep the debugger disabled until a client attaches.
this.dbg.enabled = false;
},
/**
@ -503,6 +496,11 @@ ThreadActor.prototype = {
* Handle a protocol request to return the list of loaded scripts.
*/
onScripts: function TA_onScripts(aRequest) {
// Get the script list from the debugger.
for (let s of this.dbg.findScripts()) {
this._addScript(s);
}
// Build the cache.
let scripts = [];
for (let url in this._scripts) {
for (let i = 0; i < this._scripts[url].length; i++) {
@ -859,28 +857,34 @@ ThreadActor.prototype = {
},
/**
* A function that the engine calls when a new script has been loaded into a
* debuggee compartment. If the new code is part of a function, aFunction is
* a Debugger.Object reference to the function object. (Not all code is part
* of a function; for example, the code appearing in a <script> tag that is
* outside of any functions defined in that tag would be passed to
* onNewScript without an accompanying function argument.)
* A function that the engine calls when a new script has been loaded into the
* scope of the specified debuggee global.
*
* @param aScript Debugger.Script
* The source script that has been loaded into a debuggee compartment.
* @param aFunction Debugger.Object
* The function object that the ew code is part of.
* @param aGlobal Debugger.Object
* A Debugger.Object instance whose referent is the global object.
*/
onNewScript: function TA_onNewScript(aScript, aFunction) {
onNewScript: function TA_onNewScript(aScript, aGlobal) {
this._addScript(aScript);
// Notify the client.
this.conn.send({ from: this.actorID, type: "newScript",
url: aScript.url, startLine: aScript.startLine });
},
/**
* Add the provided script to the server cache.
*
* @param aScript Debugger.Script
* The source script that will be stored.
*/
_addScript: function TA__addScript(aScript) {
// Use a sparse array for storing the scripts for each URL in order to
// optimize retrieval.
if (!this._scripts[aScript.url]) {
this._scripts[aScript.url] = [];
}
this._scripts[aScript.url][aScript.startLine] = aScript;
// Notify the client.
this.conn.send({ from: this.actorID, type: "newScript",
url: aScript.url, startLine: aScript.startLine });
}
};