Bug 1233927 - Switching between large JS files in debugger is slow. r=jlong

Changes the way that source files are loaded in the editor. Previously,
source text and mode were set on the existing editor document.

Now, source files are their own CodeMirror Documents, so when it comes time
to showing them in the editor, it's just a matter of swapping one
document for another.

Notes:
+ The DebuggerView now has a _setEditorDocument method for showing a
source document
+ The Editor now has support for creating documents and replacing
documents.

MozReview-Commit-ID: HrkiHrsJPOB
This commit is contained in:
Jason Laster 2016-03-28 13:12:28 -07:00
Родитель 17f2b6e204
Коммит 80243acca9
3 изменённых файлов: 91 добавлений и 10 удалений

Просмотреть файл

@ -82,6 +82,7 @@ var DebuggerView = {
this._initializeVariablesView(); this._initializeVariablesView();
this._editorSource = {}; this._editorSource = {};
this._editorDocuments = {};
document.title = L10N.getStr("DebuggerWindowTitle"); document.title = L10N.getStr("DebuggerWindowTitle");
@ -416,14 +417,28 @@ var DebuggerView = {
* Sets the currently displayed text contents in the source editor. * Sets the currently displayed text contents in the source editor.
* This resets the mode and undo stack. * This resets the mode and undo stack.
* *
* @param string documentKey
* Key to get the correct editor document
*
* @param string aTextContent * @param string aTextContent
* The source text content. * The source text content.
*
* @param boolean shouldUpdateText
Forces a text and mode reset
*/ */
_setEditorText: function(aTextContent = "") { _setEditorText: function(documentKey, aTextContent = "", shouldUpdateText = false) {
this.editor.setMode(Editor.modes.text); const isNew = this._setEditorDocument(documentKey);
this.editor.setText(aTextContent);
this.editor.clearDebugLocation(); this.editor.clearDebugLocation();
this.editor.clearHistory(); this.editor.clearHistory();
this.editor.setCursor({ line: 0, ch: 0});
this.editor.removeBreakpoints();
// Only set editor's text and mode if it is a new document
if (isNew || shouldUpdateText) {
this.editor.setMode(Editor.modes.text);
this.editor.setText(aTextContent);
}
}, },
/** /**
@ -453,6 +468,29 @@ var DebuggerView = {
this.editor.setMode(Editor.modes.text); this.editor.setMode(Editor.modes.text);
}, },
/**
* Sets the editor's displayed document.
* If there isn't a document for the source, create one
*
* @param string key - key used to access the editor document cache
*
* @return boolean isNew - was the document just created
*/
_setEditorDocument: function(key) {
let isNew;
if (!this._editorDocuments[key]) {
isNew = true;
this._editorDocuments[key] = this.editor.createDocument();
} else {
isNew = false;
}
const doc = this._editorDocuments[key];
this.editor.replaceDocument(doc);
return isNew;
},
renderBlackBoxed: function(source) { renderBlackBoxed: function(source) {
this._renderSourceText( this._renderSourceText(
source, source,
@ -478,6 +516,7 @@ var DebuggerView = {
_renderSourceText: function(source, textInfo, opts = {}) { _renderSourceText: function(source, textInfo, opts = {}) {
const selectedSource = queries.getSelectedSource(this.controller.getState()); const selectedSource = queries.getSelectedSource(this.controller.getState());
// Exit early if we're attempting to render an unselected source
if (!selectedSource || selectedSource.actor !== source.actor) { if (!selectedSource || selectedSource.actor !== source.actor) {
return; return;
} }
@ -497,12 +536,12 @@ var DebuggerView = {
// TODO: bug 1228866, we need to update `_editorSource` here but // TODO: bug 1228866, we need to update `_editorSource` here but
// still make the editor be updated when the full text comes // still make the editor be updated when the full text comes
// through somehow. // through somehow.
this._setEditorText(L10N.getStr("loadingText")); this._setEditorText('loading', L10N.getStr("loadingText"));
return; return;
} }
else if (textInfo.error) { else if (textInfo.error) {
let msg = L10N.getFormatStr("errorLoadingText2", textInfo.error); let msg = L10N.getFormatStr("errorLoadingText2", textInfo.error);
this._setEditorText(msg); this._setEditorText('error', msg);
Cu.reportError(msg); Cu.reportError(msg);
dumpn(msg); dumpn(msg);
@ -529,14 +568,18 @@ var DebuggerView = {
return; return;
} }
let { text, contentType } = textInfo;
let shouldUpdateText = this._editorSource.prettyPrinted != source.isPrettyPrinted;
this._setEditorText(source.actor, text, shouldUpdateText);
this._editorSource.actor = source.actor; this._editorSource.actor = source.actor;
this._editorSource.prettyPrinted = source.isPrettyPrinted; this._editorSource.prettyPrinted = source.isPrettyPrinted;
this._editorSource.blackboxed = source.isBlackBoxed; this._editorSource.blackboxed = source.isBlackBoxed;
this._editorSource.prettyPrinted = source.isPrettyPrinted;
let { text, contentType } = textInfo;
this._setEditorText(text);
this._setEditorMode(source.url, contentType, text); this._setEditorMode(source.url, contentType, text);
this.updateEditorBreakpoints(source); this.updateEditorBreakpoints(source);
setTimeout(() => { setTimeout(() => {
window.emit(EVENTS.SOURCE_SHOWN, source); window.emit(EVENTS.SOURCE_SHOWN, source);
}, 0); }, 0);
@ -788,7 +831,6 @@ var DebuggerView = {
*/ */
handleTabNavigation: function() { handleTabNavigation: function() {
dumpn("Handling tab navigation in the DebuggerView"); dumpn("Handling tab navigation in the DebuggerView");
this.Filtering.clearSearch(); this.Filtering.clearSearch();
this.GlobalSearch.clearView(); this.GlobalSearch.clearView();
this.StackFrames.empty(); this.StackFrames.empty();
@ -801,6 +843,7 @@ var DebuggerView = {
this.editor.setText(""); this.editor.setText("");
this.editor.clearHistory(); this.editor.clearHistory();
this._editorSource = {}; this._editorSource = {};
this._editorDocuments = {};
} }
}, },

Просмотреть файл

@ -173,9 +173,29 @@ function addBreakpoint(ctx, line, cond) {
return deferred.promise; return deferred.promise;
} }
/**
* Helps reset the debugger's breakpoint state
* - removes the breakpoints in the editor
* - cleares the debugger's breakpoint state
*
* Note, does not *actually* remove a source's breakpoints.
* The canonical state is kept in the app state.
*
*/
function removeBreakpoints(ctx) {
let { ed, cm } = ctx;
let meta = dbginfo.get(ed);
if (meta.breakpoints != null) {
meta.breakpoints = {};
}
cm.doc.iter((line) => { removeBreakpoint(ctx, line) });
}
/** /**
* Removes a visual breakpoint from a specified line and * Removes a visual breakpoint from a specified line and
* makes Editor to emit a breakpointRemoved event. * makes Editor emit a breakpointRemoved event.
*/ */
function removeBreakpoint(ctx, line) { function removeBreakpoint(ctx, line) {
if (!hasBreakpoint(ctx, line)) { if (!hasBreakpoint(ctx, line)) {
@ -303,7 +323,7 @@ function findPrev(ctx, query) {
[ [
initialize, hasBreakpoint, addBreakpoint, removeBreakpoint, moveBreakpoint, initialize, hasBreakpoint, addBreakpoint, removeBreakpoint, moveBreakpoint,
setBreakpointCondition, removeBreakpointCondition, getBreakpoints, setBreakpointCondition, removeBreakpointCondition, getBreakpoints, removeBreakpoints,
setDebugLocation, getDebugLocation, clearDebugLocation, find, findNext, setDebugLocation, getDebugLocation, clearDebugLocation, find, findNext,
findPrev findPrev
].forEach(func => module.exports[func.name] = func); ].forEach(func => module.exports[func.name] = func);

Просмотреть файл

@ -241,6 +241,7 @@ Editor.prototype = {
container: null, container: null,
version: null, version: null,
config: null, config: null,
Doc: null,
/** /**
* Appends the current Editor instance to the element specified by * Appends the current Editor instance to the element specified by
@ -302,6 +303,7 @@ Editor.prototype = {
// context menus won't work). // context menus won't work).
cm = win.CodeMirror(win.document.body, this.config); cm = win.CodeMirror(win.document.body, this.config);
this.Doc = win.CodeMirror.Doc;
// Disable APZ for source editors. It currently causes the line numbers to // Disable APZ for source editors. It currently causes the line numbers to
// "tear off" and swim around on top of the content. Bug 1160601 tracks // "tear off" and swim around on top of the content. Bug 1160601 tracks
@ -488,6 +490,22 @@ Editor.prototype = {
Services.scriptloader.loadSubScript(url, win, "utf8"); Services.scriptloader.loadSubScript(url, win, "utf8");
}, },
/**
* Creates a CodeMirror Document
* @returns CodeMirror.Doc
*/
createDocument: function() {
return new this.Doc("");
},
/**
* Replaces the current document with a new source document
*/
replaceDocument: function(doc) {
let cm = editors.get(this);
cm.swapDoc(doc);
},
/** /**
* Changes the value of a currently used highlighting mode. * Changes the value of a currently used highlighting mode.
* See Editor.modes for the list of all supported modes. * See Editor.modes for the list of all supported modes.