diff --git a/browser/devtools/debugger/debugger.js b/browser/devtools/debugger/debugger.js index 0a93b3e5fc47..ad56f14302f6 100644 --- a/browser/devtools/debugger/debugger.js +++ b/browser/devtools/debugger/debugger.js @@ -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); diff --git a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js index f2066d162267..7376ec5dece2 100644 --- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js +++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js @@ -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(); diff --git a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js index e4be65aac2cf..f3a166d40c4a 100644 --- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js +++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js @@ -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(); diff --git a/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js b/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js index d6e87d15167c..de18429f086b 100644 --- a/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js +++ b/browser/devtools/debugger/test/browser_dbg_debuggerstatement.js @@ -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); diff --git a/browser/devtools/debugger/test/browser_dbg_listtabs.js b/browser/devtools/debugger/test/browser_dbg_listtabs.js index 9c48ad8c66bf..8cca2953590c 100644 --- a/browser/devtools/debugger/test/browser_dbg_listtabs.js +++ b/browser/devtools/debugger/test/browser_dbg_listtabs.js @@ -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(); }); } diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js index f1923f7a8cce..d974981f7d7d 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-01.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-01.js @@ -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."); diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js index 4c1b9f1e3a2e..3ae2055cfa21 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js @@ -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"), diff --git a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js index 59765da70fce..044344450814 100644 --- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js @@ -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"), {}, diff --git a/browser/devtools/debugger/test/browser_dbg_script-switching.js b/browser/devtools/debugger/test/browser_dbg_script-switching.js index 1a08ff7f2b6b..9bdb87fded52 100644 --- a/browser/devtools/debugger/test/browser_dbg_script-switching.js +++ b/browser/devtools/debugger/test/browser_dbg_script-switching.js @@ -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; diff --git a/browser/devtools/debugger/test/browser_dbg_stack-05.js b/browser/devtools/debugger/test/browser_dbg_stack-05.js index d5884d15e7d7..9731a9230f84 100644 --- a/browser/devtools/debugger/test/browser_dbg_stack-05.js +++ b/browser/devtools/debugger/test/browser_dbg_stack-05.js @@ -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; diff --git a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js index 7a1a44400a1c..717d2cb23231 100644 --- a/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js +++ b/browser/devtools/debugger/test/browser_dbg_update-editor-mode.js @@ -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; diff --git a/browser/devtools/webconsole/test/browser_gcli_break.js b/browser/devtools/webconsole/test/browser_gcli_break.js index c1192a2674ff..da33681d323a 100644 --- a/browser/devtools/webconsole/test/browser_gcli_break.js +++ b/browser/devtools/webconsole/test/browser_gcli_break.js @@ -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(); diff --git a/browser/locales/en-US/chrome/browser/devtools/debugger.properties b/browser/locales/en-US/chrome/browser/devtools/debugger.properties index 6652f8f54677..90642b1581c0 100644 --- a/browser/locales/en-US/chrome/browser/devtools/debugger.properties +++ b/browser/locales/en-US/chrome/browser/devtools/debugger.properties @@ -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 diff --git a/toolkit/devtools/debugger/server/dbg-browser-actors.js b/toolkit/devtools/debugger/server/dbg-browser-actors.js index 9d583874e498..74d3e27bd3f3 100644 --- a/toolkit/devtools/debugger/server/dbg-browser-actors.js +++ b/toolkit/devtools/debugger/server/dbg-browser-actors.js @@ -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(); diff --git a/toolkit/devtools/debugger/server/dbg-script-actors.js b/toolkit/devtools/debugger/server/dbg-script-actors.js index 2274aec94c08..135cedfd0f83 100644 --- a/toolkit/devtools/debugger/server/dbg-script-actors.js +++ b/toolkit/devtools/debugger/server/dbg-script-actors.js @@ -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