diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index 7c2b622d644..231ae1ac079 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -661,6 +661,7 @@ StackFrames.prototype = { } DebuggerView.StackFrames.selectedDepth = Math.max(this.currentFrameDepth, 0); + DebuggerView.StackFrames.dirty = this.activeThread.moreFrames; window.emit(EVENTS.AFTER_FRAMES_REFILLED); }, diff --git a/browser/devtools/debugger/debugger-toolbar.js b/browser/devtools/debugger/debugger-toolbar.js index 641632ddd76..804274b3e77 100644 --- a/browser/devtools/debugger/debugger-toolbar.js +++ b/browser/devtools/debugger/debugger-toolbar.js @@ -471,6 +471,11 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, { return this.selectedItem.attachment.depth; }, + /** + * Specifies if the active thread has more frames that need to be loaded. + */ + dirty: false, + /** * Customization function for creating an item's UI. * @@ -556,7 +561,7 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, { */ _onScroll: function() { // Update the stackframes container only if we have to. - if (!DebuggerController.activeThread.moreFrames) { + if (!this.dirty) { return; } // Allow requests to settle down first. @@ -567,20 +572,14 @@ StackFramesView.prototype = Heritage.extend(WidgetMethods, { * Requests the addition of more frames from the controller. */ _afterScroll: function() { - // Check again if we have to update the stackframes container, because in - // some cases (e.g. browser_dbg_variables-view-edit-getset-02.js) the value - // might have changed from the time the setNamedTimeout call was made. - if (!DebuggerController.activeThread.moreFrames) { - return; - } let scrollPosition = this.widget.getAttribute("scrollPosition"); let scrollWidth = this.widget.getAttribute("scrollWidth"); // If the stackframes container scrolled almost to the end, with only // 1/10 of a breadcrumb remaining, load more content. if (scrollPosition - scrollWidth / 10 < 1) { - let index = Math.min(CALL_STACK_PAGE_SIZE - 1, this.items.length - 1); - this.ensureIndexIsVisible(index); + this.ensureIndexIsVisible(CALL_STACK_PAGE_SIZE - 1); + this.dirty = false; // Loads more stack frames from the debugger server cache. DebuggerController.StackFrames.addMoreFrames(); diff --git a/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js b/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js index 36f395535f8..d86304bec85 100644 --- a/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js +++ b/browser/devtools/debugger/test/browser_dbg_variables-view-edit-getset-02.js @@ -6,49 +6,69 @@ * to plain value properties. */ -function test() { - const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; +const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html"; +let gTab, gDebuggee, gPanel, gDebugger; +let gL10N, gEditor, gVars, gWatch; + +function test() { // Debug test slaves are a bit slow at this test. requestLongerTimeout(2); - Task.spawn(function* () { - let [, debuggee, panel] = yield initDebugger(TAB_URL); - let win = panel.panelWin; - let L10N = win.L10N; - let editor = win.DebuggerView.editor; - let vars = win.DebuggerView.Variables; - let watch = win.DebuggerView.WatchExpressions; + initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => { + gTab = aTab; + gDebuggee = aDebuggee; + gPanel = aPanel; + gDebugger = gPanel.panelWin; + gL10N = gDebugger.L10N; + gEditor = gDebugger.DebuggerView.editor; + gVars = gDebugger.DebuggerView.Variables; + gWatch = gDebugger.DebuggerView.WatchExpressions; - vars.switch = function() {}; - vars.delete = function() {}; + gVars.switch = function() {}; + gVars.delete = function() {}; - let paused = waitForSourceAndCaretAndScopes(panel, ".html", 24); - // Spin the event loop before causing the debuggee to pause, to allow - // this function to return first. - executeSoon(() => { - EventUtils.sendMouseEvent({ type: "click" }, - debuggee.document.querySelector("button"), - debuggee); + waitForSourceAndCaretAndScopes(gPanel, ".html", 24) + .then(() => addWatchExpression()) + .then(() => testEdit("\"xlerb\"", "xlerb")) + .then(() => resumeDebuggerThenCloseAndFinish(gPanel)) + .then(null, aError => { + ok(false, "Got an error: " + aError.message + "\n" + aError.stack); + }); + + EventUtils.sendMouseEvent({ type: "click" }, + gDebuggee.document.querySelector("button"), + gDebuggee); + }); +} + +function addWatchExpression() { + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS); + + gWatch.addExpression("myVar.prop"); + gEditor.focus(); + + return finished; +} + +function testEdit(aString, aExpected) { + let localScope = gVars.getScopeAtIndex(1); + let myVar = localScope.get("myVar"); + + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES).then(() => { + let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_WATCH_EXPRESSIONS).then(() => { + let exprScope = gVars.getScopeAtIndex(0); + + ok(exprScope, + "There should be a wach expressions scope in the variables view."); + is(exprScope.name, gL10N.getStr("watchExpressionsScopeLabel"), + "The scope's name should be marked as 'Watch Expressions'."); + is(exprScope._store.size, 1, + "There should be one evaluation available."); + + is(exprScope.get("myVar.prop").value, aExpected, + "The expression value is correct after the edit."); }); - yield paused; - - // Add a watch expression for direct observation of the value change. - let addedWatch = waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS); - watch.addExpression("myVar.prop"); - editor.focus(); - yield addedWatch; - - // Scroll myVar into view. - vars.focusLastVisibleItem(); - - let localScope = vars.getScopeAtIndex(1); - let myVar = localScope.get("myVar"); - - myVar.expand(); - vars.clearHierarchy(); - - yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_PROPERTIES); let editTarget = myVar.get("prop").target; @@ -56,29 +76,30 @@ function test() { // its value would scroll the new textbox node into view. executeSoon(() => { let varEdit = editTarget.querySelector(".title > .variables-view-edit"); - EventUtils.sendMouseEvent({ type: "mousedown" }, varEdit, win); + EventUtils.sendMouseEvent({ type: "mousedown" }, varEdit, gDebugger); let varInput = editTarget.querySelector(".title > .element-value-input"); - setText(varInput, "\"xlerb\""); - EventUtils.sendKey("RETURN", win); + setText(varInput, aString); + EventUtils.sendKey("RETURN", gDebugger); }); - yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS); - - let exprScope = vars.getScopeAtIndex(0); - - ok(exprScope, - "There should be a wach expressions scope in the variables view."); - is(exprScope.name, L10N.getStr("watchExpressionsScopeLabel"), - "The scope's name should be marked as 'Watch Expressions'."); - is(exprScope._store.size, 1, - "There should be one evaluation available."); - - is(exprScope.get("myVar.prop").value, "xlerb", - "The expression value is correct after the edit."); - - yield resumeDebuggerThenCloseAndFinish(panel); - }).then(null, aError => { - ok(false, "Got an error: " + aError.message + "\n" + aError.stack); + return finished; }); + + myVar.expand(); + gVars.clearHierarchy(); + + return finished; } + +registerCleanupFunction(function() { + gTab = null; + gDebuggee = null; + gPanel = null; + gDebugger = null; + gL10N = null; + gEditor = null; + gVars = null; + gWatch = null; +}); +