Bug 886170 - Intermittent browser_dbg_bug723071_editor-breakpoints-highlight.js | The currently selected source is incorrect (0). - Got http://example.com/browser/browser/devtools/debugger/test/test-script-switching-02.js, expected ... and 11 more, r=past

This commit is contained in:
Victor Porof 2013-06-26 23:35:39 +03:00
Родитель 242aa2924d
Коммит d7ac370bf8
8 изменённых файлов: 153 добавлений и 246 удалений

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

@ -213,7 +213,6 @@ let DebuggerController = {
DebuggerView._handleTabNavigation(); DebuggerView._handleTabNavigation();
// Discard all the old sources. // Discard all the old sources.
DebuggerController.SourceScripts.clearCache();
DebuggerController.Parser.clearCache(); DebuggerController.Parser.clearCache();
SourceUtils.clearCache(); SourceUtils.clearCache();
return; return;
@ -821,11 +820,11 @@ StackFrames.prototype = {
// having the whole watch expressions array throw because of a single // having the whole watch expressions array throw because of a single
// faulty expression, simply convert it to a string describing the error. // faulty expression, simply convert it to a string describing the error.
// There's no other information necessary to be offered in such cases. // There's no other information necessary to be offered in such cases.
let sanitizedExpressions = list.map(function(str) { let sanitizedExpressions = list.map((aString) => {
// Reflect.parse throws when it encounters a syntax error. // Reflect.parse throws when it encounters a syntax error.
try { try {
Parser.reflectionAPI.parse(str); Parser.reflectionAPI.parse(aString);
return str; // Watch expression can be executed safely. return aString; // Watch expression can be executed safely.
} catch (e) { } catch (e) {
return "\"" + e.name + ": " + e.message + "\""; // Syntax error. return "\"" + e.name + ": " + e.message + "\""; // Syntax error.
} }
@ -835,13 +834,13 @@ StackFrames.prototype = {
this.syncedWatchExpressions = this.syncedWatchExpressions =
this.currentWatchExpressions = this.currentWatchExpressions =
"[" + "[" +
sanitizedExpressions.map(function(str) sanitizedExpressions.map((aString) =>
"eval(\"" + "eval(\"" +
"try {" + "try {" +
// Make sure all quotes are escaped in the expression's syntax, // Make sure all quotes are escaped in the expression's syntax,
// and add a newline after the statement to avoid comments // and add a newline after the statement to avoid comments
// breaking the code integrity inside the eval block. // breaking the code integrity inside the eval block.
str.replace(/"/g, "\\$&") + "\" + " + "'\\n'" + " + \"" + aString.replace(/"/g, "\\$&") + "\" + " + "'\\n'" + " + \"" +
"} catch (e) {" + "} catch (e) {" +
"e.name + ': ' + e.message;" + // TODO: Bug 812765, 812764. "e.name + ': ' + e.message;" + // TODO: Bug 812765, 812764.
"}" + "}" +
@ -862,13 +861,9 @@ StackFrames.prototype = {
* source script cache. * source script cache.
*/ */
function SourceScripts() { function SourceScripts() {
this._cache = new Map(); // Can't use a WeakMap because keys are strings.
this._onNewGlobal = this._onNewGlobal.bind(this); this._onNewGlobal = this._onNewGlobal.bind(this);
this._onNewSource = this._onNewSource.bind(this); this._onNewSource = this._onNewSource.bind(this);
this._onSourcesAdded = this._onSourcesAdded.bind(this); this._onSourcesAdded = this._onSourcesAdded.bind(this);
this._onFetch = this._onFetch.bind(this);
this._onTimeout = this._onTimeout.bind(this);
this._onFinished = this._onFinished.bind(this);
} }
SourceScripts.prototype = { SourceScripts.prototype = {
@ -944,7 +939,7 @@ SourceScripts.prototype = {
// ..or the first entry if there's none selected yet after a while // ..or the first entry if there's none selected yet after a while
else { else {
window.clearTimeout(this._newSourceTimeout); window.clearTimeout(this._newSourceTimeout);
this._newSourceTimeout = window.setTimeout(function() { this._newSourceTimeout = window.setTimeout(() => {
// If after a certain delay the preferred source still wasn't received, // If after a certain delay the preferred source still wasn't received,
// just give up on waiting and display the first entry. // just give up on waiting and display the first entry.
if (!container.selectedValue) { if (!container.selectedValue) {
@ -1009,163 +1004,102 @@ SourceScripts.prototype = {
* *
* @param object aSource * @param object aSource
* The source object coming from the active thread. * The source object coming from the active thread.
* @param function aCallback * @param function aOnTimeout [optional]
* Function called after the source text has been loaded. * Function called when the source text takes a long time to fetch,
* @param function aTimeout * but not necessarily failing. Long fetch times don't cause the
* Function called when the source text takes too long to fetch. * rejection of the returned promise.
* @param number aDelay [optional]
* The amount of time it takes to consider a source slow to fetch.
* If unspecified, it defaults to a predefined value.
* @return object
* A promise that is resolved after the source text has been fetched.
*/ */
getText: function(aSource, aCallback, aTimeout) { getTextForSource: function(aSource, aOnTimeout, aDelay = FETCH_SOURCE_RESPONSE_DELAY) {
// If already loaded, return the source text immediately. // Fetch the source text only once.
if (aSource.loaded) { if (aSource._fetched) {
aCallback(aSource); return aSource._fetched;
return;
} }
// If the source text takes too long to fetch, invoke a timeout to let deferred = Promise.defer();
// avoid blocking any operations. aSource._fetched = deferred.promise;
if (aTimeout) {
var fetchTimeout = window.setTimeout(() => { // If the source text takes a long time to fetch, invoke a callback.
aSource._fetchingTimedOut = true; if (aOnTimeout) {
aTimeout(aSource); var fetchTimeout = window.setTimeout(() => aOnTimeout(aSource), aDelay);
}, FETCH_SOURCE_RESPONSE_DELAY);
} }
// Get the source text from the active thread. // Get the source text from the active thread.
this.activeThread.source(aSource).source((aResponse) => { this.activeThread.source(aSource).source((aResponse) => {
if (aTimeout) { if (aOnTimeout) {
window.clearTimeout(fetchTimeout); window.clearTimeout(fetchTimeout);
} }
if (aResponse.error) { if (aResponse.error) {
Cu.reportError("Error loading: " + aSource.url + "\n" + aResponse.message); deferred.reject([aSource, aResponse.message]);
return void aCallback(aSource); } else {
deferred.resolve([aSource, aResponse.source]);
} }
aSource.loaded = true;
aSource.text = aResponse.source;
aCallback(aSource);
}); });
},
/** return deferred.promise;
* Gets all the fetched sources.
*
* @return array
* An array containing [url, text] entries for the fetched sources.
*/
getCache: function() {
let sources = [];
for (let source of this._cache) {
sources.push(source);
}
return sources.sort(([first], [second]) => first > second);
},
/**
* Clears all the fetched sources from cache.
*/
clearCache: function() {
this._cache.clear();
}, },
/** /**
* Starts fetching all the sources, silently. * Starts fetching all the sources, silently.
* *
* @param array aUrls * @param array aUrls
* The urls for the sources to fetch. * The urls for the sources to fetch. If fetching a source's text
* @param object aCallbacks [optional] * takes too long, it will be discarded.
* An object containing the callback functions to invoke: * @return object
* - onFetch: optional, called after each source is fetched * A promise that is resolved after source texts have been fetched.
* - onTimeout: optional, called when a source takes too long to fetch
* - onFinished: called when all the sources are fetched
*/ */
fetchSources: function(aUrls, aCallbacks = {}) { getTextForSources: function(aUrls) {
this._fetchQueue = new Set(); let deferred = Promise.defer();
this._fetchCallbacks = aCallbacks; let pending = new Set(aUrls);
let fetched = [];
// Add each new source which needs to be fetched in a queue. // Can't use Promise.all, because if one fetch operation is rejected, then
// everything is considered rejected, thus no other subsequent source will
// be getting fetched. We don't want that. Something like Q's allSettled
// would work like a charm here.
// Try to fetch as many sources as possible.
for (let url of aUrls) { for (let url of aUrls) {
if (!this._cache.has(url)) { let sourceItem = DebuggerView.Sources.getItemByValue(url);
this._fetchQueue.add(url); let sourceClient = sourceItem.attachment.source;
this.getTextForSource(sourceClient, onTimeout).then(onFetch, onError);
}
/* Called if fetching a source takes too long. */
function onTimeout(aSource) {
onError([aSource]);
}
/* Called if fetching a source finishes successfully. */
function onFetch([aSource, aText]) {
// If fetching the source has previously timed out, discard it this time.
if (!pending.has(aSource.url)) {
return;
}
pending.delete(aSource.url);
fetched.push([aSource.url, aText]);
maybeFinish();
}
/* Called if fetching a source failed because of an error. */
function onError([aSource, aError]) {
pending.delete(aSource.url);
maybeFinish();
}
/* Called every time something interesting happens while fetching sources. */
function maybeFinish() {
if (pending.size == 0) {
deferred.resolve(fetched.sort(([aFirst], [aSecond]) => aFirst > aSecond));
} }
} }
// If all the sources were already fetched, don't do anything special. return deferred.promise;
if (this._fetchQueue.size == 0) { }
this._onFinished();
return;
}
// Start fetching each new source.
for (let url of this._fetchQueue) {
let sourceItem = DebuggerView.Sources.getItemByValue(url);
let sourceObject = sourceItem.attachment.source;
this.getText(sourceObject, this._onFetch, this._onTimeout);
}
},
/**
* Called when a source has been fetched via fetchSources().
*
* @param object aSource
* The source object coming from the active thread.
*/
_onFetch: function(aSource) {
// Remember the source in a cache so we don't have to fetch it again.
this._cache.set(aSource.url, aSource.text);
// Fetch completed before timeout, remove the source from the fetch queue.
this._fetchQueue.delete(aSource.url);
// If this fetch was eventually completed at some point after a timeout,
// don't call any subsequent event listeners.
if (aSource._fetchingTimedOut) {
return;
}
// Invoke the source fetch callback if provided via fetchSources();
if (this._fetchCallbacks.onFetch) {
this._fetchCallbacks.onFetch(aSource);
}
// Check if all sources were fetched and stored in the cache.
if (this._fetchQueue.size == 0) {
this._onFinished();
}
},
/**
* Called when a source's text takes too long to fetch via fetchSources().
*
* @param object aSource
* The source object coming from the active thread.
*/
_onTimeout: function(aSource) {
// Remove the source from the fetch queue.
this._fetchQueue.delete(aSource.url);
// Invoke the source timeout callback if provided via fetchSources();
if (this._fetchCallbacks.onTimeout) {
this._fetchCallbacks.onTimeout(aSource);
}
// Check if the remaining sources were fetched and stored in the cache.
if (this._fetchQueue.size == 0) {
this._onFinished();
}
},
/**
* Called when all the sources have been fetched.
*/
_onFinished: function() {
// Invoke the finish callback if provided via fetchSources();
if (this._fetchCallbacks.onFinished) {
this._fetchCallbacks.onFinished();
}
},
_cache: null,
_fetchQueue: null,
_fetchCallbacks: null
}; };
/** /**

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

@ -1636,16 +1636,17 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
_startSearch: function(aQuery) { _startSearch: function(aQuery) {
this._searchedToken = aQuery; this._searchedToken = aQuery;
DebuggerController.SourceScripts.fetchSources(DebuggerView.Sources.values, { // Start fetching as many sources as possible, then perform the search.
onFinished: this._performGlobalSearch DebuggerController.SourceScripts
}); .getTextForSources(DebuggerView.Sources.values)
.then(this._performGlobalSearch);
}, },
/** /**
* Finds string matches in all the sources stored in the controller's cache, * Finds string matches in all the sources stored in the controller's cache,
* and groups them by location and line number. * and groups them by location and line number.
*/ */
_performGlobalSearch: function() { _performGlobalSearch: function(aSources) {
// Get the currently searched token from the filtering input. // Get the currently searched token from the filtering input.
let token = this._searchedToken; let token = this._searchedToken;
@ -1662,9 +1663,8 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
// Prepare the results map, containing search details for each line. // Prepare the results map, containing search details for each line.
let globalResults = new GlobalResults(); let globalResults = new GlobalResults();
let sourcesCache = DebuggerController.SourceScripts.getCache();
for (let [location, contents] of sourcesCache) { for (let [location, contents] of aSources) {
// Verify that the search token is found anywhere in the source. // Verify that the search token is found anywhere in the source.
if (!contents.toLowerCase().contains(lowerCaseToken)) { if (!contents.toLowerCase().contains(lowerCaseToken)) {
continue; continue;
@ -1684,7 +1684,7 @@ GlobalSearchView.prototype = Heritage.extend(WidgetMethods, {
let lineNumber = i; let lineNumber = i;
let lineResults = new LineResults(); let lineResults = new LineResults();
lowerCaseLine.split(lowerCaseToken).reduce(function(prev, curr, index, {length}) { lowerCaseLine.split(lowerCaseToken).reduce((prev, curr, index, { length }) => {
let prevLength = prev.length; let prevLength = prev.length;
let currLength = curr.length; let currLength = curr.length;
let unmatched = line.substr(prevLength, currLength); let unmatched = line.substr(prevLength, currLength);

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

@ -292,7 +292,7 @@ OptionsView.prototype = {
window.removeEventListener("Debugger:OptionsPopupHidden", reconfigure, false); window.removeEventListener("Debugger:OptionsPopupHidden", reconfigure, false);
// The popup panel needs more time to hide after triggering onpopuphidden. // The popup panel needs more time to hide after triggering onpopuphidden.
window.setTimeout(function() { window.setTimeout(() => {
DebuggerController.reconfigureThread(pref); DebuggerController.reconfigureThread(pref);
}, POPUP_HIDDEN_DELAY); }, POPUP_HIDDEN_DELAY);
} }
@ -1446,16 +1446,17 @@ FilteredFunctionsView.prototype = Heritage.extend(ResultsPanelContainer.prototyp
_startSearch: function(aQuery) { _startSearch: function(aQuery) {
this._searchedToken = aQuery; this._searchedToken = aQuery;
DebuggerController.SourceScripts.fetchSources(DebuggerView.Sources.values, { // Start fetching as many sources as possible, then perform the search.
onFinished: this._performFunctionSearch DebuggerController.SourceScripts
}); .getTextForSources(DebuggerView.Sources.values)
.then(this._performFunctionSearch);
}, },
/** /**
* Finds function matches in all the sources stored in the cache, and groups * Finds function matches in all the sources stored in the cache, and groups
* them by location and line number. * them by location and line number.
*/ */
_performFunctionSearch: function() { _performFunctionSearch: function(aSources) {
// Get the currently searched token from the filtering input. // Get the currently searched token from the filtering input.
// Continue parsing even if the searched token is an empty string, to // Continue parsing even if the searched token is an empty string, to
// cache the syntax tree nodes generated by the reflection API. // cache the syntax tree nodes generated by the reflection API.
@ -1463,19 +1464,18 @@ FilteredFunctionsView.prototype = Heritage.extend(ResultsPanelContainer.prototyp
// Make sure the currently displayed source is parsed first. Once the // Make sure the currently displayed source is parsed first. Once the
// maximum allowed number of resutls are found, parsing will be halted. // maximum allowed number of resutls are found, parsing will be halted.
let sourcesCache = DebuggerController.SourceScripts.getCache();
let currentUrl = DebuggerView.Sources.selectedValue; let currentUrl = DebuggerView.Sources.selectedValue;
sourcesCache.sort(function([sourceUrl]) sourceUrl == currentUrl ? -1 : 1); aSources.sort(([sourceUrl]) => sourceUrl == currentUrl ? -1 : 1);
// If not searching for a specific function, only parse the displayed source. // If not searching for a specific function, only parse the displayed source.
if (!token) { if (!token) {
sourcesCache.splice(1); aSources.splice(1);
} }
// Prepare the results array, containing search details for each source. // Prepare the results array, containing search details for each source.
let searchResults = []; let searchResults = [];
for (let [location, contents] of sourcesCache) { for (let [location, contents] of aSources) {
let parserMethods = DebuggerController.Parser.get(location, contents); let parserMethods = DebuggerController.Parser.get(location, contents);
let sourceResults = parserMethods.getNamedFunctionDefinitions(token); let sourceResults = parserMethods.getNamedFunctionDefinitions(token);

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

@ -208,6 +208,12 @@ let DebuggerView = {
* The source text content. * The source text content.
*/ */
setEditorMode: function(aUrl, aContentType = "", aTextContent = "") { setEditorMode: function(aUrl, aContentType = "", aTextContent = "") {
// Avoid setting the editor mode for very large files.
if (aTextContent.length >= SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
this.editor.setMode(SourceEditor.MODES.TEXT);
return;
}
if (aContentType) { if (aContentType) {
if (/javascript/.test(aContentType)) { if (/javascript/.test(aContentType)) {
this.editor.setMode(SourceEditor.MODES.JAVASCRIPT); this.editor.setMode(SourceEditor.MODES.JAVASCRIPT);
@ -243,39 +249,23 @@ let DebuggerView = {
} }
dumpn("Setting the DebuggerView editor source: " + aSource.url + dumpn("Setting the DebuggerView editor source: " + aSource.url +
", loaded: " + aSource.loaded); ", fetched: " + !!aSource._fetched);
this.editor.setMode(SourceEditor.MODES.TEXT); this.editor.setMode(SourceEditor.MODES.TEXT);
this.editor.setText(L10N.getStr("loadingText")); this.editor.setText(L10N.getStr("loadingText"));
this.editor.resetUndo(); this.editor.resetUndo();
this._editorSource = aSource; this._editorSource = aSource;
// If the source is not loaded, display a placeholder text. DebuggerController.SourceScripts.getTextForSource(aSource).then(([, aText]) => {
if (!aSource.loaded) {
DebuggerController.SourceScripts.getText(aSource, set.bind(this));
}
// If the source is already loaded, display it immediately.
else {
set.call(this, aSource);
}
// Updates the source editor's displayed text.
// @param object aSource
function set(aSource) {
// Avoid setting an unexpected source. This may happen when fast switching // Avoid setting an unexpected source. This may happen when fast switching
// between sources that haven't been fetched yet. // between sources that haven't been fetched yet.
if (this._editorSource != aSource) { if (this._editorSource != aSource) {
return; return;
} }
// Avoid setting the editor mode for very large files. this.editor.setText(aText);
if (aSource.text.length < SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
this.setEditorMode(aSource.url, aSource.contentType, aSource.text);
} else {
this.editor.setMode(SourceEditor.MODES.TEXT);
}
this.editor.setText(aSource.text);
this.editor.resetUndo(); this.editor.resetUndo();
this.setEditorMode(aSource.url, aSource.contentType, aText);
// Update the editor's current caret and debug locations given by the // Update the editor's current caret and debug locations given by the
// currently active frame in the stack, if there's one available. // currently active frame in the stack, if there's one available.
@ -287,7 +277,13 @@ let DebuggerView = {
// Notify that we've shown a source file. // Notify that we've shown a source file.
window.dispatchEvent(document, "Debugger:SourceShown", aSource); window.dispatchEvent(document, "Debugger:SourceShown", aSource);
} },
([, aError]) => {
// Rejected. TODO: Bug 884484.
let msg = "Error loading: " + aSource.url + "\n" + aError;
dumpn(msg);
Cu.reportError(msg);
});
}, },
/** /**

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

@ -26,7 +26,10 @@ function test()
gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js"; gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js";
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) { gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let url = aEvent.detail.url; let { url, loaded, text } = aEvent.detail;
info("Shown source: " + url + ", loaded: " + loaded + ", text:\n" + text);
info("Shown label: " + gSources.selectedLabel);
info("All labels:" + gSources.labels);
if (url.indexOf("-02") != -1) { if (url.indexOf("-02") != -1) {
gDebugger.removeEventListener(aEvent.type, _onEvent); gDebugger.removeEventListener(aEvent.type, _onEvent);
performTestWhileNotPaused(); performTestWhileNotPaused();
@ -35,11 +38,11 @@ function test()
}); });
function addBreakpoints(callback) { function addBreakpoints(callback) {
gPane.addBreakpoint({url: gSources.values[0], line: 5}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[0].value, line: 5}, function(cl, err) {
gPane.addBreakpoint({url: gSources.values[1], line: 6}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 6}, function(cl, err) {
gPane.addBreakpoint({url: gSources.values[1], line: 7}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 7}, function(cl, err) {
gPane.addBreakpoint({url: gSources.values[1], line: 8}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 8}, function(cl, err) {
gPane.addBreakpoint({url: gSources.values[1], line: 9}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 9}, function(cl, err) {
callback(); callback();
}); });
}); });

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

@ -26,7 +26,10 @@ function test()
gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js"; gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js";
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) { gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let url = aEvent.detail.url; let { url, loaded, text } = aEvent.detail;
info("Shown source: " + url + ", loaded: " + loaded + ", text:\n" + text);
info("Shown label: " + gSources.selectedLabel);
info("All labels:" + gSources.labels);
if (url.indexOf("-02") != -1) { if (url.indexOf("-02") != -1) {
gDebugger.removeEventListener(aEvent.type, _onEvent); gDebugger.removeEventListener(aEvent.type, _onEvent);
performTest(); performTest();
@ -37,15 +40,15 @@ function test()
function performTest() function performTest()
{ {
initialChecks(); initialChecks();
gPane.addBreakpoint({url: gSources.values[0], line: 5}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[0].value, line: 5}, function(cl, err) {
initialChecks(); initialChecks();
gPane.addBreakpoint({url: gSources.values[1], line: 6}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 6}, function(cl, err) {
initialChecks(); initialChecks();
gPane.addBreakpoint({url: gSources.values[1], line: 7}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 7}, function(cl, err) {
initialChecks(); initialChecks();
gPane.addBreakpoint({url: gSources.values[1], line: 8}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 8}, function(cl, err) {
initialChecks(); initialChecks();
gPane.addBreakpoint({url: gSources.values[1], line: 9}, function(cl, err) { gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 9}, function(cl, err) {
initialChecks(); initialChecks();
testHighlight1(); testHighlight1();
}); });
@ -56,7 +59,7 @@ function test()
} }
function initialChecks() { function initialChecks() {
is(gSources.selectedValue, gSources.values[1], is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (0)."); "The currently selected source is incorrect (0).");
is(gEditor.getCaretPosition().line, 0, is(gEditor.getCaretPosition().line, 0,
"The editor caret line was incorrect (0)."); "The editor caret line was incorrect (0).");
@ -65,10 +68,10 @@ function test()
} }
function testHighlight1() { function testHighlight1() {
gSources.highlightBreakpoint(gSources.values[0], 5); gSources.highlightBreakpoint(gSources.orderedItems[0].value, 5);
checkHighlight(gSources.values[0], 5); checkHighlight(gSources.orderedItems[0].value, 5);
is(gSources.selectedValue, gSources.values[1], is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (1)."); "The currently selected source is incorrect (1).");
is(gEditor.getCaretPosition().line, 0, is(gEditor.getCaretPosition().line, 0,
@ -87,10 +90,10 @@ function test()
} }
function testHighlight2() { function testHighlight2() {
gSources.highlightBreakpoint(gSources.values[1], 6); gSources.highlightBreakpoint(gSources.orderedItems[1].value, 6);
checkHighlight(gSources.values[1], 6); checkHighlight(gSources.orderedItems[1].value, 6);
is(gSources.selectedValue, gSources.values[0], is(gSources.selectedValue, gSources.orderedItems[0].value,
"The currently selected source is incorrect (2)."); "The currently selected source is incorrect (2).");
is(gEditor.getCaretPosition().line, 4, is(gEditor.getCaretPosition().line, 4,
@ -109,10 +112,10 @@ function test()
} }
function testHighlight3() { function testHighlight3() {
gSources.highlightBreakpoint(gSources.values[1], 7); gSources.highlightBreakpoint(gSources.orderedItems[1].value, 7);
checkHighlight(gSources.values[1], 7); checkHighlight(gSources.orderedItems[1].value, 7);
is(gSources.selectedValue, gSources.values[1], is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (3)."); "The currently selected source is incorrect (3).");
is(gEditor.getCaretPosition().line, 5, is(gEditor.getCaretPosition().line, 5,
@ -131,10 +134,10 @@ function test()
} }
function testHighlight4() { function testHighlight4() {
gSources.highlightBreakpoint(gSources.values[1], 8); gSources.highlightBreakpoint(gSources.orderedItems[1].value, 8);
checkHighlight(gSources.values[1], 8); checkHighlight(gSources.orderedItems[1].value, 8);
is(gSources.selectedValue, gSources.values[1], is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (4)."); "The currently selected source is incorrect (4).");
is(gEditor.getCaretPosition().line, 6, is(gEditor.getCaretPosition().line, 6,
@ -153,10 +156,10 @@ function test()
} }
function testHighlight5() { function testHighlight5() {
gSources.highlightBreakpoint(gSources.values[1], 9); gSources.highlightBreakpoint(gSources.orderedItems[1].value, 9);
checkHighlight(gSources.values[1], 9); checkHighlight(gSources.orderedItems[1].value, 9);
is(gSources.selectedValue, gSources.values[1], is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (5)."); "The currently selected source is incorrect (5).");
is(gEditor.getCaretPosition().line, 7, is(gEditor.getCaretPosition().line, 7,

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

@ -123,9 +123,6 @@ function testLocationChange()
is(gSearchView._splitter.hidden, true, is(gSearchView._splitter.hidden, true,
"The global search pane splitter shouldn't be visible after a page navigation."); "The global search pane splitter shouldn't be visible after a page navigation.");
is(gDebugger.DebuggerController.SourceScripts.getCache().length, 0,
"The scripts sources cache for global searching should be cleared after a page navigation.")
closeDebuggerAndFinish(); closeDebuggerAndFinish();
}); });
}); });

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

@ -76,8 +76,6 @@ function testSourcesCache()
ok(gSources.values.sort()[2].contains("test-function-search-03.js"), ok(gSources.values.sort()[2].contains("test-function-search-03.js"),
"The third source value appears to be correct."); "The third source value appears to be correct.");
is(gControllerSources.getCache().length, 0,
"The sources cache should be empty when debugger starts.");
is(gDebugger.SourceUtils._labelsCache.size, TOTAL_SOURCES, is(gDebugger.SourceUtils._labelsCache.size, TOTAL_SOURCES,
"There should be " + TOTAL_SOURCES + " labels cached"); "There should be " + TOTAL_SOURCES + " labels cached");
is(gDebugger.SourceUtils._groupsCache.size, TOTAL_SOURCES, is(gDebugger.SourceUtils._groupsCache.size, TOTAL_SOURCES,
@ -97,30 +95,9 @@ function fetchSources(callback) {
let fetches = 0; let fetches = 0;
let timeouts = 0; let timeouts = 0;
gControllerSources.fetchSources(gSources.values, { gControllerSources.getTextForSources(gSources.values).then((aSources) => {
onFetch: function(aSource) { testCacheIntegrity(aSources);
info("Fetched: " + aSource.url); callback();
fetches++;
},
onTimeout: function(aSource) {
info("Timed out: " + aSource.url);
timeouts++;
},
onFinished: function() {
info("Finished...");
ok(fetches > 0,
"At least one source should have been fetched.");
is(fetches + timeouts, TOTAL_SOURCES,
"The correct number of sources have been either fetched or timed out.");
let cache = gControllerSources.getCache();
is(cache.length, fetches,
"The sources cache should have exactly " + fetches + " sources cached.");
testCacheIntegrity();
callback();
}
}); });
} }
@ -161,17 +138,14 @@ function testStateAfterReload() {
"There should be " + TOTAL_SOURCES + " groups cached after reload."); "There should be " + TOTAL_SOURCES + " groups cached after reload.");
} }
function testCacheIntegrity() { function testCacheIntegrity(aCache) {
let cache = gControllerSources.getCache(); for (let source of aCache) {
isnot(cache.length, 0, let [url, contents] = source;
"The sources cache should not be empty at this point."); let index = aCache.indexOf(source);
for (let source of cache) { ok(url.contains("test-function-search-0" + (index + 1)),
let index = cache.indexOf(source);
ok(source[0].contains("test-function-search-0" + (index + 1)),
"Found a source url cached correctly (" + index + ")"); "Found a source url cached correctly (" + index + ")");
ok(source[1].contains( ok(contents.contains(
["First source!", "Second source!", "Third source!"][index]), ["First source!", "Second source!", "Third source!"][index]),
"Found a source's text contents cached correctly (" + index + ")"); "Found a source's text contents cached correctly (" + index + ")");