mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 762160 - Find Implementors of a function in the Debugger, r=past
This commit is contained in:
parent
56f6beb13a
commit
c3b98c48f6
@ -13,7 +13,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
||||
"resource://gre/modules/devtools/dbg-server.jsm");
|
||||
|
@ -38,8 +38,8 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/VariablesView.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
"Reflect", "resource://gre/modules/reflect.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Parser",
|
||||
"resource:///modules/devtools/Parser.jsm");
|
||||
|
||||
/**
|
||||
* Object defining the debugger controller components.
|
||||
@ -231,6 +231,11 @@ let DebuggerController = {
|
||||
_onTabNavigated: function DC__onTabNavigated(aType, aPacket) {
|
||||
if (aPacket.state == "start") {
|
||||
DebuggerView._handleTabNavigation();
|
||||
|
||||
// Discard all the old sources.
|
||||
DebuggerController.SourceScripts.clearCache();
|
||||
DebuggerController.Parser.clearCache();
|
||||
SourceUtils.clearCache();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -955,9 +960,9 @@ StackFrames.prototype = {
|
||||
// faulty expression, simply convert it to a string describing the error.
|
||||
// There's no other information necessary to be offered in such cases.
|
||||
let sanitizedExpressions = list.map(function(str) {
|
||||
// Reflect.parse throws when encounters a syntax error.
|
||||
// Reflect.parse throws when it encounters a syntax error.
|
||||
try {
|
||||
Reflect.parse(str);
|
||||
Parser.reflectionAPI.parse(str);
|
||||
return str; // Watch expression can be executed safely.
|
||||
} catch (e) {
|
||||
return "\"" + e.name + ": " + e.message + "\""; // Syntax error.
|
||||
@ -1009,9 +1014,13 @@ StackFrames.prototype = {
|
||||
* source script cache.
|
||||
*/
|
||||
function SourceScripts() {
|
||||
this._cache = new Map(); // Can't use a WeakMap because keys are strings.
|
||||
this._onNewSource = this._onNewSource.bind(this);
|
||||
this._onNewGlobal = this._onNewGlobal.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 = {
|
||||
@ -1154,35 +1163,161 @@ SourceScripts.prototype = {
|
||||
* The source object coming from the active thread.
|
||||
* @param function aCallback
|
||||
* Function called after the source text has been loaded.
|
||||
* @param function aOnTimeout
|
||||
* @param function aTimeout
|
||||
* Function called when the source text takes too long to fetch.
|
||||
*/
|
||||
getText: function SS_getText(aSource, aCallback, aOnTimeout) {
|
||||
getText: function SS_getText(aSource, aCallback, aTimeout) {
|
||||
// If already loaded, return the source text immediately.
|
||||
if (aSource.loaded) {
|
||||
aCallback(aSource.url, aSource.text);
|
||||
aCallback(aSource);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the source text takes too long to fetch, invoke a timeout to
|
||||
// avoid blocking any operations.
|
||||
if (aOnTimeout) {
|
||||
var fetchTimeout = window.setTimeout(aOnTimeout, FETCH_SOURCE_RESPONSE_DELAY);
|
||||
if (aTimeout) {
|
||||
var fetchTimeout = window.setTimeout(() => {
|
||||
aSource._fetchingTimedOut = true;
|
||||
aTimeout(aSource);
|
||||
}, FETCH_SOURCE_RESPONSE_DELAY);
|
||||
}
|
||||
|
||||
// Get the source text from the active thread.
|
||||
this.activeThread.source(aSource).source(function(aResponse) {
|
||||
window.clearTimeout(fetchTimeout);
|
||||
|
||||
this.activeThread.source(aSource).source((aResponse) => {
|
||||
if (aTimeout) {
|
||||
window.clearTimeout(fetchTimeout);
|
||||
}
|
||||
if (aResponse.error) {
|
||||
Cu.reportError("Error loading: " + aSource.url + "\n" + aResponse.message);
|
||||
return void aCallback(aSource.url, "", aResponse.error);
|
||||
return void aCallback(aSource);
|
||||
}
|
||||
aSource.loaded = true;
|
||||
aSource.text = aResponse.source;
|
||||
aCallback(aSource.url, aResponse.source);
|
||||
aCallback(aSource);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the fetched sources.
|
||||
*
|
||||
* @return array
|
||||
* An array containing [url, text] entries for the fetched sources.
|
||||
*/
|
||||
getCache: function SS_getCache() {
|
||||
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 SS_clearCache() {
|
||||
this._cache = new Map();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts fetching all the sources, silently.
|
||||
*
|
||||
* @param array aUrls
|
||||
* The urls for the sources to fetch.
|
||||
* @param object aCallbacks [optional]
|
||||
* An object containing the callback functions to invoke:
|
||||
* - onFetch: optional, called after each source is fetched
|
||||
* - onTimeout: optional, called when a source takes too long to fetch
|
||||
* - onFinished: called when all the sources are fetched
|
||||
*/
|
||||
fetchSources: function SS_fetchSources(aUrls, aCallbacks = {}) {
|
||||
this._fetchQueue = new Set();
|
||||
this._fetchCallbacks = aCallbacks;
|
||||
|
||||
// Add each new source which needs to be fetched in a queue.
|
||||
for (let url of aUrls) {
|
||||
if (!this._cache.has(url)) {
|
||||
this._fetchQueue.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
// If all the sources were already fetched, don't do anything special.
|
||||
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 SS__onFetch(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 SS__onTimeout(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 SS__onFinished() {
|
||||
// Invoke the finish callback if provided via fetchSources();
|
||||
if (this._fetchCallbacks.onFinished) {
|
||||
this._fetchCallbacks.onFinished();
|
||||
}
|
||||
},
|
||||
|
||||
_cache: null,
|
||||
_fetchQueue: null,
|
||||
_fetchCallbacks: null
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1637,6 +1772,7 @@ XPCOMUtils.defineLazyGetter(window, "_isChromeDebugger", function() {
|
||||
* Preliminary setup for the DebuggerController object.
|
||||
*/
|
||||
DebuggerController.initialize();
|
||||
DebuggerController.Parser = new Parser();
|
||||
DebuggerController.ThreadState = new ThreadState();
|
||||
DebuggerController.StackFrames = new StackFrames();
|
||||
DebuggerController.SourceScripts = new SourceScripts();
|
||||
|
@ -1513,11 +1513,8 @@ create({ constructor: WatchExpressionsView, proto: MenuContainer.prototype }, {
|
||||
function GlobalSearchView() {
|
||||
dumpn("GlobalSearchView was instantiated");
|
||||
|
||||
this._cache = new Map();
|
||||
this._startSearch = this._startSearch.bind(this);
|
||||
this._onFetchSourceFinished = this._onFetchSourceFinished.bind(this);
|
||||
this._onFetchSourceTimeout = this._onFetchSourceTimeout.bind(this);
|
||||
this._onFetchSourcesFinished = this._onFetchSourcesFinished.bind(this);
|
||||
this._performGlobalSearch = this._performGlobalSearch.bind(this);
|
||||
this._createItemView = this._createItemView.bind(this);
|
||||
this._onScroll = this._onScroll.bind(this);
|
||||
this._onHeaderClick = this._onHeaderClick.bind(this);
|
||||
@ -1575,14 +1572,6 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
window.dispatchEvent(document, "Debugger:GlobalSearch:ViewCleared");
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears all the fetched sources from cache.
|
||||
*/
|
||||
clearCache: function DVGS_clearCache() {
|
||||
this._cache = new Map();
|
||||
window.dispatchEvent(document, "Debugger:GlobalSearch:CacheCleared");
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the next found match in the source editor.
|
||||
*/
|
||||
@ -1631,7 +1620,7 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
this.performSearch(aQuery);
|
||||
return;
|
||||
}
|
||||
let delay = Math.max(GLOBAL_SEARCH_ACTION_MAX_DELAY / aQuery.length);
|
||||
let delay = Math.max(GLOBAL_SEARCH_ACTION_MAX_DELAY / aQuery.length, 0);
|
||||
|
||||
window.clearTimeout(this._searchTimeout);
|
||||
this._searchFunction = this._startSearch.bind(this, aQuery);
|
||||
@ -1657,98 +1646,16 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
* The string to search for.
|
||||
*/
|
||||
_startSearch: function DVGS__startSearch(aQuery) {
|
||||
let locations = DebuggerView.Sources.values;
|
||||
this._sourcesCount = locations.length;
|
||||
this._searchedToken = aQuery;
|
||||
|
||||
this._fetchSources(locations, {
|
||||
onFetch: this._onFetchSourceFinished,
|
||||
onTimeout: this._onFetchSourceTimeout,
|
||||
onFinished: this._onFetchSourcesFinished
|
||||
DebuggerController.SourceScripts.fetchSources(DebuggerView.Sources.values, {
|
||||
onFinished: this._performGlobalSearch
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts fetching all the sources, silently.
|
||||
*
|
||||
* @param array aLocations
|
||||
* The locations for the sources to fetch.
|
||||
* @param object aCallbacks
|
||||
* An object containing the callback functions to invoke:
|
||||
* - onFetch: called after each source is fetched
|
||||
* - onTimeout: called when a source's text takes too long to fetch
|
||||
* - onFinished: called if all the sources were already fetched
|
||||
*/
|
||||
_fetchSources:
|
||||
function DVGS__fetchSources(aLocations, { onFetch, onTimeout, onFinished }) {
|
||||
// If all the sources were already fetched, then don't do anything.
|
||||
if (this._cache.size == aLocations.length) {
|
||||
onFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch each new source.
|
||||
for (let location of aLocations) {
|
||||
if (this._cache.has(location)) {
|
||||
continue;
|
||||
}
|
||||
let sourceItem = DebuggerView.Sources.getItemByValue(location);
|
||||
let sourceObject = sourceItem.attachment.source;
|
||||
DebuggerController.SourceScripts.getText(sourceObject, onFetch, onTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a source has been fetched.
|
||||
*
|
||||
* @param string aLocation
|
||||
* The location of the source.
|
||||
* @param string aContents
|
||||
* The text contents of the source.
|
||||
*/
|
||||
_onFetchSourceFinished: function DVGS__onFetchSourceFinished(aLocation, aContents, aError) {
|
||||
if (aError) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember the source in a cache so we don't have to fetch it again.
|
||||
this._cache.set(aLocation, aContents);
|
||||
|
||||
// Check if all sources were fetched and stored in the cache.
|
||||
if (this._cache.size == this._sourcesCount) {
|
||||
this._onFetchSourcesFinished();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a source's text takes too long to fetch.
|
||||
*/
|
||||
_onFetchSourceTimeout: function DVGS__onFetchSourceTimeout() {
|
||||
// Remove the source from the load queue.
|
||||
this._sourcesCount--;
|
||||
|
||||
// Check if the remaining sources were fetched and stored in the cache.
|
||||
if (this._cache.size == this._sourcesCount) {
|
||||
this._onFetchSourcesFinished();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when all the sources have been fetched.
|
||||
*/
|
||||
_onFetchSourcesFinished: function DVGS__onFetchSourcesFinished() {
|
||||
// At least one source needs to be present to perform a global search.
|
||||
if (!this._sourcesCount) {
|
||||
return;
|
||||
}
|
||||
// All sources are fetched and stored in the cache, we can start searching.
|
||||
this._performGlobalSearch();
|
||||
this._sourcesCount = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds string matches in all the sources stored in the cache, and groups
|
||||
* them by location and line number.
|
||||
* Finds string matches in all the sources stored in the controller's cache,
|
||||
* and groups them by location and line number.
|
||||
*/
|
||||
_performGlobalSearch: function DVGS__performGlobalSearch() {
|
||||
// Get the currently searched token from the filtering input.
|
||||
@ -1767,8 +1674,9 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
|
||||
// Prepare the results map, containing search details for each line.
|
||||
let globalResults = new GlobalResults();
|
||||
let sourcesCache = DebuggerController.SourceScripts.getCache();
|
||||
|
||||
for (let [location, contents] of this._cache) {
|
||||
for (let [location, contents] of sourcesCache) {
|
||||
// Verify that the search token is found anywhere in the source.
|
||||
if (!contents.toLowerCase().contains(lowerCaseToken)) {
|
||||
continue;
|
||||
@ -2002,9 +1910,7 @@ create({ constructor: GlobalSearchView, proto: MenuContainer.prototype }, {
|
||||
_forceExpandResults: false,
|
||||
_searchTimeout: null,
|
||||
_searchFunction: null,
|
||||
_searchedToken: "",
|
||||
_sourcesCount: -1,
|
||||
_cache: null
|
||||
_searchedToken: ""
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -683,6 +683,8 @@ FilterView.prototype = {
|
||||
this._searchboxHelpPanel = document.getElementById("searchbox-help-panel");
|
||||
this._globalOperatorButton = document.getElementById("global-operator-button");
|
||||
this._globalOperatorLabel = document.getElementById("global-operator-label");
|
||||
this._functionOperatorButton = document.getElementById("function-operator-button");
|
||||
this._functionOperatorLabel = document.getElementById("function-operator-label");
|
||||
this._tokenOperatorButton = document.getElementById("token-operator-button");
|
||||
this._tokenOperatorLabel = document.getElementById("token-operator-label");
|
||||
this._lineOperatorButton = document.getElementById("line-operator-button");
|
||||
@ -692,6 +694,7 @@ FilterView.prototype = {
|
||||
|
||||
this._fileSearchKey = LayoutHelpers.prettyKey(document.getElementById("fileSearchKey"), true);
|
||||
this._globalSearchKey = LayoutHelpers.prettyKey(document.getElementById("globalSearchKey"), true);
|
||||
this._filteredFunctionsKey = LayoutHelpers.prettyKey(document.getElementById("functionSearchKey"), true);
|
||||
this._tokenSearchKey = LayoutHelpers.prettyKey(document.getElementById("tokenSearchKey"), true);
|
||||
this._lineSearchKey = LayoutHelpers.prettyKey(document.getElementById("lineSearchKey"), true);
|
||||
this._variableSearchKey = LayoutHelpers.prettyKey(document.getElementById("variableSearchKey"), true);
|
||||
@ -703,12 +706,15 @@ FilterView.prototype = {
|
||||
this._searchbox.addEventListener("blur", this._onBlur, false);
|
||||
|
||||
this._globalOperatorButton.setAttribute("label", SEARCH_GLOBAL_FLAG);
|
||||
this._functionOperatorButton.setAttribute("label", SEARCH_FUNCTION_FLAG);
|
||||
this._tokenOperatorButton.setAttribute("label", SEARCH_TOKEN_FLAG);
|
||||
this._lineOperatorButton.setAttribute("label", SEARCH_LINE_FLAG);
|
||||
this._variableOperatorButton.setAttribute("label", SEARCH_VARIABLE_FLAG);
|
||||
|
||||
this._globalOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelGlobal", [this._globalSearchKey]));
|
||||
this._functionOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelFunction", [this._filteredFunctionsKey]));
|
||||
this._tokenOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelToken", [this._tokenSearchKey]));
|
||||
this._lineOperatorLabel.setAttribute("value",
|
||||
@ -755,22 +761,29 @@ FilterView.prototype = {
|
||||
this._target = aView;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the target container to be currently filtered.
|
||||
* @return object
|
||||
*/
|
||||
get target() this._target,
|
||||
|
||||
/**
|
||||
* Gets the entered file, line and token entered in the searchbox.
|
||||
* @return array
|
||||
*/
|
||||
get searchboxInfo() {
|
||||
let file, line, token, isGlobal, isVariable;
|
||||
let operator, file, line, token;
|
||||
|
||||
let rawValue = this._searchbox.value;
|
||||
let rawLength = rawValue.length;
|
||||
let globalFlagIndex = rawValue.indexOf(SEARCH_GLOBAL_FLAG);
|
||||
let functionFlagIndex = rawValue.indexOf(SEARCH_FUNCTION_FLAG);
|
||||
let variableFlagIndex = rawValue.indexOf(SEARCH_VARIABLE_FLAG);
|
||||
let lineFlagIndex = rawValue.lastIndexOf(SEARCH_LINE_FLAG);
|
||||
let tokenFlagIndex = rawValue.lastIndexOf(SEARCH_TOKEN_FLAG);
|
||||
|
||||
// This is not a global or variable search, allow file or line flags.
|
||||
if (globalFlagIndex != 0 && variableFlagIndex != 0) {
|
||||
// This is not a global, function or variable search, allow file/line flags.
|
||||
if (globalFlagIndex != 0 && functionFlagIndex != 0 && variableFlagIndex != 0) {
|
||||
let fileEnd = lineFlagIndex != -1
|
||||
? lineFlagIndex
|
||||
: tokenFlagIndex != -1 ? tokenFlagIndex : rawLength;
|
||||
@ -779,49 +792,59 @@ FilterView.prototype = {
|
||||
? tokenFlagIndex
|
||||
: rawLength;
|
||||
|
||||
operator = "";
|
||||
file = rawValue.slice(0, fileEnd);
|
||||
line = ~~(rawValue.slice(fileEnd + 1, lineEnd)) || 0;
|
||||
token = rawValue.slice(lineEnd + 1);
|
||||
isGlobal = false;
|
||||
isVariable = false;
|
||||
}
|
||||
// Global searches dissalow the use of file or line flags.
|
||||
else if (globalFlagIndex == 0) {
|
||||
operator = SEARCH_GLOBAL_FLAG;
|
||||
file = "";
|
||||
line = 0;
|
||||
token = rawValue.slice(1);
|
||||
}
|
||||
// Function searches dissalow the use of file or line flags.
|
||||
else if (functionFlagIndex == 0) {
|
||||
operator = SEARCH_FUNCTION_FLAG;
|
||||
file = "";
|
||||
line = 0;
|
||||
token = rawValue.slice(1);
|
||||
isGlobal = true;
|
||||
isVariable = false;
|
||||
}
|
||||
// Variable searches dissalow the use of file or line flags.
|
||||
else if (variableFlagIndex == 0) {
|
||||
operator = SEARCH_VARIABLE_FLAG;
|
||||
file = "";
|
||||
line = 0;
|
||||
token = rawValue.slice(1);
|
||||
isGlobal = false;
|
||||
isVariable = true;
|
||||
}
|
||||
|
||||
return [file, line, token, isGlobal, isVariable];
|
||||
return [operator, file, line, token];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current searched operator.
|
||||
* @return string
|
||||
*/
|
||||
get currentOperator() this.searchboxInfo[0],
|
||||
|
||||
/**
|
||||
* Returns the currently searched file.
|
||||
* @return string
|
||||
*/
|
||||
get searchedFile() this.searchboxInfo[0],
|
||||
get searchedFile() this.searchboxInfo[1],
|
||||
|
||||
/**
|
||||
* Returns the currently searched line.
|
||||
* @return number
|
||||
*/
|
||||
get searchedLine() this.searchboxInfo[1],
|
||||
get searchedLine() this.searchboxInfo[2],
|
||||
|
||||
/**
|
||||
* Returns the currently searched token.
|
||||
* @return string
|
||||
*/
|
||||
get searchedToken() this.searchboxInfo[2],
|
||||
get searchedToken() this.searchboxInfo[3],
|
||||
|
||||
/**
|
||||
* Clears the text from the searchbox and resets any changed view.
|
||||
@ -955,25 +978,35 @@ FilterView.prototype = {
|
||||
*/
|
||||
_onSearch: function DVF__onScriptsSearch() {
|
||||
this._searchboxHelpPanel.hidePopup();
|
||||
let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
|
||||
let [operator, file, line, token] = this.searchboxInfo;
|
||||
|
||||
// If this is a global search, schedule it for when the user stops typing,
|
||||
// or hide the corresponding pane otherwise.
|
||||
if (isGlobal) {
|
||||
if (operator == SEARCH_GLOBAL_FLAG) {
|
||||
DebuggerView.GlobalSearch.scheduleSearch(token);
|
||||
this._prevSearchedToken = token;
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a function search, schedule it for when the user stops typing,
|
||||
// or hide the corresponding panel otherwise.
|
||||
if (operator == SEARCH_FUNCTION_FLAG) {
|
||||
DebuggerView.FilteredFunctions.scheduleSearch(token);
|
||||
this._prevSearchedToken = token;
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a variable search, defer the action to the corresponding
|
||||
// variables view instance.
|
||||
if (isVariable) {
|
||||
if (operator == SEARCH_VARIABLE_FLAG) {
|
||||
DebuggerView.Variables.scheduleSearch(token);
|
||||
this._prevSearchedToken = token;
|
||||
return;
|
||||
}
|
||||
|
||||
DebuggerView.GlobalSearch.clearView();
|
||||
DebuggerView.FilteredFunctions.clearView();
|
||||
|
||||
this._performFileSearch(file);
|
||||
this._performLineSearch(line);
|
||||
this._performTokenSearch(token);
|
||||
@ -986,18 +1019,20 @@ FilterView.prototype = {
|
||||
// This attribute is not implemented in Gecko at this time, see bug 680830.
|
||||
e.char = String.fromCharCode(e.charCode);
|
||||
|
||||
let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
|
||||
let isFileSearch, isLineSearch, isDifferentToken, isReturnKey;
|
||||
let [operator, file, line, token] = this.searchboxInfo;
|
||||
let isGlobal = operator == SEARCH_GLOBAL_FLAG;
|
||||
let isFunction = operator == SEARCH_FUNCTION_FLAG;
|
||||
let isVariable = operator == SEARCH_VARIABLE_FLAG;
|
||||
let action = -1;
|
||||
|
||||
if (file && !line && !token) {
|
||||
isFileSearch = true;
|
||||
var isFileSearch = true;
|
||||
}
|
||||
if (line && !token) {
|
||||
isLineSearch = true;
|
||||
var isLineSearch = true;
|
||||
}
|
||||
if (this._prevSearchedToken != token) {
|
||||
isDifferentToken = true;
|
||||
var isDifferentToken = true;
|
||||
}
|
||||
|
||||
// Meta+G and Ctrl+N focus next matches.
|
||||
@ -1013,7 +1048,7 @@ FilterView.prototype = {
|
||||
else switch (e.keyCode) {
|
||||
case e.DOM_VK_RETURN:
|
||||
case e.DOM_VK_ENTER:
|
||||
isReturnKey = true;
|
||||
var isReturnKey = true;
|
||||
// fall through
|
||||
case e.DOM_VK_DOWN:
|
||||
action = 0;
|
||||
@ -1030,8 +1065,7 @@ FilterView.prototype = {
|
||||
DebuggerView.editor.focus();
|
||||
return;
|
||||
}
|
||||
if (action == -1 || (!file && !line && !token)) {
|
||||
DebuggerView.FilteredSources.hidden = true;
|
||||
if (action == -1 || (!operator && !file && !line && !token)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1041,7 +1075,7 @@ FilterView.prototype = {
|
||||
// Select the next or previous file search entry.
|
||||
if (isFileSearch) {
|
||||
if (isReturnKey) {
|
||||
DebuggerView.FilteredSources.hidden = true;
|
||||
DebuggerView.FilteredSources.clearView();
|
||||
DebuggerView.editor.focus();
|
||||
this.clearSearch();
|
||||
} else {
|
||||
@ -1062,6 +1096,21 @@ FilterView.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a function search based on the specified operator.
|
||||
if (isFunction) {
|
||||
if (isReturnKey && (isDifferentToken || DebuggerView.FilteredFunctions.hidden)) {
|
||||
DebuggerView.FilteredFunctions.performSearch(token);
|
||||
} else if (!isReturnKey) {
|
||||
DebuggerView.FilteredFunctions[["focusNext", "focusPrev"][action]]();
|
||||
} else {
|
||||
DebuggerView.FilteredFunctions.clearView();
|
||||
DebuggerView.editor.focus();
|
||||
this.clearSearch();
|
||||
}
|
||||
this._prevSearchedToken = token;
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a variable search based on the specified operator.
|
||||
if (isVariable) {
|
||||
if (isReturnKey && isDifferentToken) {
|
||||
@ -1097,6 +1146,8 @@ FilterView.prototype = {
|
||||
*/
|
||||
_onBlur: function DVF__onBlur() {
|
||||
DebuggerView.GlobalSearch.clearView();
|
||||
DebuggerView.FilteredSources.clearView();
|
||||
DebuggerView.FilteredFunctions.clearView();
|
||||
DebuggerView.Variables.performSearch(null);
|
||||
this._searchboxHelpPanel.hidePopup();
|
||||
},
|
||||
@ -1109,6 +1160,7 @@ FilterView.prototype = {
|
||||
*/
|
||||
_doSearch: function DVF__doSearch(aOperator = "") {
|
||||
this._searchbox.focus();
|
||||
this._searchbox.value = ""; // Need to clear value beforehand. Bug 779738.
|
||||
this._searchbox.value = aOperator;
|
||||
},
|
||||
|
||||
@ -1128,6 +1180,14 @@ FilterView.prototype = {
|
||||
this._searchboxHelpPanel.hidePopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the source function filter key sequence was pressed.
|
||||
*/
|
||||
_doFunctionSearch: function DVF__doFunctionSearch() {
|
||||
this._doSearch(SEARCH_FUNCTION_FLAG);
|
||||
this._searchboxHelpPanel.hidePopup();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the source token filter key sequence was pressed.
|
||||
*/
|
||||
@ -1165,6 +1225,8 @@ FilterView.prototype = {
|
||||
_searchboxHelpPanel: null,
|
||||
_globalOperatorButton: null,
|
||||
_globalOperatorLabel: null,
|
||||
_functionOperatorButton: null,
|
||||
_functionOperatorLabel: null,
|
||||
_tokenOperatorButton: null,
|
||||
_tokenOperatorLabel: null,
|
||||
_lineOperatorButton: null,
|
||||
@ -1173,6 +1235,7 @@ FilterView.prototype = {
|
||||
_variableOperatorLabel: null,
|
||||
_fileSearchKey: "",
|
||||
_globalSearchKey: "",
|
||||
_filteredFunctionsKey: "",
|
||||
_tokenSearchKey: "",
|
||||
_lineSearchKey: "",
|
||||
_variableSearchKey: "",
|
||||
@ -1187,23 +1250,20 @@ FilterView.prototype = {
|
||||
*/
|
||||
function FilteredSourcesView() {
|
||||
dumpn("FilteredSourcesView was instantiated");
|
||||
ResultsPanelContainer.call(this);
|
||||
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
this.onSelect = this.onSelect.bind(this);
|
||||
}
|
||||
|
||||
create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
|
||||
create({ constructor: FilteredSourcesView, proto: ResultsPanelContainer.prototype }, {
|
||||
/**
|
||||
* Initialization function, called when the debugger is started.
|
||||
*/
|
||||
initialize: function DVFS_initialize() {
|
||||
dumpn("Initializing the FilteredSourcesView");
|
||||
|
||||
this.node = new ListWidget(document.getElementById("filtered-sources-panel"));
|
||||
this._searchbox = document.getElementById("searchbox");
|
||||
|
||||
this.node.itemFactory = this._createItemView;
|
||||
this.node.itemType = "vbox";
|
||||
this.node.addEventListener("click", this._onClick, false);
|
||||
this.anchor = document.getElementById("searchbox");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1212,19 +1272,7 @@ create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
|
||||
destroy: function DVFS_destroy() {
|
||||
dumpn("Destroying the FilteredSourcesView");
|
||||
|
||||
this.node.removeEventListener("click", this._onClick, false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the files container hidden or visible. It's hidden by default.
|
||||
* @param boolean aFlag
|
||||
*/
|
||||
set hidden(aFlag) {
|
||||
if (aFlag) {
|
||||
this.node._parent.hidePopup();
|
||||
} else {
|
||||
this.node._parent.openPopup(this._searchbox);
|
||||
}
|
||||
this.anchor = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1234,7 +1282,7 @@ create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
|
||||
this.empty();
|
||||
|
||||
// If there's no currently searched file, or there are no matches found,
|
||||
// hide the popup.
|
||||
// hide the popup and avoid creating the view again.
|
||||
if (!DebuggerView.Filtering.searchedFile ||
|
||||
!DebuggerView.Sources.visibleItems.length) {
|
||||
this.hidden = true;
|
||||
@ -1243,12 +1291,12 @@ create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
|
||||
|
||||
// Get the currently visible items in the sources container.
|
||||
let visibleItems = DebuggerView.Sources.visibleItems;
|
||||
let displayedItems = visibleItems.slice(0, FILTERED_SOURCES_MAX_RESULTS);
|
||||
let displayedItems = visibleItems.slice(0, RESULTS_PANEL_MAX_RESULTS);
|
||||
|
||||
for (let item of displayedItems) {
|
||||
// Append a location item item to this container.
|
||||
let trimmedLabel = SourceUtils.trimUrlLength(item.label);
|
||||
let trimmedValue = SourceUtils.trimUrlLength(item.value);
|
||||
let trimmedValue = SourceUtils.trimUrlLength(item.value, 0, "start");
|
||||
let locationItem = this.push([trimmedLabel, trimmedValue], {
|
||||
relaxed: true, /* this container should allow dupes & degenerates */
|
||||
attachment: {
|
||||
@ -1258,82 +1306,263 @@ create({ constructor: FilteredSourcesView, proto: MenuContainer.prototype }, {
|
||||
});
|
||||
}
|
||||
|
||||
this._updateSelection(this.getItemAtIndex(0));
|
||||
this.hidden = false;
|
||||
},
|
||||
// Select the first entry in this container.
|
||||
this.select(0);
|
||||
|
||||
/**
|
||||
* Focuses the next found match in this container.
|
||||
*/
|
||||
focusNext: function DVFS_focusNext() {
|
||||
let nextIndex = this.selectedIndex + 1;
|
||||
if (nextIndex >= this.itemCount) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
this._updateSelection(this.getItemAtIndex(nextIndex));
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the previously found match in this container.
|
||||
*/
|
||||
focusPrev: function DVFS_focusPrev() {
|
||||
let prevIndex = this.selectedIndex - 1;
|
||||
if (prevIndex < 0) {
|
||||
prevIndex = this.itemCount - 1;
|
||||
}
|
||||
this._updateSelection(this.getItemAtIndex(prevIndex));
|
||||
// Only display the results panel if there's at least one entry available.
|
||||
this.hidden = this.itemCount == 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* The click listener for this container.
|
||||
*/
|
||||
_onClick: function DVFS__onClick(e) {
|
||||
onClick: function DVFS_onClick(e) {
|
||||
let locationItem = this.getItemForElement(e.target);
|
||||
if (locationItem) {
|
||||
this._updateSelection(locationItem);
|
||||
this.select(locationItem);
|
||||
DebuggerView.Filtering.clearSearch();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the selected item in this container and other views.
|
||||
* The select listener for this container.
|
||||
*
|
||||
* @param MenuItem aItem
|
||||
* The item associated with the element to select.
|
||||
*/
|
||||
_updateSelection: function DVFS__updateSelection(aItem) {
|
||||
this.selectedItem = aItem;
|
||||
DebuggerView.Filtering._target.selectedValue = aItem.attachment.fullValue;
|
||||
onSelect: function DVFS_onSelect(e) {
|
||||
let locationItem = this.getItemForElement(e.target);
|
||||
if (locationItem) {
|
||||
DebuggerView.Sources.selectedValue = locationItem.attachment.fullValue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Functions handling the function search UI.
|
||||
*/
|
||||
function FilteredFunctionsView() {
|
||||
dumpn("FilteredFunctionsView was instantiated");
|
||||
ResultsPanelContainer.call(this);
|
||||
|
||||
this._performFunctionSearch = this._performFunctionSearch.bind(this);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
this.onSelect = this.onSelect.bind(this);
|
||||
}
|
||||
|
||||
create({ constructor: FilteredFunctionsView, proto: ResultsPanelContainer.prototype }, {
|
||||
/**
|
||||
* Initialization function, called when the debugger is started.
|
||||
*/
|
||||
initialize: function DVFF_initialize() {
|
||||
dumpn("Initializing the FilteredFunctionsView");
|
||||
|
||||
this.anchor = document.getElementById("searchbox");
|
||||
},
|
||||
|
||||
/**
|
||||
* Customization function for creating an item's UI.
|
||||
*
|
||||
* @param nsIDOMNode aElementNode
|
||||
* The element associated with the displayed item.
|
||||
* @param any aAttachment
|
||||
* Some attached primitive/object.
|
||||
* @param string aLabel
|
||||
* The item's label.
|
||||
* @param string aValue
|
||||
* The item's value.
|
||||
* Destruction function, called when the debugger is closed.
|
||||
*/
|
||||
_createItemView:
|
||||
function DVFS__createItemView(aElementNode, aAttachment, aLabel, aValue) {
|
||||
let labelNode = document.createElement("label");
|
||||
labelNode.className = "plain dbg-source-item-name";
|
||||
labelNode.setAttribute("value", aLabel);
|
||||
destroy: function DVFF_destroy() {
|
||||
dumpn("Destroying the FilteredFunctionsView");
|
||||
|
||||
let valueNode = document.createElement("label");
|
||||
valueNode.setAttribute("value", aValue);
|
||||
valueNode.className = "plain dbg-source-item-details";
|
||||
|
||||
aElementNode.className = "light dbg-source-item";
|
||||
aElementNode.appendChild(labelNode);
|
||||
aElementNode.appendChild(valueNode);
|
||||
this.anchor = null;
|
||||
},
|
||||
|
||||
_searchbox: null
|
||||
/**
|
||||
* Allows searches to be scheduled and delayed to avoid redundant calls.
|
||||
*/
|
||||
delayedSearch: true,
|
||||
|
||||
/**
|
||||
* Schedules searching for a function in all of the sources.
|
||||
*
|
||||
* @param string aQuery
|
||||
* The function to search for.
|
||||
*/
|
||||
scheduleSearch: function DVFF_scheduleSearch(aQuery) {
|
||||
if (!this.delayedSearch) {
|
||||
this.performSearch(aQuery);
|
||||
return;
|
||||
}
|
||||
let delay = Math.max(FUNCTION_SEARCH_ACTION_MAX_DELAY / aQuery.length, 0);
|
||||
|
||||
window.clearTimeout(this._searchTimeout);
|
||||
this._searchFunction = this._startSearch.bind(this, aQuery);
|
||||
this._searchTimeout = window.setTimeout(this._searchFunction, delay);
|
||||
},
|
||||
|
||||
/**
|
||||
* Immediately searches for a function in all of the sources.
|
||||
*
|
||||
* @param string aQuery
|
||||
* The function to search for.
|
||||
*/
|
||||
performSearch: function DVFF_performSearch(aQuery) {
|
||||
window.clearTimeout(this._searchTimeout);
|
||||
this._searchFunction = null;
|
||||
this._startSearch(aQuery);
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts searching for a function in all of the sources.
|
||||
*
|
||||
* @param string aQuery
|
||||
* The function to search for.
|
||||
*/
|
||||
_startSearch: function DVFF__startSearch(aQuery) {
|
||||
this._searchedToken = aQuery;
|
||||
|
||||
DebuggerController.SourceScripts.fetchSources(DebuggerView.Sources.values, {
|
||||
onFinished: this._performFunctionSearch
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds function matches in all the sources stored in the cache, and groups
|
||||
* them by location and line number.
|
||||
*/
|
||||
_performFunctionSearch: function DVFF__performFunctionSearch() {
|
||||
// Get the currently searched token from the filtering input.
|
||||
// Continue parsing even if the searched token is an empty string, to
|
||||
// cache the syntax tree nodes generated by the reflection API.
|
||||
let token = this._searchedToken;
|
||||
|
||||
// Make sure the currently displayed source is parsed first. Once the
|
||||
// maximum allowed number of resutls are found, parsing will be halted.
|
||||
let sourcesCache = DebuggerController.SourceScripts.getCache();
|
||||
let currentUrl = DebuggerView.Sources.selectedValue;
|
||||
sourcesCache.sort(function([sourceUrl]) sourceUrl == currentUrl ? -1 : 1);
|
||||
|
||||
// If not searching for a specific function, only parse the displayed source.
|
||||
if (!token) {
|
||||
sourcesCache.splice(1);
|
||||
}
|
||||
|
||||
// Prepare the results array, containing search details for each source.
|
||||
let searchResults = [];
|
||||
|
||||
for (let [location, contents] of sourcesCache) {
|
||||
let parserMethods = DebuggerController.Parser.get(location, contents);
|
||||
let sourceResults = parserMethods.getNamedFunctionDefinitions(token);
|
||||
|
||||
for (let scriptResult of sourceResults) {
|
||||
for (let parseResult of scriptResult.parseResults) {
|
||||
searchResults.push({
|
||||
sourceUrl: scriptResult.sourceUrl,
|
||||
scriptOffset: scriptResult.scriptOffset,
|
||||
functionName: parseResult.functionName,
|
||||
functionLocation: parseResult.functionLocation,
|
||||
inferredName: parseResult.inferredName,
|
||||
inferredChain: parseResult.inferredChain,
|
||||
inferredLocation: parseResult.inferredLocation
|
||||
});
|
||||
|
||||
// Once the maximum allowed number of results is reached, proceed
|
||||
// with building the UI immediately.
|
||||
if (searchResults.length >= RESULTS_PANEL_MAX_RESULTS) {
|
||||
this._syncFunctionSearch(searchResults);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Couldn't reach the maximum allowed number of results, but that's ok,
|
||||
// continue building the UI.
|
||||
this._syncFunctionSearch(searchResults);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the list of functions displayed in this container.
|
||||
*
|
||||
* @param array aSearchResults
|
||||
* The results array, containing search details for each source.
|
||||
*/
|
||||
_syncFunctionSearch: function DVFF__syncFunctionSearch(aSearchResults) {
|
||||
this.empty();
|
||||
|
||||
// Show the popup even if the search token is an empty string. If there are
|
||||
// no matches found, hide the popup and avoid creating the view again.
|
||||
if (!aSearchResults.length) {
|
||||
this.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
for (let item of aSearchResults) {
|
||||
// Some function expressions don't necessarily have a name, but the
|
||||
// parser provides us with an inferred name from an enclosing
|
||||
// VariableDeclarator, AssignmentExpression, ObjectExpression node.
|
||||
if (item.functionName && item.inferredName &&
|
||||
item.functionName != item.inferredName) {
|
||||
let s = " " + L10N.getStr("functionSearchSeparatorLabel") + " ";
|
||||
item.displayedName = item.inferredName + s + item.functionName;
|
||||
}
|
||||
// The function doesn't have an explicit name, but it could be inferred.
|
||||
else if (item.inferredName) {
|
||||
item.displayedName = item.inferredName;
|
||||
}
|
||||
// The function only has an explicit name.
|
||||
else {
|
||||
item.displayedName = item.functionName;
|
||||
}
|
||||
|
||||
// Some function expressions have unexpected bounds, since they may not
|
||||
// necessarily have an associated name defining them.
|
||||
if (item.inferredLocation) {
|
||||
item.actualLocation = item.inferredLocation;
|
||||
} else {
|
||||
item.actualLocation = item.functionLocation;
|
||||
}
|
||||
|
||||
// Append a function item to this container.
|
||||
let trimmedLabel = SourceUtils.trimUrlLength(item.displayedName + "()");
|
||||
let trimmedValue = SourceUtils.trimUrlLength(item.sourceUrl, 0, "start");
|
||||
let description = (item.inferredChain || []).join(".");
|
||||
|
||||
let functionItem = this.push([trimmedLabel, trimmedValue, description], {
|
||||
index: -1, /* specifies on which position should the item be appended */
|
||||
relaxed: true, /* this container should allow dupes & degenerates */
|
||||
attachment: item
|
||||
});
|
||||
}
|
||||
|
||||
// Select the first entry in this container.
|
||||
this.select(0);
|
||||
this.hidden = this.itemCount == 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* The click listener for this container.
|
||||
*/
|
||||
onClick: function DVFF_onClick(e) {
|
||||
let functionItem = this.getItemForElement(e.target);
|
||||
if (functionItem) {
|
||||
this.select(functionItem);
|
||||
DebuggerView.Filtering.clearSearch();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The select listener for this container.
|
||||
*/
|
||||
onSelect: function DVFF_onSelect(e) {
|
||||
let functionItem = this.getItemForElement(e.target);
|
||||
if (functionItem) {
|
||||
let sourceUrl = functionItem.attachment.sourceUrl;
|
||||
let scriptOffset = functionItem.attachment.scriptOffset;
|
||||
let actualLocation = functionItem.attachment.actualLocation;
|
||||
|
||||
DebuggerView.updateEditor(sourceUrl, actualLocation.start.line, {
|
||||
charOffset: scriptOffset,
|
||||
columnOffset: actualLocation.start.column,
|
||||
noDebug: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_searchTimeout: null,
|
||||
_searchFunction: null,
|
||||
_searchedToken: ""
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1343,5 +1572,6 @@ DebuggerView.Toolbar = new ToolbarView();
|
||||
DebuggerView.Options = new OptionsView();
|
||||
DebuggerView.Filtering = new FilterView();
|
||||
DebuggerView.FilteredSources = new FilteredSourcesView();
|
||||
DebuggerView.FilteredFunctions = new FilteredFunctionsView();
|
||||
DebuggerView.ChromeGlobals = new ChromeGlobalsView();
|
||||
DebuggerView.StackFrames = new StackFramesView();
|
||||
|
@ -17,11 +17,14 @@ const BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH = 1000; // chars
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_POSITION = "before_start";
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X = 7; // px
|
||||
const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_Y = -3; // px
|
||||
const FILTERED_SOURCES_MAX_RESULTS = 10;
|
||||
const RESULTS_PANEL_POPUP_POSITION = "before_end";
|
||||
const RESULTS_PANEL_MAX_RESULTS = 10;
|
||||
const GLOBAL_SEARCH_EXPAND_MAX_RESULTS = 50;
|
||||
const GLOBAL_SEARCH_LINE_MAX_LENGTH = 300; // chars
|
||||
const GLOBAL_SEARCH_ACTION_MAX_DELAY = 1500; // ms
|
||||
const FUNCTION_SEARCH_ACTION_MAX_DELAY = 400; // ms
|
||||
const SEARCH_GLOBAL_FLAG = "!";
|
||||
const SEARCH_FUNCTION_FLAG = "@";
|
||||
const SEARCH_TOKEN_FLAG = "#";
|
||||
const SEARCH_LINE_FLAG = ":";
|
||||
const SEARCH_VARIABLE_FLAG = "*";
|
||||
@ -46,6 +49,7 @@ let DebuggerView = {
|
||||
this.Options.initialize();
|
||||
this.Filtering.initialize();
|
||||
this.FilteredSources.initialize();
|
||||
this.FilteredFunctions.initialize();
|
||||
this.ChromeGlobals.initialize();
|
||||
this.StackFrames.initialize();
|
||||
this.Sources.initialize();
|
||||
@ -76,6 +80,7 @@ let DebuggerView = {
|
||||
this.Options.destroy();
|
||||
this.Filtering.destroy();
|
||||
this.FilteredSources.destroy();
|
||||
this.FilteredFunctions.destroy();
|
||||
this.ChromeGlobals.destroy();
|
||||
this.StackFrames.destroy();
|
||||
this.Sources.destroy();
|
||||
@ -260,7 +265,7 @@ let DebuggerView = {
|
||||
|
||||
// If the source is not loaded, display a placeholder text.
|
||||
if (!aSource.loaded) {
|
||||
DebuggerController.SourceScripts.getText(aSource, set.bind(this, aSource));
|
||||
DebuggerController.SourceScripts.getText(aSource, set.bind(this));
|
||||
}
|
||||
// If the source is already loaded, display it immediately.
|
||||
else {
|
||||
@ -371,10 +376,10 @@ let DebuggerView = {
|
||||
aLine += aFlags.lineOffset;
|
||||
}
|
||||
if (!aFlags.noCaret) {
|
||||
editor.setCaretPosition(aLine - 1);
|
||||
editor.setCaretPosition(aLine - 1, aFlags.columnOffset);
|
||||
}
|
||||
if (!aFlags.noDebug) {
|
||||
editor.setDebugLocation(aLine - 1);
|
||||
editor.setDebugLocation(aLine - 1, aFlags.columnOffset);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -388,13 +393,24 @@ let DebuggerView = {
|
||||
* @return string
|
||||
* The specified line's text.
|
||||
*/
|
||||
getEditorLine: function SS_getEditorLine(aLine) {
|
||||
getEditorLine: function DV_getEditorLine(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);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the text in the source editor's selection bounds.
|
||||
*
|
||||
* @return string
|
||||
* The selected text.
|
||||
*/
|
||||
getEditorSelection: function DV_getEditorSelection() {
|
||||
let selection = this.editor.getSelection();
|
||||
return this.editor.getText(selection.start, selection.end);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the visibility state of the instruments pane.
|
||||
* @return boolean
|
||||
@ -486,13 +502,13 @@ let DebuggerView = {
|
||||
dumpn("Handling tab navigation in the DebuggerView");
|
||||
|
||||
this.Filtering.clearSearch();
|
||||
this.FilteredSources.clearView();
|
||||
this.FilteredFunctions.clearView();
|
||||
this.GlobalSearch.clearView();
|
||||
this.GlobalSearch.clearCache();
|
||||
this.ChromeGlobals.empty();
|
||||
this.StackFrames.empty();
|
||||
this.Sources.empty();
|
||||
this.Variables.empty();
|
||||
SourceUtils.clearCache();
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.setText("");
|
||||
@ -750,6 +766,202 @@ ListWidget.prototype = {
|
||||
_emptyTextValue: ""
|
||||
};
|
||||
|
||||
/**
|
||||
* A custom items container, used for displaying views like the
|
||||
* FilteredSources, FilteredFunctions etc., inheriting the generic MenuContainer.
|
||||
*/
|
||||
function ResultsPanelContainer() {
|
||||
this._createItemView = this._createItemView.bind(this);
|
||||
}
|
||||
|
||||
create({ constructor: ResultsPanelContainer, proto: MenuContainer.prototype }, {
|
||||
onClick: null,
|
||||
onSelect: null,
|
||||
|
||||
/**
|
||||
* Sets the anchor node for this container panel.
|
||||
* @param nsIDOMNode aNode
|
||||
*/
|
||||
set anchor(aNode) {
|
||||
this._anchor = aNode;
|
||||
|
||||
// If the anchor node is not null, create a panel to attach to the anchor
|
||||
// when showing the popup.
|
||||
if (aNode) {
|
||||
if (!this._panel) {
|
||||
this._panel = document.createElement("panel");
|
||||
this._panel.className = "results-panel";
|
||||
this._panel.setAttribute("level", "top");
|
||||
this._panel.setAttribute("noautofocus", "true");
|
||||
document.documentElement.appendChild(this._panel);
|
||||
}
|
||||
if (!this.node) {
|
||||
this.node = new ListWidget(this._panel);
|
||||
this.node.itemType = "vbox";
|
||||
this.node.itemFactory = this._createItemView;
|
||||
this.node.addEventListener("click", this.onClick, false);
|
||||
}
|
||||
}
|
||||
// Cleanup the anchor and remove the previously created panel.
|
||||
else {
|
||||
if (this._panel) {
|
||||
document.documentElement.removeChild(this._panel);
|
||||
this._panel = null;
|
||||
}
|
||||
if (this.node) {
|
||||
this.node.removeEventListener("click", this.onClick, false);
|
||||
this.node = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the anchor node for this container panel.
|
||||
* @return nsIDOMNode
|
||||
*/
|
||||
get anchor() this._anchor,
|
||||
|
||||
/**
|
||||
* Sets the default top, left and position params when opening the panel.
|
||||
* @param object aOptions
|
||||
*/
|
||||
set options(aOptions) {
|
||||
this._top = aOptions.top;
|
||||
this._left = aOptions.left;
|
||||
this._position = aOptions.position;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the default params for when opening the panel.
|
||||
* @return object
|
||||
*/
|
||||
get options() ({
|
||||
top: this._top,
|
||||
left: this._left,
|
||||
position: this._position
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets the container panel hidden or visible. It's hidden by default.
|
||||
* @param boolean aFlag
|
||||
*/
|
||||
set hidden(aFlag) {
|
||||
if (aFlag) {
|
||||
this._panel.hidePopup();
|
||||
} else {
|
||||
this._panel.openPopup(this._anchor, this._position, this._left, this._top);
|
||||
this.anchor.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets this container's visibility state.
|
||||
* @return boolean
|
||||
*/
|
||||
get hidden()
|
||||
this._panel.state == "closed" ||
|
||||
this._panel.state == "hiding",
|
||||
|
||||
/**
|
||||
* Removes all items from this container and hides it.
|
||||
*/
|
||||
clearView: function RPC_clearView() {
|
||||
this.hidden = true;
|
||||
this.empty();
|
||||
window.dispatchEvent(document, "Debugger:ResultsPanelContainer:ViewCleared");
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the next found item in this container.
|
||||
*/
|
||||
focusNext: function RPC_focusNext() {
|
||||
let nextIndex = this.selectedIndex + 1;
|
||||
if (nextIndex >= this.itemCount) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
this.select(this.getItemAtIndex(nextIndex));
|
||||
},
|
||||
|
||||
/**
|
||||
* Focuses the previously found item in this container.
|
||||
*/
|
||||
focusPrev: function RPC_focusPrev() {
|
||||
let prevIndex = this.selectedIndex - 1;
|
||||
if (prevIndex < 0) {
|
||||
prevIndex = this.itemCount - 1;
|
||||
}
|
||||
this.select(this.getItemAtIndex(prevIndex));
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the selected item in this container.
|
||||
*
|
||||
* @param MenuItem | number aItem
|
||||
* The item associated with the element to select.
|
||||
*/
|
||||
select: function RPC_select(aItem) {
|
||||
if (typeof aItem == "number") {
|
||||
this.select(this.getItemAtIndex(aItem));
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the currently selected item in this container using the
|
||||
// selectedItem setter in the MenuContainer prototype chain.
|
||||
this.selectedItem = aItem;
|
||||
|
||||
// Invoke the attached selection callback if available in any
|
||||
// inheriting prototype.
|
||||
if (this.onSelect) {
|
||||
this.onSelect({ target: aItem.target });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Customization function for creating an item's UI.
|
||||
*
|
||||
* @param nsIDOMNode aElementNode
|
||||
* The element associated with the displayed item.
|
||||
* @param any aAttachment
|
||||
* Some attached primitive/object.
|
||||
* @param string aLabel
|
||||
* The item's label.
|
||||
* @param string aValue
|
||||
* The item's value.
|
||||
* @param string aDescription
|
||||
* An optional description of the item.
|
||||
*/
|
||||
_createItemView:
|
||||
function RPC__createItemView(aElementNode, aAttachment, aLabel, aValue, aDescription) {
|
||||
let labelsGroup = document.createElement("hbox");
|
||||
if (aDescription) {
|
||||
let preLabelNode = document.createElement("label");
|
||||
preLabelNode.className = "plain results-panel-item-pre";
|
||||
preLabelNode.setAttribute("value", aDescription);
|
||||
labelsGroup.appendChild(preLabelNode);
|
||||
}
|
||||
if (aLabel) {
|
||||
let labelNode = document.createElement("label");
|
||||
labelNode.className = "plain results-panel-item-name";
|
||||
labelNode.setAttribute("value", aLabel);
|
||||
labelsGroup.appendChild(labelNode);
|
||||
}
|
||||
|
||||
let valueNode = document.createElement("label");
|
||||
valueNode.className = "plain results-panel-item-details";
|
||||
valueNode.setAttribute("value", aValue);
|
||||
|
||||
aElementNode.className = "light results-panel-item";
|
||||
aElementNode.appendChild(labelsGroup);
|
||||
aElementNode.appendChild(valueNode);
|
||||
},
|
||||
|
||||
_anchor: null,
|
||||
_panel: null,
|
||||
_position: RESULTS_PANEL_POPUP_POSITION,
|
||||
_left: 0,
|
||||
_top: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* A simple way of displaying a "Connect to..." prompt.
|
||||
*/
|
||||
|
@ -38,6 +38,8 @@
|
||||
oncommand="DebuggerView.Filtering._doFileSearch()"/>
|
||||
<command id="globalSearchCommand"
|
||||
oncommand="DebuggerView.Filtering._doGlobalSearch()"/>
|
||||
<command id="functionSearchCommand"
|
||||
oncommand="DebuggerView.Filtering._doFunctionSearch()"/>
|
||||
<command id="tokenSearchCommand"
|
||||
oncommand="DebuggerView.Filtering._doTokenSearch()"/>
|
||||
<command id="lineSearchCommand"
|
||||
@ -94,6 +96,11 @@
|
||||
accesskey="&debuggerUI.searchGlobal.key;"
|
||||
key="globalSearchKey"
|
||||
command="globalSearchCommand"/>
|
||||
<menuitem id="se-dbg-cMenu-findFunction"
|
||||
label="&debuggerUI.searchFunction;"
|
||||
accesskey="&debuggerUI.searchFunction.key;"
|
||||
key="functionSearchKey"
|
||||
command="functionSearchCommand"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="se-dbg-cMenu-findToken"
|
||||
label="&debuggerUI.searchToken;"
|
||||
@ -174,10 +181,22 @@
|
||||
key="&debuggerUI.searchFile.key;"
|
||||
modifiers="accel"
|
||||
command="fileSearchCommand"/>
|
||||
<key id="fileSearchKey"
|
||||
key="&debuggerUI.searchFile.altkey;"
|
||||
modifiers="accel"
|
||||
command="fileSearchCommand"/>
|
||||
<key id="globalSearchKey"
|
||||
key="&debuggerUI.searchGlobal.key;"
|
||||
modifiers="accel alt"
|
||||
command="globalSearchCommand"/>
|
||||
<key id="functionSearchKey"
|
||||
key="&debuggerUI.searchFunction.key;"
|
||||
modifiers="accel"
|
||||
command="functionSearchCommand"/>
|
||||
<key id="functionSearchKey"
|
||||
key="&debuggerUI.searchFunction.altkey;"
|
||||
modifiers="accel shift"
|
||||
command="functionSearchCommand"/>
|
||||
<key id="tokenSearchKey"
|
||||
key="&debuggerUI.searchToken.key;"
|
||||
modifiers="accel"
|
||||
@ -278,6 +297,13 @@
|
||||
<label id="global-operator-label"
|
||||
class="plain searchbox-panel-operator-label"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<button id="function-operator-button"
|
||||
class="searchbox-panel-operator-button"
|
||||
command="functionSearchCommand"/>
|
||||
<label id="function-operator-label"
|
||||
class="plain searchbox-panel-operator-label"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<button id="token-operator-button"
|
||||
class="searchbox-panel-operator-button"
|
||||
@ -295,19 +321,13 @@
|
||||
<hbox align="center">
|
||||
<button id="variable-operator-button"
|
||||
class="searchbox-panel-operator-button"
|
||||
command="variableSearchCommand"/>
|
||||
command="variableSearchCommand"/>
|
||||
<label id="variable-operator-label"
|
||||
class="plain searchbox-panel-operator-label"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</panel>
|
||||
|
||||
<panel id="filtered-sources-panel"
|
||||
level="top"
|
||||
noautofocus="true"
|
||||
position="before_start">
|
||||
</panel>
|
||||
|
||||
<panel id="conditional-breakpoint-panel"
|
||||
hidden="true"
|
||||
level="top"
|
||||
|
@ -11,10 +11,10 @@ relativesrcdir = @relativesrcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_BROWSER_TESTS = \
|
||||
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
|
||||
browser_dbg_cmd.js \
|
||||
browser_dbg_aaa_run_first_leaktest.js \
|
||||
browser_dbg_clean-exit.js \
|
||||
browser_dbg_cmd.js \
|
||||
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
|
||||
browser_dbg_createChrome.js \
|
||||
$(browser_dbg_createRemote.js disabled for intermittent failures, bug 753225) \
|
||||
$(browser_dbg_debugger-tab-switch.js disabled until issues 106, 40 are fixed) \
|
||||
@ -63,6 +63,7 @@ MOCHITEST_BROWSER_TESTS = \
|
||||
browser_dbg_location-changes.js \
|
||||
browser_dbg_location-changes-new.js \
|
||||
browser_dbg_location-changes-blank.js \
|
||||
browser_dbg_sources-cache.js \
|
||||
browser_dbg_scripts-switching.js \
|
||||
browser_dbg_scripts-sorting.js \
|
||||
browser_dbg_scripts-searching-01.js \
|
||||
@ -75,6 +76,7 @@ MOCHITEST_BROWSER_TESTS = \
|
||||
browser_dbg_scripts-searching-08.js \
|
||||
browser_dbg_scripts-searching-files_ui.js \
|
||||
browser_dbg_scripts-searching-popup.js \
|
||||
browser_dbg_function-search.js \
|
||||
browser_dbg_pause-resume.js \
|
||||
browser_dbg_pause-warning.js \
|
||||
browser_dbg_update-editor-mode.js \
|
||||
@ -122,6 +124,11 @@ MOCHITEST_BROWSER_PAGES = \
|
||||
browser_dbg_breakpoint-new-script.html \
|
||||
browser_dbg_conditional-breakpoints.html \
|
||||
browser_dbg_watch-expressions.html \
|
||||
browser_dbg_function-search-01.html \
|
||||
browser_dbg_function-search-02.html \
|
||||
test-function-search-01.js \
|
||||
test-function-search-02.js \
|
||||
test-function-search-03.js \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
|
||||
|
@ -1,5 +1,9 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<script type="application/javascript;version=1.7"/>
|
||||
let output;
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<title>Browser Debugger Function Search</title>
|
||||
<script type="text/javascript" src="test-function-search-01.js"></script>
|
||||
<script type="text/javascript" src="test-function-search-02.js"></script>
|
||||
<script type="text/javascript" src="test-function-search-03.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Peanut butter jelly time!</p>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<head>
|
||||
<meta charset='utf-8'/>
|
||||
<title>Browser Debugger Function Search</title>
|
||||
<script type="text/javascript" src="test-function-search-01.js"></script>
|
||||
<script type="text/javascript" src="test-function-search-02.js"></script>
|
||||
<script type="text/javascript" src="test-function-search-03.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>Peanut butter jelly time!</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function inline() {
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
495
browser/devtools/debugger/test/browser_dbg_function-search.js
Normal file
495
browser/devtools/debugger/test/browser_dbg_function-search.js
Normal file
@ -0,0 +1,495 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_function-search-02.html";
|
||||
|
||||
/**
|
||||
* Tests if the function searching works properly.
|
||||
*/
|
||||
|
||||
let gPane = null;
|
||||
let gTab = null;
|
||||
let gDebuggee = null;
|
||||
let gDebugger = null;
|
||||
let gEditor = null;
|
||||
let gSources = null;
|
||||
let gSearchBox = null;
|
||||
let gFilteredFunctions = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
Services.tm.currentThread.dispatch({ run: testFunctionsFilter }, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testFunctionsFilter()
|
||||
{
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
|
||||
gFilteredFunctions = gDebugger.DebuggerView.FilteredFunctions;
|
||||
|
||||
htmlSearch(function() {
|
||||
showSource("test-function-search-01.js", function() {
|
||||
firstSearch(function() {
|
||||
showSource("test-function-search-02.js", function() {
|
||||
secondSearch(function() {
|
||||
showSource("test-function-search-03.js", function() {
|
||||
thirdSearch(function() {
|
||||
saveSearch(function() {
|
||||
filterSearch(function() {
|
||||
bogusSearch(function() {
|
||||
anotherSearch(function() {
|
||||
emptySearch(function() {
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function htmlSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
info("Current script url:\n" + gSources.selectedValue + "\n");
|
||||
info("Debugger editor text:\n" + gEditor.getText() + "\n");
|
||||
|
||||
ok(gFilteredFunctions.selectedValue,
|
||||
"An item should be selected in the filtered functions view");
|
||||
ok(gFilteredFunctions.selectedLabel,
|
||||
"An item should be selected in the filtered functions view");
|
||||
|
||||
let url = gSources.selectedValue;
|
||||
if (url.indexOf("-02.html") != -1) {
|
||||
|
||||
executeSoon(function() {
|
||||
let expectedResults = [
|
||||
["inline", "-02.html", "", 16, 15],
|
||||
]
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
gDebugger.SourceUtils.trimUrlLength(label + "()"),
|
||||
"The corect label (" + label + ") is currently selected.");
|
||||
ok(gFilteredFunctions.selectedItem.value.contains(value),
|
||||
"The corect value (" + value + ") is attached.");
|
||||
is(gFilteredFunctions.selectedItem.description, description,
|
||||
"The corect description (" + description + ") is currently shown.");
|
||||
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
|
||||
ok(gEditor.getCaretPosition().line == line &&
|
||||
gEditor.getCaretPosition().col == col,
|
||||
"The editor didn't jump to the correct line.");
|
||||
|
||||
ok(gSources.selectedLabel, label,
|
||||
"The current source isn't the correct one, according to the label.");
|
||||
ok(gSources.selectedValue, value,
|
||||
"The current source isn't the correct one, according to the value.");
|
||||
|
||||
EventUtils.sendKey("DOWN", gDebugger);
|
||||
}
|
||||
|
||||
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
|
||||
gEditor.getCaretPosition().col == expectedResults[0][4],
|
||||
"The editor didn't jump to the correct line again.");
|
||||
|
||||
executeSoon(callback);
|
||||
});
|
||||
} else {
|
||||
ok(false, "How did you get here? Go away, you.");
|
||||
}
|
||||
});
|
||||
|
||||
write("@inline");
|
||||
}
|
||||
|
||||
function firstSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
info("Current script url:\n" + gSources.selectedValue + "\n");
|
||||
info("Debugger editor text:\n" + gEditor.getText() + "\n");
|
||||
|
||||
ok(gFilteredFunctions.selectedValue,
|
||||
"An item should be selected in the filtered functions view");
|
||||
ok(gFilteredFunctions.selectedLabel,
|
||||
"An item should be selected in the filtered functions view");
|
||||
|
||||
let url = gSources.selectedValue;
|
||||
if (url.indexOf("-01.js") != -1) {
|
||||
|
||||
executeSoon(function() {
|
||||
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
|
||||
let expectedResults = [
|
||||
["test", "-01.js", "", 3, 9],
|
||||
["anonymousExpression", "-01.js", "test.prototype", 8, 2],
|
||||
["namedExpression" + s + "NAME", "-01.js", "test.prototype", 10, 2],
|
||||
["a_test", "-01.js", "foo", 21, 2],
|
||||
["n_test" + s + "x", "-01.js", "foo", 23, 2],
|
||||
["a_test", "-01.js", "foo.sub", 26, 4],
|
||||
["n_test" + s + "y", "-01.js", "foo.sub", 28, 4],
|
||||
["a_test", "-01.js", "foo.sub.sub", 31, 6],
|
||||
["n_test" + s + "z", "-01.js", "foo.sub.sub", 33, 6],
|
||||
["test_SAME_NAME", "-01.js", "foo.sub.sub.sub", 36, 8]
|
||||
]
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
gDebugger.SourceUtils.trimUrlLength(label + "()"),
|
||||
"The corect label (" + label + ") is currently selected.");
|
||||
ok(gFilteredFunctions.selectedItem.value.contains(value),
|
||||
"The corect value (" + value + ") is attached.");
|
||||
is(gFilteredFunctions.selectedItem.description, description,
|
||||
"The corect description (" + description + ") is currently shown.");
|
||||
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
|
||||
ok(gEditor.getCaretPosition().line == line &&
|
||||
gEditor.getCaretPosition().col == col,
|
||||
"The editor didn't jump to the correct line.");
|
||||
|
||||
ok(gSources.selectedLabel, label,
|
||||
"The current source isn't the correct one, according to the label.");
|
||||
ok(gSources.selectedValue, value,
|
||||
"The current source isn't the correct one, according to the value.");
|
||||
|
||||
EventUtils.sendKey("DOWN", gDebugger);
|
||||
}
|
||||
|
||||
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
|
||||
gEditor.getCaretPosition().col == expectedResults[0][4],
|
||||
"The editor didn't jump to the correct line again.");
|
||||
|
||||
executeSoon(callback);
|
||||
});
|
||||
} else {
|
||||
ok(false, "How did you get here? Go away, you.");
|
||||
}
|
||||
});
|
||||
|
||||
write("@");
|
||||
}
|
||||
|
||||
function secondSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
info("Current script url:\n" + gSources.selectedValue + "\n");
|
||||
info("Debugger editor text:\n" + gEditor.getText() + "\n");
|
||||
|
||||
ok(gFilteredFunctions.selectedValue,
|
||||
"An item should be selected in the filtered functions view");
|
||||
ok(gFilteredFunctions.selectedLabel,
|
||||
"An item should be selected in the filtered functions view");
|
||||
|
||||
let url = gSources.selectedValue;
|
||||
if (url.indexOf("-02.js") != -1) {
|
||||
|
||||
executeSoon(function() {
|
||||
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
|
||||
let expectedResults = [
|
||||
["test2", "-02.js", "", 3, 4],
|
||||
["test3" + s + "test3_NAME", "-02.js", "", 7, 4],
|
||||
["test4_SAME_NAME", "-02.js", "", 10, 4],
|
||||
["x" + s + "X", "-02.js", "test.prototype", 13, 0],
|
||||
["y" + s + "Y", "-02.js", "test.prototype.sub", 15, 0],
|
||||
["z" + s + "Z", "-02.js", "test.prototype.sub.sub", 17, 0],
|
||||
["t", "-02.js", "test.prototype.sub.sub.sub", 19, 0],
|
||||
["x", "-02.js", "", 19, 31],
|
||||
["y", "-02.js", "", 19, 40],
|
||||
["z", "-02.js", "", 19, 49]
|
||||
]
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
gDebugger.SourceUtils.trimUrlLength(label + "()"),
|
||||
"The corect label (" + label + ") is currently selected.");
|
||||
ok(gFilteredFunctions.selectedItem.value.contains(value),
|
||||
"The corect value (" + value + ") is attached.");
|
||||
is(gFilteredFunctions.selectedItem.description, description,
|
||||
"The corect description (" + description + ") is currently shown.");
|
||||
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
|
||||
ok(gEditor.getCaretPosition().line == line &&
|
||||
gEditor.getCaretPosition().col == col,
|
||||
"The editor didn't jump to the correct line.");
|
||||
|
||||
ok(gSources.selectedLabel, label,
|
||||
"The current source isn't the correct one, according to the label.");
|
||||
ok(gSources.selectedValue, value,
|
||||
"The current source isn't the correct one, according to the value.");
|
||||
|
||||
EventUtils.sendKey("DOWN", gDebugger);
|
||||
}
|
||||
|
||||
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
|
||||
gEditor.getCaretPosition().col == expectedResults[0][4],
|
||||
"The editor didn't jump to the correct line again.");
|
||||
|
||||
executeSoon(callback);
|
||||
});
|
||||
} else {
|
||||
ok(false, "How did you get here? Go away, you.");
|
||||
}
|
||||
});
|
||||
|
||||
write("@");
|
||||
}
|
||||
|
||||
function thirdSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
info("Current script url:\n" + gSources.selectedValue + "\n");
|
||||
info("Debugger editor text:\n" + gEditor.getText() + "\n");
|
||||
|
||||
ok(gFilteredFunctions.selectedValue,
|
||||
"An item should be selected in the filtered functions view");
|
||||
ok(gFilteredFunctions.selectedLabel,
|
||||
"An item should be selected in the filtered functions view");
|
||||
|
||||
let url = gSources.selectedValue;
|
||||
if (url.indexOf("-03.js") != -1) {
|
||||
|
||||
executeSoon(function() {
|
||||
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
|
||||
let expectedResults = [
|
||||
["namedEventListener", "-03.js", "", 3, 42],
|
||||
["a" + s + "A", "-03.js", "bar", 9, 4],
|
||||
["b" + s + "B", "-03.js", "bar.alpha", 14, 4],
|
||||
["c" + s + "C", "-03.js", "bar.alpha.beta", 19, 4],
|
||||
["d" + s + "D", "-03.js", "theta", 24, 4],
|
||||
["fun", "-03.js", "", 28, 6],
|
||||
["foo", "-03.js", "", 28, 12],
|
||||
["bar", "-03.js", "", 28, 18],
|
||||
["t_foo", "-03.js", "", 28, 24],
|
||||
["w_bar" + s + "baz", "-03.js", "window", 28, 37]
|
||||
];
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
gDebugger.SourceUtils.trimUrlLength(label + "()"),
|
||||
"The corect label (" + label + ") is currently selected.");
|
||||
ok(gFilteredFunctions.selectedItem.value.contains(value),
|
||||
"The corect value (" + value + ") is attached.");
|
||||
is(gFilteredFunctions.selectedItem.description, description,
|
||||
"The corect description (" + description + ") is currently shown.");
|
||||
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
|
||||
ok(gEditor.getCaretPosition().line == line &&
|
||||
gEditor.getCaretPosition().col == col,
|
||||
"The editor didn't jump to the correct line.");
|
||||
|
||||
ok(gSources.selectedLabel, label,
|
||||
"The current source isn't the correct one, according to the label.");
|
||||
ok(gSources.selectedValue, value,
|
||||
"The current source isn't the correct one, according to the value.");
|
||||
|
||||
EventUtils.sendKey("DOWN", gDebugger);
|
||||
}
|
||||
|
||||
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
|
||||
gEditor.getCaretPosition().col == expectedResults[0][4],
|
||||
"The editor didn't jump to the correct line again.");
|
||||
|
||||
executeSoon(callback);
|
||||
});
|
||||
} else {
|
||||
ok(false, "How did you get here? Go away, you.");
|
||||
}
|
||||
});
|
||||
|
||||
write("@");
|
||||
}
|
||||
|
||||
function filterSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
info("Current script url:\n" + gSources.selectedValue + "\n");
|
||||
info("Debugger editor text:\n" + gEditor.getText() + "\n");
|
||||
|
||||
ok(gFilteredFunctions.selectedValue,
|
||||
"An item should be selected in the filtered functions view");
|
||||
ok(gFilteredFunctions.selectedLabel,
|
||||
"An item should be selected in the filtered functions view");
|
||||
|
||||
let url = gSources.selectedValue;
|
||||
if (url.indexOf("-03.js") != -1) {
|
||||
|
||||
executeSoon(function() {
|
||||
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
|
||||
let expectedResults = [
|
||||
["namedEventListener", "-03.js", "", 3, 42],
|
||||
["a" + s + "A", "-03.js", "bar", 9, 4],
|
||||
["bar", "-03.js", "", 28, 18],
|
||||
["w_bar" + s + "baz", "-03.js", "window", 28, 37],
|
||||
["test3" + s + "test3_NAME", "-02.js", "", 7, 4],
|
||||
["test4_SAME_NAME", "-02.js", "", 10, 4],
|
||||
["anonymousExpression", "-01.js", "test.prototype", 8, 2],
|
||||
["namedExpression" + s + "NAME", "-01.js", "test.prototype", 10, 2],
|
||||
["a_test", "-01.js", "foo", 21, 2],
|
||||
["a_test", "-01.js", "foo.sub", 26, 4]
|
||||
];
|
||||
|
||||
for (let [label, value, description, line, col] of expectedResults) {
|
||||
is(gFilteredFunctions.selectedItem.label,
|
||||
gDebugger.SourceUtils.trimUrlLength(label + "()"),
|
||||
"The corect label (" + label + ") is currently selected.");
|
||||
ok(gFilteredFunctions.selectedItem.value.contains(value),
|
||||
"The corect value (" + value + ") is attached.");
|
||||
is(gFilteredFunctions.selectedItem.description, description,
|
||||
"The corect description (" + description + ") is currently shown.");
|
||||
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
|
||||
ok(gEditor.getCaretPosition().line == line &&
|
||||
gEditor.getCaretPosition().col == col,
|
||||
"The editor didn't jump to the correct line.");
|
||||
|
||||
ok(gSources.selectedLabel, label,
|
||||
"The current source isn't the correct one, according to the label.");
|
||||
ok(gSources.selectedValue, value,
|
||||
"The current source isn't the correct one, according to the value.");
|
||||
|
||||
EventUtils.sendKey("DOWN", gDebugger);
|
||||
}
|
||||
|
||||
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
|
||||
gEditor.getCaretPosition().col == expectedResults[0][4],
|
||||
"The editor didn't jump to the correct line again.");
|
||||
|
||||
executeSoon(callback);
|
||||
});
|
||||
} else {
|
||||
ok(false, "How did you get here? Go away, you.");
|
||||
}
|
||||
});
|
||||
|
||||
write("@a");
|
||||
}
|
||||
|
||||
function bogusSearch(callback) {
|
||||
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
|
||||
ok(true, "Popup was successfully hidden after no matches were found!");
|
||||
executeSoon(callback);
|
||||
});
|
||||
|
||||
write("@bogus");
|
||||
}
|
||||
|
||||
function anotherSearch(callback) {
|
||||
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
|
||||
ok(true, "Popup was successfully shown after some matches were found!");
|
||||
executeSoon(callback);
|
||||
});
|
||||
|
||||
write("@NAME");
|
||||
}
|
||||
|
||||
function emptySearch(callback) {
|
||||
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
|
||||
ok(true, "Popup was successfully hidden when nothing was searched!");
|
||||
executeSoon(callback);
|
||||
});
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
function showSource(label, callback) {
|
||||
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
executeSoon(callback);
|
||||
});
|
||||
gSources.selectedLabel = label;
|
||||
}
|
||||
|
||||
function saveSearch(callback) {
|
||||
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
executeSoon(callback);
|
||||
});
|
||||
if (Math.random() >= 0.5) {
|
||||
EventUtils.sendKey("RETURN", gDebugger);
|
||||
} else {
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gFilteredFunctions.selectedItem.target,
|
||||
gDebugger);
|
||||
}
|
||||
}
|
||||
|
||||
function waitForCaretPos(number, callback)
|
||||
{
|
||||
// Poll every few milliseconds until the source editor line is active.
|
||||
let count = 0;
|
||||
let intervalID = window.setInterval(function() {
|
||||
info("count: " + count + " ");
|
||||
info("caret: " + gEditor.getCaretPosition().line);
|
||||
if (++count > 50) {
|
||||
ok(false, "Timed out while polling for the line.");
|
||||
window.clearInterval(intervalID);
|
||||
return closeDebuggerAndFinish();
|
||||
}
|
||||
if (gEditor.getCaretPosition().line != number) {
|
||||
return;
|
||||
}
|
||||
// We got the source editor at the expected line, it's safe to callback.
|
||||
window.clearInterval(intervalID);
|
||||
callback();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
gSearchBox.focus();
|
||||
gSearchBox.value = "";
|
||||
}
|
||||
|
||||
function write(text) {
|
||||
clear();
|
||||
append(text);
|
||||
}
|
||||
|
||||
function backspace(times) {
|
||||
for (let i = 0; i < times; i++) {
|
||||
EventUtils.sendKey("BACK_SPACE", gDebugger);
|
||||
}
|
||||
}
|
||||
|
||||
function append(text) {
|
||||
gSearchBox.focus();
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
EventUtils.sendChar(text[i], gDebugger);
|
||||
}
|
||||
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
gSources = null;
|
||||
gSearchBox = null;
|
||||
gFilteredFunctions = null;
|
||||
});
|
@ -109,37 +109,30 @@ function doSearch() {
|
||||
|
||||
function testLocationChange()
|
||||
{
|
||||
let viewCleared = false;
|
||||
let cacheCleared = false;
|
||||
|
||||
function _maybeFinish() {
|
||||
if (viewCleared && cacheCleared) {
|
||||
closeDebuggerAndFinish();
|
||||
gDebugger.DebuggerController.client.addListener("tabNavigated", function onTabNavigated(aEvent, aPacket) {
|
||||
dump("tabNavigated state " + aPacket.state + "\n");
|
||||
if (aPacket.state == "start") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gDebugger.addEventListener("Debugger:GlobalSearch:ViewCleared", function _onViewCleared(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onViewCleared);
|
||||
gDebugger.DebuggerController.client.removeListener("tabNavigated", onTabNavigated);
|
||||
|
||||
is(gSearchView._container._list.childNodes.length, 0,
|
||||
"The global search pane shouldn't have any child nodes after a page navigation.");
|
||||
is(gSearchView._container._parent.hidden, true,
|
||||
"The global search pane shouldn't be visible after a page navigation.");
|
||||
is(gSearchView._splitter.hidden, true,
|
||||
"The global search pane splitter shouldn't be visible after a page navigation.");
|
||||
ok(true, "tabNavigated event was fired after location change.");
|
||||
info("Still attached to the tab.");
|
||||
|
||||
viewCleared = true;
|
||||
_maybeFinish();
|
||||
});
|
||||
executeSoon(function() {
|
||||
is(gSearchView._container._list.childNodes.length, 0,
|
||||
"The global search pane shouldn't have any child nodes after a page navigation.");
|
||||
is(gSearchView._container._parent.hidden, true,
|
||||
"The global search pane shouldn't be visible after a page navigation.");
|
||||
is(gSearchView._splitter.hidden, true,
|
||||
"The global search pane splitter shouldn't be visible after a page navigation.");
|
||||
|
||||
gDebugger.addEventListener("Debugger:GlobalSearch:CacheCleared", function _onCacheCleared(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onCacheCleared);
|
||||
is(gDebugger.DebuggerController.SourceScripts.getCache().length, 0,
|
||||
"The scripts sources cache for global searching should be cleared after a page navigation.")
|
||||
|
||||
is(gSearchView._cache.size, 0,
|
||||
"The scripts sources cache for global searching should be cleared after a page navigation.")
|
||||
|
||||
cacheCleared = true;
|
||||
_maybeFinish();
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
|
||||
content.location = TAB1_URL;
|
||||
|
@ -30,7 +30,6 @@ function test()
|
||||
Services.tm.currentThread.dispatch({ run: testScriptSearching }, 0);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function testScriptSearching() {
|
||||
@ -58,14 +57,14 @@ function firstSearch() {
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.labels[i]),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.values[i],
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.values[i]),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.values[i], 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].label,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.labels[i]),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.visibleItems[i].value,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.values[i]),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.values[i], 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gSources.labels[i],
|
||||
@ -75,7 +74,7 @@ function firstSearch() {
|
||||
}
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -135,14 +134,14 @@ function secondSearch() {
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].label),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.values[i],
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value, 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].label,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].label),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.visibleItems[i].value,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value, 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gSources.visibleItems[i].label,
|
||||
@ -152,7 +151,7 @@ function secondSearch() {
|
||||
}
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -175,7 +174,7 @@ function secondSearch() {
|
||||
ok(false, "How did you get here?");
|
||||
}
|
||||
}
|
||||
append("-0")
|
||||
write(".-0");
|
||||
}
|
||||
|
||||
function thirdSearch() {
|
||||
@ -212,14 +211,14 @@ function thirdSearch() {
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].label),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.values[i],
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value, 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].label,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].label),
|
||||
"The filtered sources view should have the correct labels.");
|
||||
is(gFilteredSources.visibleItems[i].value,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.visibleItems[i].value, 0, "start"),
|
||||
"The filtered sources view should have the correct values.");
|
||||
|
||||
is(gFilteredSources.visibleItems[i].attachment.fullLabel, gSources.visibleItems[i].label,
|
||||
@ -229,7 +228,7 @@ function thirdSearch() {
|
||||
}
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -252,7 +251,7 @@ function thirdSearch() {
|
||||
ok(false, "How did you get here?");
|
||||
}
|
||||
}
|
||||
backspace(1)
|
||||
write(".-");
|
||||
}
|
||||
|
||||
function goDown() {
|
||||
@ -266,7 +265,7 @@ function goDown() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -304,7 +303,7 @@ function goDownAgain() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -342,7 +341,7 @@ function goDownAndWrap() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -380,7 +379,7 @@ function goUpAndWrap() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -458,7 +457,7 @@ function clickAndSwitch() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -485,12 +484,12 @@ function clickAndSwitch() {
|
||||
}
|
||||
});
|
||||
|
||||
ok(gFilteredSources._container._parent.querySelectorAll(".dbg-source-item")[0]
|
||||
.classList.contains("dbg-source-item"),
|
||||
ok(gFilteredSources._container._parent.querySelectorAll(".results-panel-item")[0]
|
||||
.classList.contains("results-panel-item"),
|
||||
"The first visible item target isn't the correct one.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gFilteredSources._container._parent.querySelector(".dbg-source-item"),
|
||||
gFilteredSources._container._parent.querySelectorAll(".results-panel-item")[0],
|
||||
gDebugger);
|
||||
}
|
||||
|
||||
@ -545,7 +544,7 @@ function clickAndSwitchAgain() {
|
||||
"The filtered sources view should have 3 items visible.");
|
||||
|
||||
is(gFilteredSources.selectedValue,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue),
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedValue, 0, "start"),
|
||||
"The correct item should be selected in the filtered sources view");
|
||||
is(gFilteredSources.selectedLabel,
|
||||
gDebugger.SourceUtils.trimUrlLength(gSources.selectedLabel),
|
||||
@ -572,12 +571,12 @@ function clickAndSwitchAgain() {
|
||||
}
|
||||
});
|
||||
|
||||
ok(gFilteredSources._container._parent.querySelectorAll(".dbg-source-item")[2]
|
||||
.classList.contains("dbg-source-item"),
|
||||
ok(gFilteredSources._container._parent.querySelectorAll(".results-panel-item")[2]
|
||||
.classList.contains("results-panel-item"),
|
||||
"The first visible item target isn't the correct one.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gFilteredSources._container._parent.querySelectorAll(".dbg-source-item")[2],
|
||||
gFilteredSources._container._parent.querySelectorAll(".results-panel-item")[2],
|
||||
gDebugger);
|
||||
}
|
||||
|
||||
@ -672,12 +671,6 @@ function write(text) {
|
||||
append(text);
|
||||
}
|
||||
|
||||
function backspace(times) {
|
||||
for (let i = 0; i < times; i++) {
|
||||
EventUtils.sendKey("BACK_SPACE", gDebugger);
|
||||
}
|
||||
}
|
||||
|
||||
function append(text) {
|
||||
gSearchBox.focus();
|
||||
|
||||
|
201
browser/devtools/debugger/test/browser_dbg_sources-cache.js
Normal file
201
browser/devtools/debugger/test/browser_dbg_sources-cache.js
Normal file
@ -0,0 +1,201 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "browser_dbg_function-search-01.html";
|
||||
|
||||
/**
|
||||
* Tests if the sources cache knows how to cache sources when prompted.
|
||||
*/
|
||||
|
||||
let gPane = null;
|
||||
let gTab = null;
|
||||
let gDebuggee = null;
|
||||
let gDebugger = null;
|
||||
let gEditor = null;
|
||||
let gSources = null;
|
||||
let gControllerSources = null;
|
||||
let gPrevLabelsCache = null;
|
||||
let gPrevGroupsCache = null;
|
||||
const TOTAL_SOURCES = 3;
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gDebuggee = aDebuggee;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.panelWin;
|
||||
|
||||
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
|
||||
gDebugger.removeEventListener(aEvent.type, _onEvent);
|
||||
Services.tm.currentThread.dispatch({ run: testSourcesCache }, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testSourcesCache()
|
||||
{
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gControllerSources = gDebugger.DebuggerController.SourceScripts;
|
||||
|
||||
ok(gEditor.getText().contains("First source!"),
|
||||
"Editor text contents appears to be correct.");
|
||||
is(gSources.selectedLabel, "test-function-search-01.js",
|
||||
"The currently selected label in the sources container is correct.");
|
||||
ok(gSources.selectedValue.contains("test-function-search-01.js"),
|
||||
"The currently selected value in the sources container appears to be correct.");
|
||||
|
||||
is(gSources.itemCount, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " sources present in the sources list.");
|
||||
is(gSources.visibleItems.length, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " sources visible in the sources list.");
|
||||
is(gSources.labels.length, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " labels stored in the sources container model.")
|
||||
is(gSources.values.length, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " values stored in the sources container model.")
|
||||
|
||||
info("Source labels: " + gSources.labels.toSource());
|
||||
info("Source values: " + gSources.values.toSource());
|
||||
|
||||
is(gSources.labels.sort()[0], "test-function-search-01.js",
|
||||
"The first source label is correct.");
|
||||
ok(gSources.values.sort()[0].contains("test-function-search-01.js"),
|
||||
"The first source value appears to be correct.");
|
||||
|
||||
is(gSources.labels.sort()[1], "test-function-search-02.js",
|
||||
"The second source label is correct.");
|
||||
ok(gSources.values.sort()[1].contains("test-function-search-02.js"),
|
||||
"The second source value appears to be correct.");
|
||||
|
||||
is(gSources.labels.sort()[2], "test-function-search-03.js",
|
||||
"The third source label is correct.");
|
||||
ok(gSources.values.sort()[2].contains("test-function-search-03.js"),
|
||||
"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,
|
||||
"There should be " + TOTAL_SOURCES + " labels cached");
|
||||
is(gDebugger.SourceUtils._groupsCache.size, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " groups cached");
|
||||
|
||||
gPrevLabelsCache = gDebugger.SourceUtils._labelsCache;
|
||||
gPrevLabelsCache = gDebugger.SourceUtils._groupsCache;
|
||||
|
||||
fetchSources(function() {
|
||||
performReload(function() {
|
||||
closeDebuggerAndFinish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fetchSources(callback) {
|
||||
let fetches = 0;
|
||||
let timeouts = 0;
|
||||
|
||||
gControllerSources.fetchSources(gSources.values, {
|
||||
onFetch: function(aSource) {
|
||||
info("Fetched: " + aSource.url);
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function performReload(callback) {
|
||||
gDebugger.DebuggerController.client.addListener("tabNavigated", function onTabNavigated(aEvent, aPacket) {
|
||||
dump("tabNavigated state " + aPacket.state + "\n");
|
||||
if (aPacket.state == "start") {
|
||||
testStateBeforeReload();
|
||||
return;
|
||||
}
|
||||
|
||||
gDebugger.DebuggerController.client.removeListener("tabNavigated", onTabNavigated);
|
||||
|
||||
ok(true, "tabNavigated event was fired.");
|
||||
info("Still attached to the tab.");
|
||||
|
||||
testStateAfterReload();
|
||||
callback();
|
||||
});
|
||||
|
||||
gDebuggee.location.reload();
|
||||
}
|
||||
|
||||
function testStateBeforeReload() {
|
||||
is(gSources.itemCount, 0,
|
||||
"There should be no sources present in the sources list during reload.");
|
||||
is(gControllerSources.getCache().length, 0,
|
||||
"The sources cache should be empty during reload.");
|
||||
isnot(gDebugger.SourceUtils._labelsCache, gPrevLabelsCache,
|
||||
"The labels cache has been refreshed during reload.")
|
||||
isnot(gDebugger.SourceUtils._groupsCache, gPrevGroupsCache,
|
||||
"The groups cache has been refreshed during reload.")
|
||||
is(gDebugger.SourceUtils._labelsCache.size, 0,
|
||||
"There should be no labels cached during reload");
|
||||
is(gDebugger.SourceUtils._groupsCache.size, 0,
|
||||
"There should be no groups cached during reload");
|
||||
}
|
||||
|
||||
function testStateAfterReload() {
|
||||
is(gSources.itemCount, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " sources present in the sources list.");
|
||||
is(gDebugger.SourceUtils._labelsCache.size, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " labels cached after reload.");
|
||||
is(gDebugger.SourceUtils._groupsCache.size, TOTAL_SOURCES,
|
||||
"There should be " + TOTAL_SOURCES + " groups cached after reload.");
|
||||
}
|
||||
|
||||
function testCacheIntegrity() {
|
||||
let cache = gControllerSources.getCache();
|
||||
isnot(cache.length, 0,
|
||||
"The sources cache should not be empty at this point.");
|
||||
|
||||
for (let source of cache) {
|
||||
let index = cache.indexOf(source);
|
||||
|
||||
ok(source[0].contains("test-function-search-0" + (index + 1)),
|
||||
"Found a source url cached correctly (" + index + ")");
|
||||
ok(source[1].contains(
|
||||
["First source!", "Second source!", "Third source!"][index]),
|
||||
"Found a source's text contents cached correctly (" + index + ")");
|
||||
|
||||
info("Cached source url at " + index + ": " + source[0]);
|
||||
info("Cached source text at " + index + ": " + source[1]);
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebuggee = null;
|
||||
gDebugger = null;
|
||||
gEditor = null;
|
||||
gSources = null;
|
||||
gControllerSources = null;
|
||||
gPrevLabelsCache = null;
|
||||
gPrevGroupsCache = null;
|
||||
});
|
42
browser/devtools/debugger/test/test-function-search-01.js
Normal file
42
browser/devtools/debugger/test/test-function-search-01.js
Normal file
@ -0,0 +1,42 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
// Blah! First source!
|
||||
}
|
||||
|
||||
test.prototype = {
|
||||
anonymousExpression: function() {
|
||||
},
|
||||
namedExpression: function NAME() {
|
||||
},
|
||||
sub: {
|
||||
sub: {
|
||||
sub: {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var foo = {
|
||||
a_test: function() {
|
||||
},
|
||||
n_test: function x() {
|
||||
},
|
||||
sub: {
|
||||
a_test: function() {
|
||||
},
|
||||
n_test: function y() {
|
||||
},
|
||||
sub: {
|
||||
a_test: function() {
|
||||
},
|
||||
n_test: function z() {
|
||||
},
|
||||
sub: {
|
||||
test_SAME_NAME: function test_SAME_NAME() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
21
browser/devtools/debugger/test/test-function-search-02.js
Normal file
21
browser/devtools/debugger/test/test-function-search-02.js
Normal file
@ -0,0 +1,21 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var test2 = function() {
|
||||
// Blah! Second source!
|
||||
}
|
||||
|
||||
var test3 = function test3_NAME() {
|
||||
}
|
||||
|
||||
var test4_SAME_NAME = function test4_SAME_NAME() {
|
||||
}
|
||||
|
||||
test.prototype.x = function X() {
|
||||
};
|
||||
test.prototype.sub.y = function Y() {
|
||||
};
|
||||
test.prototype.sub.sub.z = function Z() {
|
||||
};
|
||||
test.prototype.sub.sub.sub.t = this.x = this.y = this.z = function() {
|
||||
};
|
32
browser/devtools/debugger/test/test-function-search-03.js
Normal file
32
browser/devtools/debugger/test/test-function-search-03.js
Normal file
@ -0,0 +1,32 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
window.addEventListener("bogus", function namedEventListener() {
|
||||
// Blah! Third source!
|
||||
});
|
||||
|
||||
try {
|
||||
var bar = foo.sub.sub.test({
|
||||
a: function A() {
|
||||
}
|
||||
});
|
||||
|
||||
bar.alpha = foo.sub.sub.test({
|
||||
b: function B() {
|
||||
}
|
||||
});
|
||||
|
||||
bar.alpha.beta = new X(Y(Z(foo.sub.sub.test({
|
||||
c: function C() {
|
||||
}
|
||||
}))));
|
||||
|
||||
this.theta = new X(new Y(new Z(new foo.sub.sub.test({
|
||||
d: function D() {
|
||||
}
|
||||
}))));
|
||||
|
||||
var fun = foo = bar = this.t_foo = window.w_bar = function baz() {};
|
||||
|
||||
} catch (e) {
|
||||
}
|
2226
browser/devtools/shared/Parser.jsm
Normal file
2226
browser/devtools/shared/Parser.jsm
Normal file
File diff suppressed because it is too large
Load Diff
@ -73,12 +73,19 @@
|
||||
- in the source editor's context menu for the scripts search operation. -->
|
||||
<!ENTITY debuggerUI.searchFile "Filter scripts">
|
||||
<!ENTITY debuggerUI.searchFile.key "P">
|
||||
<!ENTITY debuggerUI.searchFile.altkey "O">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.searchGlobal): This is the text that appears
|
||||
- in the source editor's context menu for the global search operation. -->
|
||||
<!ENTITY debuggerUI.searchGlobal "Search in all files">
|
||||
<!ENTITY debuggerUI.searchGlobal.key "F">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.searchFunction): This is the text that appears
|
||||
- in the source editor's context menu for the function search operation. -->
|
||||
<!ENTITY debuggerUI.searchFunction "Search for function definition">
|
||||
<!ENTITY debuggerUI.searchFunction.key "D">
|
||||
<!ENTITY debuggerUI.searchFunction.altkey "O">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.searchToken): This is the text that appears
|
||||
- in the source editor's context menu for the token search operation. -->
|
||||
<!ENTITY debuggerUI.searchToken "Find">
|
||||
|
@ -120,6 +120,10 @@ emptyVariablesFilterText=Filter variables
|
||||
# filter panel popup for the global search operation.
|
||||
searchPanelGlobal=Search in all files (%S)
|
||||
|
||||
# LOCALIZATION NOTE (searchPanelFunction): This is the text that appears in the
|
||||
# filter panel popup for the function search operation.
|
||||
searchPanelFunction=Search for function definition (%S)
|
||||
|
||||
# LOCALIZATION NOTE (searchPanelToken): This is the text that appears in the
|
||||
# filter panel popup for the token search operation.
|
||||
searchPanelToken=Find in this file (%S)
|
||||
@ -206,3 +210,8 @@ variablesSeparatorLabel=:
|
||||
# LOCALIZATION NOTE (watchExpressionsSeparatorLabel): The text that is displayed
|
||||
# in the watch expressions list as a separator between the code and evaluation.
|
||||
watchExpressionsSeparatorLabel=\ →
|
||||
|
||||
# LOCALIZATION NOTE (functionSearchSeparatorLabel): The text that is displayed
|
||||
# in the functions search panel as a separator between function's inferred name
|
||||
# and its real name (if available).
|
||||
functionSearchSeparatorLabel=←
|
||||
|
@ -138,14 +138,14 @@
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Filtering results panel */
|
||||
/* Searchbox results panel */
|
||||
|
||||
#filtered-sources-panel {
|
||||
.results-panel {
|
||||
padding: 4px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dbg-source-item {
|
||||
.results-panel-item {
|
||||
background: #f4f4f4;
|
||||
border: 1px solid #ddd;
|
||||
border-top-color: #fff;
|
||||
@ -153,31 +153,37 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dbg-source-item:first-of-type {
|
||||
.results-panel-item:first-of-type {
|
||||
border-top-color: #ddd;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.dbg-source-item:last-of-type {
|
||||
.results-panel-item:last-of-type {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:only-of-type {
|
||||
.results-panel-item:only-of-type {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:not(.selected):not(:hover) {
|
||||
.results-panel-item:not(.selected):not(:hover) {
|
||||
text-shadow: 0 1px #fff;
|
||||
}
|
||||
|
||||
.dbg-source-item-name {
|
||||
.results-panel-item-pre {
|
||||
-moz-margin-end: 5px !important;
|
||||
color: #444;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.results-panel-item-name {
|
||||
color: #111;
|
||||
font-weight: 600;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.dbg-source-item-details {
|
||||
color: #777;
|
||||
.results-panel-item-details {
|
||||
color: #7f7f7f;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
@ -140,14 +140,14 @@
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Filtering results panel */
|
||||
/* Searchbox results panel */
|
||||
|
||||
#filtered-sources-panel {
|
||||
.results-panel {
|
||||
padding: 4px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dbg-source-item {
|
||||
.results-panel-item {
|
||||
background: #f4f4f4;
|
||||
border: 1px solid #ddd;
|
||||
border-top-color: #fff;
|
||||
@ -155,31 +155,37 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dbg-source-item:first-of-type {
|
||||
.results-panel-item:first-of-type {
|
||||
border-top-color: #ddd;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.dbg-source-item:last-of-type {
|
||||
.results-panel-item:last-of-type {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:only-of-type {
|
||||
.results-panel-item:only-of-type {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:not(.selected):not(:hover) {
|
||||
.results-panel-item:not(.selected):not(:hover) {
|
||||
text-shadow: 0 1px #fff;
|
||||
}
|
||||
|
||||
.dbg-source-item-name {
|
||||
.results-panel-item-pre {
|
||||
-moz-margin-end: 5px !important;
|
||||
color: #444;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.results-panel-item-name {
|
||||
color: #111;
|
||||
font-weight: 600;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.dbg-source-item-details {
|
||||
color: #777;
|
||||
.results-panel-item-details {
|
||||
color: #7f7f7f;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
@ -138,14 +138,14 @@
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Filtering results panel */
|
||||
/* Searchbox results panel */
|
||||
|
||||
#filtered-sources-panel {
|
||||
.results-panel {
|
||||
padding: 4px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.dbg-source-item {
|
||||
.results-panel-item {
|
||||
background: #f4f4f4;
|
||||
border: 1px solid #ddd;
|
||||
border-top-color: #fff;
|
||||
@ -153,31 +153,37 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dbg-source-item:first-of-type {
|
||||
.results-panel-item:first-of-type {
|
||||
border-top-color: #ddd;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.dbg-source-item:last-of-type {
|
||||
.results-panel-item:last-of-type {
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:only-of-type {
|
||||
.results-panel-item:only-of-type {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dbg-source-item:not(.selected):not(:hover) {
|
||||
.results-panel-item:not(.selected):not(:hover) {
|
||||
text-shadow: 0 1px #fff;
|
||||
}
|
||||
|
||||
.dbg-source-item-name {
|
||||
.results-panel-item-pre {
|
||||
-moz-margin-end: 5px !important;
|
||||
color: #444;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.results-panel-item-name {
|
||||
color: #111;
|
||||
font-weight: 600;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
.dbg-source-item-details {
|
||||
color: #777;
|
||||
.results-panel-item-details {
|
||||
color: #7f7f7f;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user