Loading browser/devtools/debugger/debugger-controller.js +21 −33 Original line number Diff line number Diff line Loading @@ -78,15 +78,18 @@ const EVENTS = { Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/devtools/dbg-client.jsm"); let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise; Cu.import("resource:///modules/devtools/shared/event-emitter.js"); Cu.import("resource:///modules/devtools/sourceeditor/source-editor.jsm"); Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm"); Cu.import("resource:///modules/devtools/SideMenuWidget.jsm"); Cu.import("resource:///modules/devtools/VariablesView.jsm"); Cu.import("resource:///modules/devtools/VariablesViewController.jsm"); Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require; const Editor = require("devtools/sourceeditor/editor"); const promise = require("sdk/core/promise"); const DebuggerEditor = require("devtools/sourceeditor/debugger.js"); XPCOMUtils.defineLazyModuleGetter(this, "Parser", "resource:///modules/devtools/Parser.jsm"); Loading Loading @@ -608,7 +611,7 @@ StackFrames.prototype = { * Handler for the thread client's resumed notification. */ _onResumed: function() { DebuggerView.editor.setDebugLocation(-1); DebuggerView.editor.clearDebugLocation(); // Prepare the watch expression evaluation string for the next pause. if (!this._isWatchExpressionsEvaluation) { Loading Loading @@ -1434,7 +1437,6 @@ EventListeners.prototype = { * Handles all the breakpoints in the current debugger. */ function Breakpoints() { this._onEditorBreakpointChange = this._onEditorBreakpointChange.bind(this); this._onEditorBreakpointAdd = this._onEditorBreakpointAdd.bind(this); this._onEditorBreakpointRemove = this._onEditorBreakpointRemove.bind(this); this.addBreakpoint = this.addBreakpoint.bind(this); Loading @@ -1457,8 +1459,8 @@ Breakpoints.prototype = { * A promise that is resolved when the breakpoints finishes initializing. */ initialize: function() { DebuggerView.editor.addEventListener( SourceEditor.EVENTS.BREAKPOINT_CHANGE, this._onEditorBreakpointChange); DebuggerView.editor.on("breakpointAdded", this._onEditorBreakpointAdd); DebuggerView.editor.on("breakpointRemoved", this._onEditorBreakpointRemove); // Initialization is synchronous, for now. return promise.resolve(null); Loading @@ -1471,34 +1473,21 @@ Breakpoints.prototype = { * A promise that is resolved when the breakpoints finishes destroying. */ destroy: function() { DebuggerView.editor.removeEventListener( SourceEditor.EVENTS.BREAKPOINT_CHANGE, this._onEditorBreakpointChange); DebuggerView.editor.off("breakpointAdded", this._onEditorBreakpointAdd); DebuggerView.editor.off("breakpointRemoved", this._onEditorBreakpointRemove); return this.removeAllBreakpoints(); }, /** * Event handler for breakpoint changes that happen in the editor. This * function syncs the breakpoints in the editor to those in the debugger. * * @param object aEvent * The SourceEditor.EVENTS.BREAKPOINT_CHANGE event object. */ _onEditorBreakpointChange: function(aEvent) { aEvent.added.forEach(this._onEditorBreakpointAdd, this); aEvent.removed.forEach(this._onEditorBreakpointRemove, this); }, /** * Event handler for new breakpoints that come from the editor. * * @param object aEditorBreakpoint * The breakpoint object coming from the editor. * @param number aLine * Line number where breakpoint was set. */ _onEditorBreakpointAdd: function(aEditorBreakpoint) { _onEditorBreakpointAdd: function(_, aLine) { let url = DebuggerView.Sources.selectedValue; let line = aEditorBreakpoint.line + 1; let location = { url: url, line: line }; let location = { url: url, line: aLine + 1 }; // Initialize the breakpoint, but don't update the editor, since this // callback is invoked because a breakpoint was added in the editor itself. Loading @@ -1511,26 +1500,25 @@ Breakpoints.prototype = { DebuggerView.editor.addBreakpoint(aBreakpointClient.location.line - 1); } // Notify that we've shown a breakpoint in the source editor. window.emit(EVENTS.BREAKPOINT_SHOWN, aEditorBreakpoint); window.emit(EVENTS.BREAKPOINT_SHOWN); }); }, /** * Event handler for breakpoints that are removed from the editor. * * @param object aEditorBreakpoint * The breakpoint object that was removed from the editor. * @param number aLine * Line number where breakpoint was removed. */ _onEditorBreakpointRemove: function(aEditorBreakpoint) { _onEditorBreakpointRemove: function(_, aLine) { let url = DebuggerView.Sources.selectedValue; let line = aEditorBreakpoint.line + 1; let location = { url: url, line: line }; let location = { url: url, line: aLine + 1 }; // Destroy the breakpoint, but don't update the editor, since this callback // is invoked because a breakpoint was removed from the editor itself. this.removeBreakpoint(location, { noEditorUpdate: true }).then(() => { // Notify that we've hidden a breakpoint in the source editor. window.emit(EVENTS.BREAKPOINT_HIDDEN, aEditorBreakpoint); window.emit(EVENTS.BREAKPOINT_HIDDEN); }); }, Loading Loading @@ -1644,7 +1632,7 @@ Breakpoints.prototype = { // after the target navigated). Note that this will get out of sync // if the source text contents change. let line = aBreakpointClient.location.line - 1; aBreakpointClient.text = DebuggerView.getEditorLineText(line).trim(); aBreakpointClient.text = DebuggerView.editor.getText(line).trim(); // Show the breakpoint in the editor and breakpoints pane, and resolve. this._showBreakpoint(aBreakpointClient, aOptions); Loading browser/devtools/debugger/debugger-panes.js +28 −26 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ function SourcesView() { this.togglePrettyPrint = this.togglePrettyPrint.bind(this); this._onEditorLoad = this._onEditorLoad.bind(this); this._onEditorUnload = this._onEditorUnload.bind(this); this._onEditorSelection = this._onEditorSelection.bind(this); this._onEditorCursorActivity = this._onEditorCursorActivity.bind(this); this._onEditorContextMenu = this._onEditorContextMenu.bind(this); this._onSourceSelect = this._onSourceSelect.bind(this); this._onSourceClick = this._onSourceClick.bind(this); Loading Loading @@ -479,7 +479,12 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { */ _hideConditionalPopup: function() { this._cbPanel.hidden = true; // Sometimes this._cbPanel doesn't have hidePopup method which doesn't // break anything but simply outputs an exception to the console. if (this._cbPanel.hidePopup) { this._cbPanel.hidePopup(); } }, /** Loading Loading @@ -645,30 +650,30 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { * The load listener for the source editor. */ _onEditorLoad: function(aName, aEditor) { aEditor.addEventListener(SourceEditor.EVENTS.SELECTION, this._onEditorSelection, false); aEditor.addEventListener(SourceEditor.EVENTS.CONTEXT_MENU, this._onEditorContextMenu, false); aEditor.on("cursorActivity", this._onEditorCursorActivity); aEditor.on("contextMenu", this._onEditorContextMenu); }, /** * The unload listener for the source editor. */ _onEditorUnload: function(aName, aEditor) { aEditor.removeEventListener(SourceEditor.EVENTS.SELECTION, this._onEditorSelection, false); aEditor.removeEventListener(SourceEditor.EVENTS.CONTEXT_MENU, this._onEditorContextMenu, false); aEditor.off("cursorActivity", this._onEditorCursorActivity); aEditor.off("contextMenu", this._onEditorContextMenu); }, /** * The selection listener for the source editor. */ _onEditorSelection: function(e) { let { start, end } = e.newValue; _onEditorCursorActivity: function(e) { let editor = DebuggerView.editor; let start = editor.getCursor("start").line + 1; let end = editor.getCursor().line + 1; let url = this.selectedValue; let lineStart = DebuggerView.editor.getLineAtOffset(start) + 1; let lineEnd = DebuggerView.editor.getLineAtOffset(end) + 1; let location = { url: url, line: lineStart }; if (this.getBreakpoint(location) && lineStart == lineEnd) { let location = { url: url, line: start }; if (this.getBreakpoint(location) && start == end) { this.highlightBreakpoint(location, { noEditorUpdate: true }); } else { this.unhighlightBreakpoint(); Loading @@ -679,9 +684,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { * The context menu listener for the source editor. */ _onEditorContextMenu: function({ x, y }) { let offset = DebuggerView.editor.getOffsetAtLocation(x, y); let line = DebuggerView.editor.getLineAtOffset(offset); this._editorContextMenuLineNumber = line; this._editorContextMenuLineNumber = DebuggerView.editor.getPositionFromCoords(x, y).line; }, /** Loading Loading @@ -869,13 +872,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { // If this command was executed via the context menu, add the breakpoint // on the currently hovered line in the source editor. if (this._editorContextMenuLineNumber >= 0) { DebuggerView.editor.setCaretPosition(this._editorContextMenuLineNumber); DebuggerView.editor.setCursor({ line: this._editorContextMenuLineNumber, ch: 0 }); } // Avoid placing breakpoints incorrectly when using key shortcuts. this._editorContextMenuLineNumber = -1; let url = DebuggerView.Sources.selectedValue; let line = DebuggerView.editor.getCaretPosition().line + 1; let line = DebuggerView.editor.getCursor().line + 1; let location = { url: url, line: line }; let breakpointItem = this.getBreakpoint(location); Loading @@ -896,13 +900,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { // If this command was executed via the context menu, add the breakpoint // on the currently hovered line in the source editor. if (this._editorContextMenuLineNumber >= 0) { DebuggerView.editor.setCaretPosition(this._editorContextMenuLineNumber); DebuggerView.editor.setCursor({ line: this._editorContextMenuLineNumber, ch: 0 }); } // Avoid placing breakpoints incorrectly when using key shortcuts. this._editorContextMenuLineNumber = -1; let url = DebuggerView.Sources.selectedValue; let line = DebuggerView.editor.getCaretPosition().line + 1; let line = DebuggerView.editor.getCursor().line + 1; let location = { url: url, line: line }; let breakpointItem = this.getBreakpoint(location); Loading Loading @@ -1456,7 +1461,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, { _onCmdAddExpression: function(aText) { // Only add a new expression if there's no pending input. if (this.getAllStrings().indexOf("") == -1) { this.addExpression(aText || DebuggerView.editor.getSelectedText()); this.addExpression(aText || DebuggerView.editor.getSelection()); } }, Loading Loading @@ -2100,12 +2105,9 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, { let url = sourceResultsItem.instance.url; let line = lineResultsItem.instance.line; DebuggerView.setEditorLocation(url, line + 1, { noDebug: true }); let editor = DebuggerView.editor; let offset = editor.getCaretOffset(); let { start, length } = lineResultsItem.lineData.range; editor.setSelection(offset + start, offset + start + length); DebuggerView.setEditorLocation(url, line + 1, { noDebug: true }); DebuggerView.editor.extendSelection(lineResultsItem.lineData.range); }, /** Loading browser/devtools/debugger/debugger-toolbar.js +8 −17 Original line number Diff line number Diff line Loading @@ -861,10 +861,9 @@ FilterView.prototype = { */ _performLineSearch: function(aLine) { // Make sure we're actually searching for a valid line. if (!aLine) { return; if (aLine) { DebuggerView.editor.setCursor({ line: aLine - 1, ch: 0 }); } DebuggerView.editor.setCaretPosition(aLine - 1); }, /** Loading @@ -879,10 +878,8 @@ FilterView.prototype = { if (!aToken) { return; } let offset = DebuggerView.editor.find(aToken, { ignoreCase: true }); if (offset > -1) { DebuggerView.editor.setSelection(offset, offset + aToken.length) } DebuggerView.editor.find(aToken); }, /** Loading Loading @@ -1043,14 +1040,8 @@ FilterView.prototype = { // Jump to the next/previous instance of the currently searched token. if (isTokenSearch) { let [, token] = args; let methods = { selectNext: "findNext", selectPrev: "findPrevious" }; // Search for the token and select it. let offset = DebuggerView.editor[methods[actionToPerform]](true); if (offset > -1) { DebuggerView.editor.setSelection(offset, offset + token.length) } let methods = { selectNext: "findNext", selectPrev: "findPrev" }; DebuggerView.editor[methods[actionToPerform]](); return; } Loading @@ -1061,7 +1052,7 @@ FilterView.prototype = { // Modify the line number and jump to it. line += !isReturnKey ? amounts[actionToPerform] : 0; let lineCount = DebuggerView.editor.getLineCount(); let lineCount = DebuggerView.editor.lineCount(); let lineTarget = line < 1 ? 1 : line > lineCount ? lineCount : line; this._doSearch(SEARCH_LINE_FLAG, lineTarget); return; Loading @@ -1084,7 +1075,7 @@ FilterView.prototype = { _doSearch: function(aOperator = "", aText = "") { this._searchbox.focus(); this._searchbox.value = ""; // Need to clear value beforehand. Bug 779738. this._searchbox.value = aOperator + (aText || DebuggerView.editor.getSelectedText()); this._searchbox.value = aOperator + (aText || DebuggerView.editor.getSelection()); }, /** Loading browser/devtools/debugger/debugger-view.js +56 −44 Original line number Diff line number Diff line Loading @@ -28,13 +28,6 @@ const SEARCH_FUNCTION_FLAG = "@"; const SEARCH_TOKEN_FLAG = "#"; const SEARCH_LINE_FLAG = ":"; const SEARCH_VARIABLE_FLAG = "*"; const DEFAULT_EDITOR_CONFIG = { mode: SourceEditor.MODES.TEXT, readOnly: true, showLineNumbers: true, showAnnotationRuler: true, showOverviewRuler: true }; /** * Object defining the debugger view components. Loading Loading @@ -187,7 +180,7 @@ let DebuggerView = { }, /** * Initializes the SourceEditor instance. * Initializes the Editor instance. * * @param function aCallback * Called after the editor finishes initializing. Loading @@ -195,11 +188,35 @@ let DebuggerView = { _initializeEditor: function(aCallback) { dumpn("Initializing the DebuggerView editor"); this.editor = new SourceEditor(); this.editor.init(document.getElementById("editor"), DEFAULT_EDITOR_CONFIG, () => { // This needs to be more localizable: see bug 929234. let extraKeys = {}; extraKeys[(Services.appinfo.OS == "Darwin" ? "Cmd-" : "Ctrl-") + "F"] = (cm) => { DebuggerView.Filtering._doTokenSearch(); }; this.editor = new Editor({ mode: Editor.modes.text, readOnly: true, lineNumbers: true, showAnnotationRuler: true, gutters: [ "breakpoints" ], extraKeys: extraKeys, contextMenu: "sourceEditorContextMenu" }); this.editor.appendTo(document.getElementById("editor")).then(() => { this.editor.extend(DebuggerEditor); this._loadingText = L10N.getStr("loadingText"); this._onEditorLoad(aCallback); }); this.editor.on("gutterClick", (ev, line) => { if (this.editor.hasBreakpoint(line)) { this.editor.removeBreakpoint(line); } else { this.editor.addBreakpoint(line); } }); }, /** Loading @@ -219,7 +236,7 @@ let DebuggerView = { }, /** * Destroys the SourceEditor instance and also executes any necessary * Destroys the Editor instance and also executes any necessary * post-unload operations. * * @param function aCallback Loading Loading @@ -276,9 +293,9 @@ let DebuggerView = { * The source text content. */ _setEditorText: function(aTextContent = "") { this.editor.setMode(SourceEditor.MODES.TEXT); this.editor.setMode(Editor.modes.text); this.editor.setText(aTextContent); this.editor.resetUndo(); this.editor.clearHistory(); }, /** Loading @@ -294,22 +311,24 @@ let DebuggerView = { */ _setEditorMode: function(aUrl, aContentType = "", aTextContent = "") { // Avoid setting the editor mode for very large files. // Is this still necessary? See bug 929225. if (aTextContent.length >= SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) { this.editor.setMode(SourceEditor.MODES.TEXT); return void this.editor.setMode(Editor.modes.text); } // Use JS mode for files with .js and .jsm extensions. else if (SourceUtils.isJavaScript(aUrl, aContentType)) { this.editor.setMode(SourceEditor.MODES.JAVASCRIPT); if (SourceUtils.isJavaScript(aUrl, aContentType)) { return void this.editor.setMode(Editor.modes.js); } // Use HTML mode for files in which the first non whitespace character is // <, regardless of extension. else if (aTextContent.match(/^\s*</)) { this.editor.setMode(SourceEditor.MODES.HTML); } // Unknown languange, use plain text. else { this.editor.setMode(SourceEditor.MODES.TEXT); if (aTextContent.match(/^\s*</)) { return void this.editor.setMode(Editor.modes.html); } // Unknown language, use text. this.editor.setMode(Editor.modes.text); }, /** Loading Loading @@ -415,6 +434,11 @@ let DebuggerView = { let sourceItem = this.Sources.getItemByValue(aUrl); let sourceForm = sourceItem.attachment.source; // Once we change the editor location, it replaces editor's contents. // This means that the debug location information is now obsolete, so // we need to clear it. We set a new location below, in this function. this.editor.clearDebugLocation(); // Make sure the requested source client is shown in the editor, then // update the source editor's caret position and debug location. return this._setEditorSource(sourceForm, aFlags).then(() => { Loading @@ -423,35 +447,23 @@ let DebuggerView = { if (aLine < 1) { return; } if (aFlags.charOffset) { aLine += this.editor.getLineAtOffset(aFlags.charOffset); aLine += this.editor.getPosition(aFlags.charOffset).line; } if (aFlags.lineOffset) { aLine += aFlags.lineOffset; } if (!aFlags.noCaret) { this.editor.setCaretPosition(aLine - 1, aFlags.columnOffset); this.editor.setCursor({ line: aLine -1, ch: aFlags.columnOffset || 0 }); } if (!aFlags.noDebug) { this.editor.setDebugLocation(aLine - 1, aFlags.columnOffset); this.editor.setDebugLocation(aLine - 1); } }); }, /** * Gets the text in the source editor's specified line. * * @param number aLine [optional] * The line to get the text from. If unspecified, it defaults to * the current caret position. * @return string * The specified line's text. */ getEditorLineText: function(aLine) { let line = aLine || this.editor.getCaretPosition().line; let start = this.editor.getLineStart(line); let end = this.editor.getLineEnd(line); return this.editor.getText(start, end); }).then(null, console.error); }, /** Loading Loading @@ -599,9 +611,9 @@ let DebuggerView = { this.EventListeners.empty(); if (this.editor) { this.editor.setMode(SourceEditor.MODES.TEXT); this.editor.setMode(Editor.modes.text); this.editor.setText(""); this.editor.resetUndo(); this.editor.clearHistory(); this._editorSource = {}; } }, Loading browser/devtools/debugger/debugger.xul +3 −5 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ %debuggerDTD; ]> <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> <?xul-overlay href="chrome://browser/content/devtools/source-editor-overlay.xul"?> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" macanimationtype="document" Loading @@ -29,7 +28,6 @@ <script type="text/javascript" src="debugger-panes.js"/> <commandset id="editMenuCommands"/> <commandset id="sourceEditorCommands"/> <commandset id="debuggerCommands"> <command id="prettyPrintCommand" Loading Loading @@ -86,7 +84,7 @@ <popupset id="debuggerPopupset"> <menupopup id="sourceEditorContextMenu" onpopupshowing="goUpdateSourceEditorMenuItems()"> onpopupshowing="goUpdateGlobalEditMenuItems()"> <menuitem id="se-dbg-cMenu-addBreakpoint" label="&debuggerUI.seMenuBreak;" key="addBreakpointKey" Loading @@ -100,9 +98,9 @@ key="addWatchExpressionKey" command="addWatchExpressionCommand"/> <menuseparator/> <menuitem id="se-cMenu-copy"/> <menuitem id="cMenu_copy"/> <menuseparator/> <menuitem id="se-cMenu-selectAll"/> <menuitem id="cMenu_selectAll"/> <menuseparator/> <menuitem id="se-dbg-cMenu-findFile" label="&debuggerUI.searchFile;" Loading Loading
browser/devtools/debugger/debugger-controller.js +21 −33 Original line number Diff line number Diff line Loading @@ -78,15 +78,18 @@ const EVENTS = { Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/devtools/dbg-client.jsm"); let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise; Cu.import("resource:///modules/devtools/shared/event-emitter.js"); Cu.import("resource:///modules/devtools/sourceeditor/source-editor.jsm"); Cu.import("resource:///modules/devtools/BreadcrumbsWidget.jsm"); Cu.import("resource:///modules/devtools/SideMenuWidget.jsm"); Cu.import("resource:///modules/devtools/VariablesView.jsm"); Cu.import("resource:///modules/devtools/VariablesViewController.jsm"); Cu.import("resource:///modules/devtools/ViewHelpers.jsm"); const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require; const Editor = require("devtools/sourceeditor/editor"); const promise = require("sdk/core/promise"); const DebuggerEditor = require("devtools/sourceeditor/debugger.js"); XPCOMUtils.defineLazyModuleGetter(this, "Parser", "resource:///modules/devtools/Parser.jsm"); Loading Loading @@ -608,7 +611,7 @@ StackFrames.prototype = { * Handler for the thread client's resumed notification. */ _onResumed: function() { DebuggerView.editor.setDebugLocation(-1); DebuggerView.editor.clearDebugLocation(); // Prepare the watch expression evaluation string for the next pause. if (!this._isWatchExpressionsEvaluation) { Loading Loading @@ -1434,7 +1437,6 @@ EventListeners.prototype = { * Handles all the breakpoints in the current debugger. */ function Breakpoints() { this._onEditorBreakpointChange = this._onEditorBreakpointChange.bind(this); this._onEditorBreakpointAdd = this._onEditorBreakpointAdd.bind(this); this._onEditorBreakpointRemove = this._onEditorBreakpointRemove.bind(this); this.addBreakpoint = this.addBreakpoint.bind(this); Loading @@ -1457,8 +1459,8 @@ Breakpoints.prototype = { * A promise that is resolved when the breakpoints finishes initializing. */ initialize: function() { DebuggerView.editor.addEventListener( SourceEditor.EVENTS.BREAKPOINT_CHANGE, this._onEditorBreakpointChange); DebuggerView.editor.on("breakpointAdded", this._onEditorBreakpointAdd); DebuggerView.editor.on("breakpointRemoved", this._onEditorBreakpointRemove); // Initialization is synchronous, for now. return promise.resolve(null); Loading @@ -1471,34 +1473,21 @@ Breakpoints.prototype = { * A promise that is resolved when the breakpoints finishes destroying. */ destroy: function() { DebuggerView.editor.removeEventListener( SourceEditor.EVENTS.BREAKPOINT_CHANGE, this._onEditorBreakpointChange); DebuggerView.editor.off("breakpointAdded", this._onEditorBreakpointAdd); DebuggerView.editor.off("breakpointRemoved", this._onEditorBreakpointRemove); return this.removeAllBreakpoints(); }, /** * Event handler for breakpoint changes that happen in the editor. This * function syncs the breakpoints in the editor to those in the debugger. * * @param object aEvent * The SourceEditor.EVENTS.BREAKPOINT_CHANGE event object. */ _onEditorBreakpointChange: function(aEvent) { aEvent.added.forEach(this._onEditorBreakpointAdd, this); aEvent.removed.forEach(this._onEditorBreakpointRemove, this); }, /** * Event handler for new breakpoints that come from the editor. * * @param object aEditorBreakpoint * The breakpoint object coming from the editor. * @param number aLine * Line number where breakpoint was set. */ _onEditorBreakpointAdd: function(aEditorBreakpoint) { _onEditorBreakpointAdd: function(_, aLine) { let url = DebuggerView.Sources.selectedValue; let line = aEditorBreakpoint.line + 1; let location = { url: url, line: line }; let location = { url: url, line: aLine + 1 }; // Initialize the breakpoint, but don't update the editor, since this // callback is invoked because a breakpoint was added in the editor itself. Loading @@ -1511,26 +1500,25 @@ Breakpoints.prototype = { DebuggerView.editor.addBreakpoint(aBreakpointClient.location.line - 1); } // Notify that we've shown a breakpoint in the source editor. window.emit(EVENTS.BREAKPOINT_SHOWN, aEditorBreakpoint); window.emit(EVENTS.BREAKPOINT_SHOWN); }); }, /** * Event handler for breakpoints that are removed from the editor. * * @param object aEditorBreakpoint * The breakpoint object that was removed from the editor. * @param number aLine * Line number where breakpoint was removed. */ _onEditorBreakpointRemove: function(aEditorBreakpoint) { _onEditorBreakpointRemove: function(_, aLine) { let url = DebuggerView.Sources.selectedValue; let line = aEditorBreakpoint.line + 1; let location = { url: url, line: line }; let location = { url: url, line: aLine + 1 }; // Destroy the breakpoint, but don't update the editor, since this callback // is invoked because a breakpoint was removed from the editor itself. this.removeBreakpoint(location, { noEditorUpdate: true }).then(() => { // Notify that we've hidden a breakpoint in the source editor. window.emit(EVENTS.BREAKPOINT_HIDDEN, aEditorBreakpoint); window.emit(EVENTS.BREAKPOINT_HIDDEN); }); }, Loading Loading @@ -1644,7 +1632,7 @@ Breakpoints.prototype = { // after the target navigated). Note that this will get out of sync // if the source text contents change. let line = aBreakpointClient.location.line - 1; aBreakpointClient.text = DebuggerView.getEditorLineText(line).trim(); aBreakpointClient.text = DebuggerView.editor.getText(line).trim(); // Show the breakpoint in the editor and breakpoints pane, and resolve. this._showBreakpoint(aBreakpointClient, aOptions); Loading
browser/devtools/debugger/debugger-panes.js +28 −26 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ function SourcesView() { this.togglePrettyPrint = this.togglePrettyPrint.bind(this); this._onEditorLoad = this._onEditorLoad.bind(this); this._onEditorUnload = this._onEditorUnload.bind(this); this._onEditorSelection = this._onEditorSelection.bind(this); this._onEditorCursorActivity = this._onEditorCursorActivity.bind(this); this._onEditorContextMenu = this._onEditorContextMenu.bind(this); this._onSourceSelect = this._onSourceSelect.bind(this); this._onSourceClick = this._onSourceClick.bind(this); Loading Loading @@ -479,7 +479,12 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { */ _hideConditionalPopup: function() { this._cbPanel.hidden = true; // Sometimes this._cbPanel doesn't have hidePopup method which doesn't // break anything but simply outputs an exception to the console. if (this._cbPanel.hidePopup) { this._cbPanel.hidePopup(); } }, /** Loading Loading @@ -645,30 +650,30 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { * The load listener for the source editor. */ _onEditorLoad: function(aName, aEditor) { aEditor.addEventListener(SourceEditor.EVENTS.SELECTION, this._onEditorSelection, false); aEditor.addEventListener(SourceEditor.EVENTS.CONTEXT_MENU, this._onEditorContextMenu, false); aEditor.on("cursorActivity", this._onEditorCursorActivity); aEditor.on("contextMenu", this._onEditorContextMenu); }, /** * The unload listener for the source editor. */ _onEditorUnload: function(aName, aEditor) { aEditor.removeEventListener(SourceEditor.EVENTS.SELECTION, this._onEditorSelection, false); aEditor.removeEventListener(SourceEditor.EVENTS.CONTEXT_MENU, this._onEditorContextMenu, false); aEditor.off("cursorActivity", this._onEditorCursorActivity); aEditor.off("contextMenu", this._onEditorContextMenu); }, /** * The selection listener for the source editor. */ _onEditorSelection: function(e) { let { start, end } = e.newValue; _onEditorCursorActivity: function(e) { let editor = DebuggerView.editor; let start = editor.getCursor("start").line + 1; let end = editor.getCursor().line + 1; let url = this.selectedValue; let lineStart = DebuggerView.editor.getLineAtOffset(start) + 1; let lineEnd = DebuggerView.editor.getLineAtOffset(end) + 1; let location = { url: url, line: lineStart }; if (this.getBreakpoint(location) && lineStart == lineEnd) { let location = { url: url, line: start }; if (this.getBreakpoint(location) && start == end) { this.highlightBreakpoint(location, { noEditorUpdate: true }); } else { this.unhighlightBreakpoint(); Loading @@ -679,9 +684,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { * The context menu listener for the source editor. */ _onEditorContextMenu: function({ x, y }) { let offset = DebuggerView.editor.getOffsetAtLocation(x, y); let line = DebuggerView.editor.getLineAtOffset(offset); this._editorContextMenuLineNumber = line; this._editorContextMenuLineNumber = DebuggerView.editor.getPositionFromCoords(x, y).line; }, /** Loading Loading @@ -869,13 +872,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { // If this command was executed via the context menu, add the breakpoint // on the currently hovered line in the source editor. if (this._editorContextMenuLineNumber >= 0) { DebuggerView.editor.setCaretPosition(this._editorContextMenuLineNumber); DebuggerView.editor.setCursor({ line: this._editorContextMenuLineNumber, ch: 0 }); } // Avoid placing breakpoints incorrectly when using key shortcuts. this._editorContextMenuLineNumber = -1; let url = DebuggerView.Sources.selectedValue; let line = DebuggerView.editor.getCaretPosition().line + 1; let line = DebuggerView.editor.getCursor().line + 1; let location = { url: url, line: line }; let breakpointItem = this.getBreakpoint(location); Loading @@ -896,13 +900,14 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, { // If this command was executed via the context menu, add the breakpoint // on the currently hovered line in the source editor. if (this._editorContextMenuLineNumber >= 0) { DebuggerView.editor.setCaretPosition(this._editorContextMenuLineNumber); DebuggerView.editor.setCursor({ line: this._editorContextMenuLineNumber, ch: 0 }); } // Avoid placing breakpoints incorrectly when using key shortcuts. this._editorContextMenuLineNumber = -1; let url = DebuggerView.Sources.selectedValue; let line = DebuggerView.editor.getCaretPosition().line + 1; let line = DebuggerView.editor.getCursor().line + 1; let location = { url: url, line: line }; let breakpointItem = this.getBreakpoint(location); Loading Loading @@ -1456,7 +1461,7 @@ WatchExpressionsView.prototype = Heritage.extend(WidgetMethods, { _onCmdAddExpression: function(aText) { // Only add a new expression if there's no pending input. if (this.getAllStrings().indexOf("") == -1) { this.addExpression(aText || DebuggerView.editor.getSelectedText()); this.addExpression(aText || DebuggerView.editor.getSelection()); } }, Loading Loading @@ -2100,12 +2105,9 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, { let url = sourceResultsItem.instance.url; let line = lineResultsItem.instance.line; DebuggerView.setEditorLocation(url, line + 1, { noDebug: true }); let editor = DebuggerView.editor; let offset = editor.getCaretOffset(); let { start, length } = lineResultsItem.lineData.range; editor.setSelection(offset + start, offset + start + length); DebuggerView.setEditorLocation(url, line + 1, { noDebug: true }); DebuggerView.editor.extendSelection(lineResultsItem.lineData.range); }, /** Loading
browser/devtools/debugger/debugger-toolbar.js +8 −17 Original line number Diff line number Diff line Loading @@ -861,10 +861,9 @@ FilterView.prototype = { */ _performLineSearch: function(aLine) { // Make sure we're actually searching for a valid line. if (!aLine) { return; if (aLine) { DebuggerView.editor.setCursor({ line: aLine - 1, ch: 0 }); } DebuggerView.editor.setCaretPosition(aLine - 1); }, /** Loading @@ -879,10 +878,8 @@ FilterView.prototype = { if (!aToken) { return; } let offset = DebuggerView.editor.find(aToken, { ignoreCase: true }); if (offset > -1) { DebuggerView.editor.setSelection(offset, offset + aToken.length) } DebuggerView.editor.find(aToken); }, /** Loading Loading @@ -1043,14 +1040,8 @@ FilterView.prototype = { // Jump to the next/previous instance of the currently searched token. if (isTokenSearch) { let [, token] = args; let methods = { selectNext: "findNext", selectPrev: "findPrevious" }; // Search for the token and select it. let offset = DebuggerView.editor[methods[actionToPerform]](true); if (offset > -1) { DebuggerView.editor.setSelection(offset, offset + token.length) } let methods = { selectNext: "findNext", selectPrev: "findPrev" }; DebuggerView.editor[methods[actionToPerform]](); return; } Loading @@ -1061,7 +1052,7 @@ FilterView.prototype = { // Modify the line number and jump to it. line += !isReturnKey ? amounts[actionToPerform] : 0; let lineCount = DebuggerView.editor.getLineCount(); let lineCount = DebuggerView.editor.lineCount(); let lineTarget = line < 1 ? 1 : line > lineCount ? lineCount : line; this._doSearch(SEARCH_LINE_FLAG, lineTarget); return; Loading @@ -1084,7 +1075,7 @@ FilterView.prototype = { _doSearch: function(aOperator = "", aText = "") { this._searchbox.focus(); this._searchbox.value = ""; // Need to clear value beforehand. Bug 779738. this._searchbox.value = aOperator + (aText || DebuggerView.editor.getSelectedText()); this._searchbox.value = aOperator + (aText || DebuggerView.editor.getSelection()); }, /** Loading
browser/devtools/debugger/debugger-view.js +56 −44 Original line number Diff line number Diff line Loading @@ -28,13 +28,6 @@ const SEARCH_FUNCTION_FLAG = "@"; const SEARCH_TOKEN_FLAG = "#"; const SEARCH_LINE_FLAG = ":"; const SEARCH_VARIABLE_FLAG = "*"; const DEFAULT_EDITOR_CONFIG = { mode: SourceEditor.MODES.TEXT, readOnly: true, showLineNumbers: true, showAnnotationRuler: true, showOverviewRuler: true }; /** * Object defining the debugger view components. Loading Loading @@ -187,7 +180,7 @@ let DebuggerView = { }, /** * Initializes the SourceEditor instance. * Initializes the Editor instance. * * @param function aCallback * Called after the editor finishes initializing. Loading @@ -195,11 +188,35 @@ let DebuggerView = { _initializeEditor: function(aCallback) { dumpn("Initializing the DebuggerView editor"); this.editor = new SourceEditor(); this.editor.init(document.getElementById("editor"), DEFAULT_EDITOR_CONFIG, () => { // This needs to be more localizable: see bug 929234. let extraKeys = {}; extraKeys[(Services.appinfo.OS == "Darwin" ? "Cmd-" : "Ctrl-") + "F"] = (cm) => { DebuggerView.Filtering._doTokenSearch(); }; this.editor = new Editor({ mode: Editor.modes.text, readOnly: true, lineNumbers: true, showAnnotationRuler: true, gutters: [ "breakpoints" ], extraKeys: extraKeys, contextMenu: "sourceEditorContextMenu" }); this.editor.appendTo(document.getElementById("editor")).then(() => { this.editor.extend(DebuggerEditor); this._loadingText = L10N.getStr("loadingText"); this._onEditorLoad(aCallback); }); this.editor.on("gutterClick", (ev, line) => { if (this.editor.hasBreakpoint(line)) { this.editor.removeBreakpoint(line); } else { this.editor.addBreakpoint(line); } }); }, /** Loading @@ -219,7 +236,7 @@ let DebuggerView = { }, /** * Destroys the SourceEditor instance and also executes any necessary * Destroys the Editor instance and also executes any necessary * post-unload operations. * * @param function aCallback Loading Loading @@ -276,9 +293,9 @@ let DebuggerView = { * The source text content. */ _setEditorText: function(aTextContent = "") { this.editor.setMode(SourceEditor.MODES.TEXT); this.editor.setMode(Editor.modes.text); this.editor.setText(aTextContent); this.editor.resetUndo(); this.editor.clearHistory(); }, /** Loading @@ -294,22 +311,24 @@ let DebuggerView = { */ _setEditorMode: function(aUrl, aContentType = "", aTextContent = "") { // Avoid setting the editor mode for very large files. // Is this still necessary? See bug 929225. if (aTextContent.length >= SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) { this.editor.setMode(SourceEditor.MODES.TEXT); return void this.editor.setMode(Editor.modes.text); } // Use JS mode for files with .js and .jsm extensions. else if (SourceUtils.isJavaScript(aUrl, aContentType)) { this.editor.setMode(SourceEditor.MODES.JAVASCRIPT); if (SourceUtils.isJavaScript(aUrl, aContentType)) { return void this.editor.setMode(Editor.modes.js); } // Use HTML mode for files in which the first non whitespace character is // <, regardless of extension. else if (aTextContent.match(/^\s*</)) { this.editor.setMode(SourceEditor.MODES.HTML); } // Unknown languange, use plain text. else { this.editor.setMode(SourceEditor.MODES.TEXT); if (aTextContent.match(/^\s*</)) { return void this.editor.setMode(Editor.modes.html); } // Unknown language, use text. this.editor.setMode(Editor.modes.text); }, /** Loading Loading @@ -415,6 +434,11 @@ let DebuggerView = { let sourceItem = this.Sources.getItemByValue(aUrl); let sourceForm = sourceItem.attachment.source; // Once we change the editor location, it replaces editor's contents. // This means that the debug location information is now obsolete, so // we need to clear it. We set a new location below, in this function. this.editor.clearDebugLocation(); // Make sure the requested source client is shown in the editor, then // update the source editor's caret position and debug location. return this._setEditorSource(sourceForm, aFlags).then(() => { Loading @@ -423,35 +447,23 @@ let DebuggerView = { if (aLine < 1) { return; } if (aFlags.charOffset) { aLine += this.editor.getLineAtOffset(aFlags.charOffset); aLine += this.editor.getPosition(aFlags.charOffset).line; } if (aFlags.lineOffset) { aLine += aFlags.lineOffset; } if (!aFlags.noCaret) { this.editor.setCaretPosition(aLine - 1, aFlags.columnOffset); this.editor.setCursor({ line: aLine -1, ch: aFlags.columnOffset || 0 }); } if (!aFlags.noDebug) { this.editor.setDebugLocation(aLine - 1, aFlags.columnOffset); this.editor.setDebugLocation(aLine - 1); } }); }, /** * Gets the text in the source editor's specified line. * * @param number aLine [optional] * The line to get the text from. If unspecified, it defaults to * the current caret position. * @return string * The specified line's text. */ getEditorLineText: function(aLine) { let line = aLine || this.editor.getCaretPosition().line; let start = this.editor.getLineStart(line); let end = this.editor.getLineEnd(line); return this.editor.getText(start, end); }).then(null, console.error); }, /** Loading Loading @@ -599,9 +611,9 @@ let DebuggerView = { this.EventListeners.empty(); if (this.editor) { this.editor.setMode(SourceEditor.MODES.TEXT); this.editor.setMode(Editor.modes.text); this.editor.setText(""); this.editor.resetUndo(); this.editor.clearHistory(); this._editorSource = {}; } }, Loading
browser/devtools/debugger/debugger.xul +3 −5 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ %debuggerDTD; ]> <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> <?xul-overlay href="chrome://browser/content/devtools/source-editor-overlay.xul"?> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" macanimationtype="document" Loading @@ -29,7 +28,6 @@ <script type="text/javascript" src="debugger-panes.js"/> <commandset id="editMenuCommands"/> <commandset id="sourceEditorCommands"/> <commandset id="debuggerCommands"> <command id="prettyPrintCommand" Loading Loading @@ -86,7 +84,7 @@ <popupset id="debuggerPopupset"> <menupopup id="sourceEditorContextMenu" onpopupshowing="goUpdateSourceEditorMenuItems()"> onpopupshowing="goUpdateGlobalEditMenuItems()"> <menuitem id="se-dbg-cMenu-addBreakpoint" label="&debuggerUI.seMenuBreak;" key="addBreakpointKey" Loading @@ -100,9 +98,9 @@ key="addWatchExpressionKey" command="addWatchExpressionCommand"/> <menuseparator/> <menuitem id="se-cMenu-copy"/> <menuitem id="cMenu_copy"/> <menuseparator/> <menuitem id="se-cMenu-selectAll"/> <menuitem id="cMenu_selectAll"/> <menuseparator/> <menuitem id="se-dbg-cMenu-findFile" label="&debuggerUI.searchFile;" Loading