Bug 793375 - Search operator for finding a variable in scope(s) while the debugger is paused, r=past

This commit is contained in:
Victor Porof 2012-11-04 01:01:05 +02:00
parent 21fe763a1d
commit ce3c4d522a
15 changed files with 781 additions and 84 deletions

View File

@ -1040,7 +1040,8 @@ pref("devtools.debugger.ui.remote-win.height", 400);
pref("devtools.debugger.ui.stackframes-width", 200); pref("devtools.debugger.ui.stackframes-width", 200);
pref("devtools.debugger.ui.variables-width", 300); pref("devtools.debugger.ui.variables-width", 300);
pref("devtools.debugger.ui.panes-visible-on-startup", false); pref("devtools.debugger.ui.panes-visible-on-startup", false);
pref("devtools.debugger.ui.non-enum-visible", true); pref("devtools.debugger.ui.variables-non-enum-visible", true);
pref("devtools.debugger.ui.variables-searchbox-visible", false);
// Enable the style inspector // Enable the style inspector
pref("devtools.styleinspector.enabled", true); pref("devtools.styleinspector.enabled", true);

View File

@ -185,6 +185,16 @@ VariablesView.prototype = {
this._searchboxNode = null; this._searchboxNode = null;
}, },
/**
* Sets if the variable and property searching is enabled.
*/
set searchEnabled(aFlag) aFlag ? this.enableSearch() : this.disableSearch(),
/**
* Gets if the variable and property searching is enabled.
*/
get searchEnabled() !!this._searchboxContainer,
/** /**
* Performs a case insensitive search for variables or properties matching * Performs a case insensitive search for variables or properties matching
* the query, and hides non-matched items. * the query, and hides non-matched items.
@ -193,10 +203,28 @@ VariablesView.prototype = {
* The variable or property to search for. * The variable or property to search for.
*/ */
performSearch: function VV_performSerch(aQuery) { performSearch: function VV_performSerch(aQuery) {
let lowerCaseQuery = aQuery.toLowerCase(); if (!aQuery) {
for (let [_, item] of this._currHierarchy) {
item._match = true;
}
} else {
for (let [_, scope] in this) {
scope._performSearch(aQuery.toLowerCase());
}
}
},
/**
* Expands the first search results in this container.
*/
expandFirstSearchResults: function VV_expandFirstSearchResults() {
for (let [_, scope] in this) { for (let [_, scope] in this) {
scope._performSearch(lowerCaseQuery); for (let [_, variable] in scope) {
if (variable._isMatch) {
variable.expand();
break;
}
}
} }
}, },
@ -406,7 +434,7 @@ Scope.prototype = {
* Pass true to not show an opening animation. * Pass true to not show an opening animation.
*/ */
expand: function S_expand(aSkipAnimationFlag) { expand: function S_expand(aSkipAnimationFlag) {
if (this._locked) { if (this._isExpanded || this._locked) {
return; return;
} }
if (this._variablesView._enumVisible) { if (this._variablesView._enumVisible) {
@ -431,7 +459,7 @@ Scope.prototype = {
* Collapses the scope, hiding all the added details. * Collapses the scope, hiding all the added details.
*/ */
collapse: function S_collapse() { collapse: function S_collapse() {
if (this._locked) { if (!this._isExpanded || this._locked) {
return; return;
} }
this._arrow.removeAttribute("open"); this._arrow.removeAttribute("open");
@ -486,12 +514,6 @@ Scope.prototype = {
*/ */
get expanded() this._isExpanded, get expanded() this._isExpanded,
/**
* Returns if this element was ever toggled.
* @return boolean
*/
get toggled() this._wasToggled,
/** /**
* Gets the twisty visibility state. * Gets the twisty visibility state.
* @return boolean * @return boolean
@ -651,17 +673,17 @@ Scope.prototype = {
// Non-matched variables or properties require a corresponding attribute. // Non-matched variables or properties require a corresponding attribute.
if (!lowerCaseName.contains(aLowerCaseQuery) && if (!lowerCaseName.contains(aLowerCaseQuery) &&
!lowerCaseValue.contains(aLowerCaseQuery)) { !lowerCaseValue.contains(aLowerCaseQuery)) {
variable.target.setAttribute("non-match", ""); variable._match = false;
} }
// Variable or property is matched. // Variable or property is matched.
else { else {
variable.target.removeAttribute("non-match"); variable._match = true;
// If the variable was ever expanded, there's a possibility it may // If the variable was ever expanded, there's a possibility it may
// contain some matched properties, so make sure they're visible // contain some matched properties, so make sure they're visible
// ("expand downwards"). // ("expand downwards").
if (variable.toggled) { if (variable._wasToggled) {
variable.expand(true); variable.expand(true);
} }
@ -675,13 +697,32 @@ Scope.prototype = {
variable instanceof Property)) { variable instanceof Property)) {
// Show and expand the parent, as it is certainly accessible. // Show and expand the parent, as it is certainly accessible.
variable.target.removeAttribute("non-match"); variable._match = true;
variable.expand(true); variable.expand(true);
} }
} }
// Proceed with the search recursively inside this variable or property. // Proceed with the search recursively inside this variable or property.
currentObject._performSearch(aLowerCaseQuery); if (variable._wasToggled || variable.expanded || variable.getter || variable.setter) {
currentObject._performSearch(aLowerCaseQuery);
}
}
},
/**
* Sets if this object instance is a match or non-match.
* @param boolean aStatus
*/
set _match(aStatus) {
if (this._isMatch == aStatus) {
return;
}
if (aStatus) {
this._isMatch = true;
this.target.removeAttribute("non-match");
} else {
this._isMatch = false;
this.target.setAttribute("non-match", "");
} }
}, },
@ -725,6 +766,7 @@ Scope.prototype = {
_isExpanded: false, _isExpanded: false,
_wasToggled: false, _wasToggled: false,
_isArrowVisible: true, _isArrowVisible: true,
_isMatch: true,
_store: null, _store: null,
_idString: "", _idString: "",
_nameString: "", _nameString: "",
@ -818,6 +860,16 @@ create({ constructor: Variable, proto: Scope.prototype }, {
} }
}, },
/**
* Returns this variable's getter from the descriptor if available,
*/
get getter() this._initialDescriptor.get,
/**
* Returns this variable's getter from the descriptor if available,
*/
get setter() this._initialDescriptor.set,
/** /**
* Sets the specific grip for this variable. * Sets the specific grip for this variable.
* The grip should contain the value or the type & class, as defined in the * The grip should contain the value or the type & class, as defined in the

View File

@ -1248,7 +1248,8 @@ XPCOMUtils.defineLazyGetter(L10N, "ellipsis", function() {
const STACKFRAMES_WIDTH = "devtools.debugger.ui.stackframes-width"; const STACKFRAMES_WIDTH = "devtools.debugger.ui.stackframes-width";
const VARIABLES_WIDTH = "devtools.debugger.ui.variables-width"; const VARIABLES_WIDTH = "devtools.debugger.ui.variables-width";
const PANES_VISIBLE_ON_STARTUP = "devtools.debugger.ui.panes-visible-on-startup"; const PANES_VISIBLE_ON_STARTUP = "devtools.debugger.ui.panes-visible-on-startup";
const NON_ENUM_VISIBLE = "devtools.debugger.ui.non-enum-visible"; const VARIABLES_NON_ENUM_VISIBLE = "devtools.debugger.ui.variables-non-enum-visible";
const VARIABLES_SEARCHBOX_VISIBLE = "devtools.debugger.ui.variables-searchbox-visible";
const REMOTE_HOST = "devtools.debugger.remote-host"; const REMOTE_HOST = "devtools.debugger.remote-host";
const REMOTE_PORT = "devtools.debugger.remote-port"; const REMOTE_PORT = "devtools.debugger.remote-port";
const REMOTE_AUTO_CONNECT = "devtools.debugger.remote-autoconnect"; const REMOTE_AUTO_CONNECT = "devtools.debugger.remote-autoconnect";
@ -1324,11 +1325,11 @@ let Prefs = {
* properties and variables in the scope view. * properties and variables in the scope view.
* @return boolean * @return boolean
*/ */
get nonEnumVisible() { get variablesNonEnumVisible() {
if (this._nonEnumVisible === undefined) { if (this._varNonEnum === undefined) {
this._nonEnumVisible = Services.prefs.getBoolPref(NON_ENUM_VISIBLE); this._varNonEnum = Services.prefs.getBoolPref(VARIABLES_NON_ENUM_VISIBLE);
} }
return this._nonEnumVisible; return this._varNonEnum;
}, },
/** /**
@ -1336,9 +1337,29 @@ let Prefs = {
* properties and variables in the scope view. * properties and variables in the scope view.
* @param boolean value * @param boolean value
*/ */
set nonEnumVisible(value) { set variablesNonEnumVisible(value) {
Services.prefs.setBoolPref(NON_ENUM_VISIBLE, value); Services.prefs.setBoolPref(VARIABLES_NON_ENUM_VISIBLE, value);
this._nonEnumVisible = value; this._varNonEnum = value;
},
/**
* Gets a flag specifying if the a variables searchbox should be shown.
* @return boolean
*/
get variablesSearchboxVisible() {
if (this._varSearchbox === undefined) {
this._varSearchbox = Services.prefs.getBoolPref(VARIABLES_SEARCHBOX_VISIBLE);
}
return this._varSearchbox;
},
/**
* Sets a flag specifying if the a variables searchbox should be shown.
* @param boolean value
*/
set variablesSearchboxVisible(value) {
Services.prefs.setBoolPref(VARIABLES_SEARCHBOX_VISIBLE, value);
this._varSearchbox = value;
}, },
/** /**

View File

@ -199,7 +199,8 @@ function OptionsView() {
dumpn("OptionsView was instantiated"); dumpn("OptionsView was instantiated");
this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this); this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this); this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
this._toggleShowNonEnum = this._toggleShowNonEnum.bind(this); this._toggleShowVariablesNonEnum = this._toggleShowVariablesNonEnum.bind(this);
this._toggleShowVariablesSearchbox = this._toggleShowVariablesSearchbox.bind(this);
} }
OptionsView.prototype = { OptionsView.prototype = {
@ -211,11 +212,13 @@ OptionsView.prototype = {
this._button = document.getElementById("debugger-options"); this._button = document.getElementById("debugger-options");
this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions"); this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup"); this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
this._showNonEnumItem = document.getElementById("show-nonenum"); this._showVariablesNonEnumItem = document.getElementById("show-vars-nonenum");
this._showVariablesSearchboxItem = document.getElementById("show-vars-searchbox");
this._pauseOnExceptionsItem.setAttribute("checked", "false"); this._pauseOnExceptionsItem.setAttribute("checked", "false");
this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup); this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
this._showNonEnumItem.setAttribute("checked", Prefs.nonEnumVisible); this._showVariablesNonEnumItem.setAttribute("checked", Prefs.variablesNonEnumVisible);
this._showVariablesSearchboxItem.setAttribute("checked", Prefs.variablesSearchboxVisible);
}, },
/** /**
@ -259,15 +262,24 @@ OptionsView.prototype = {
/** /**
* Listener handling the 'show non-enumerables' menuitem command. * Listener handling the 'show non-enumerables' menuitem command.
*/ */
_toggleShowNonEnum: function DVO__toggleShowNonEnum() { _toggleShowVariablesNonEnum: function DVO__toggleShowVariablesNonEnum() {
DebuggerView.Variables.nonEnumVisible = Prefs.nonEnumVisible = DebuggerView.Variables.nonEnumVisible = Prefs.variablesNonEnumVisible =
this._showNonEnumItem.getAttribute("checked") == "true"; this._showVariablesNonEnumItem.getAttribute("checked") == "true";
},
/**
* Listener handling the 'show variables searchbox' menuitem command.
*/
_toggleShowVariablesSearchbox: function DVO__toggleShowVariablesSearchbox() {
DebuggerView.Variables.searchEnabled = Prefs.variablesSearchboxVisible =
this._showVariablesSearchboxItem.getAttribute("checked") == "true";
}, },
_button: null, _button: null,
_pauseOnExceptionsItem: null, _pauseOnExceptionsItem: null,
_showPanesOnStartupItem: null, _showPanesOnStartupItem: null,
_showNonEnumItem: null _showVariablesNonEnumItem: null,
_showVariablesSearchboxItem: null
}; };
/** /**
@ -562,11 +574,14 @@ FilterView.prototype = {
this._tokenOperatorLabel = document.getElementById("token-operator-label"); this._tokenOperatorLabel = document.getElementById("token-operator-label");
this._lineOperatorButton = document.getElementById("line-operator-button"); this._lineOperatorButton = document.getElementById("line-operator-button");
this._lineOperatorLabel = document.getElementById("line-operator-label"); this._lineOperatorLabel = document.getElementById("line-operator-label");
this._variableOperatorButton = document.getElementById("variable-operator-button");
this._variableOperatorLabel = document.getElementById("variable-operator-label");
this._globalSearchKey = LayoutHelpers.prettyKey(document.getElementById("globalSearchKey")); this._globalSearchKey = LayoutHelpers.prettyKey(document.getElementById("globalSearchKey"));
this._fileSearchKey = LayoutHelpers.prettyKey(document.getElementById("fileSearchKey")); this._fileSearchKey = LayoutHelpers.prettyKey(document.getElementById("fileSearchKey"));
this._lineSearchKey = LayoutHelpers.prettyKey(document.getElementById("lineSearchKey")); this._lineSearchKey = LayoutHelpers.prettyKey(document.getElementById("lineSearchKey"));
this._tokenSearchKey = LayoutHelpers.prettyKey(document.getElementById("tokenSearchKey")); this._tokenSearchKey = LayoutHelpers.prettyKey(document.getElementById("tokenSearchKey"));
this._variableSearchKey = LayoutHelpers.prettyKey(document.getElementById("variableSearchKey"));
this._searchbox.addEventListener("click", this._onClick, false); this._searchbox.addEventListener("click", this._onClick, false);
this._searchbox.addEventListener("select", this._onSearch, false); this._searchbox.addEventListener("select", this._onSearch, false);
@ -577,6 +592,7 @@ FilterView.prototype = {
this._globalOperatorButton.setAttribute("label", SEARCH_GLOBAL_FLAG); this._globalOperatorButton.setAttribute("label", SEARCH_GLOBAL_FLAG);
this._tokenOperatorButton.setAttribute("label", SEARCH_TOKEN_FLAG); this._tokenOperatorButton.setAttribute("label", SEARCH_TOKEN_FLAG);
this._lineOperatorButton.setAttribute("label", SEARCH_LINE_FLAG); this._lineOperatorButton.setAttribute("label", SEARCH_LINE_FLAG);
this._variableOperatorButton.setAttribute("label", SEARCH_VARIABLE_FLAG);
this._globalOperatorLabel.setAttribute("value", this._globalOperatorLabel.setAttribute("value",
L10N.getFormatStr("searchPanelGlobal", [this._globalSearchKey])); L10N.getFormatStr("searchPanelGlobal", [this._globalSearchKey]));
@ -584,6 +600,8 @@ FilterView.prototype = {
L10N.getFormatStr("searchPanelToken", [this._tokenSearchKey])); L10N.getFormatStr("searchPanelToken", [this._tokenSearchKey]));
this._lineOperatorLabel.setAttribute("value", this._lineOperatorLabel.setAttribute("value",
L10N.getFormatStr("searchPanelLine", [this._lineSearchKey])); L10N.getFormatStr("searchPanelLine", [this._lineSearchKey]));
this._variableOperatorLabel.setAttribute("value",
L10N.getFormatStr("searchPanelVariable", [this._variableSearchKey]));
// TODO: bug 806775 // TODO: bug 806775
// if (window._isChromeDebugger) { // if (window._isChromeDebugger) {
@ -628,16 +646,17 @@ FilterView.prototype = {
* @return array * @return array
*/ */
get searchboxInfo() { get searchboxInfo() {
let file, line, token, global; let file, line, token, isGlobal, isVariable;
let rawValue = this._searchbox.value; let rawValue = this._searchbox.value;
let rawLength = rawValue.length; let rawLength = rawValue.length;
let globalFlagIndex = rawValue.indexOf(SEARCH_GLOBAL_FLAG); let globalFlagIndex = rawValue.indexOf(SEARCH_GLOBAL_FLAG);
let variableFlagIndex = rawValue.indexOf(SEARCH_VARIABLE_FLAG);
let lineFlagIndex = rawValue.lastIndexOf(SEARCH_LINE_FLAG); let lineFlagIndex = rawValue.lastIndexOf(SEARCH_LINE_FLAG);
let tokenFlagIndex = rawValue.lastIndexOf(SEARCH_TOKEN_FLAG); let tokenFlagIndex = rawValue.lastIndexOf(SEARCH_TOKEN_FLAG);
// This is not a global search, allow file or line flags. // This is not a global or variable search, allow file or line flags.
if (globalFlagIndex != 0) { if (globalFlagIndex != 0 && variableFlagIndex != 0) {
let fileEnd = lineFlagIndex != -1 let fileEnd = lineFlagIndex != -1
? lineFlagIndex ? lineFlagIndex
: tokenFlagIndex != -1 ? tokenFlagIndex : rawLength; : tokenFlagIndex != -1 ? tokenFlagIndex : rawLength;
@ -649,17 +668,27 @@ FilterView.prototype = {
file = rawValue.slice(0, fileEnd); file = rawValue.slice(0, fileEnd);
line = ~~(rawValue.slice(fileEnd + 1, lineEnd)) || -1; line = ~~(rawValue.slice(fileEnd + 1, lineEnd)) || -1;
token = rawValue.slice(lineEnd + 1); token = rawValue.slice(lineEnd + 1);
global = false; isGlobal = false;
isVariable = false;
} }
// Global searches dissalow the use of file or line flags. // Global searches dissalow the use of file or line flags.
else { else if (globalFlagIndex == 0) {
file = ""; file = "";
line = -1; line = -1;
token = rawValue.slice(1); token = rawValue.slice(1);
global = true; isGlobal = true;
isVariable = false;
}
// Variable searches dissalow the use of file or line flags.
else if (variableFlagIndex == 0) {
file = "";
line = -1;
token = rawValue.slice(1);
isGlobal = false;
isVariable = true;
} }
return [file, line, token, global]; return [file, line, token, isGlobal, isVariable];
}, },
/** /**
@ -787,25 +816,33 @@ FilterView.prototype = {
*/ */
_onSearch: function DVF__onScriptsSearch() { _onSearch: function DVF__onScriptsSearch() {
this._searchboxPanel.hidePopup(); this._searchboxPanel.hidePopup();
let [file, line, token, global] = this.searchboxInfo; let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
// If this is a global search, schedule it for when the user stops typing, // If this is a global search, schedule it for when the user stops typing,
// or hide the corresponding pane otherwise. // or hide the corresponding pane otherwise.
if (global) { if (isGlobal) {
DebuggerView.GlobalSearch.scheduleSearch(); DebuggerView.GlobalSearch.scheduleSearch();
} else { return;
DebuggerView.GlobalSearch.clearView();
this._performFileSearch(file);
this._performLineSearch(line);
this._performTokenSearch(token);
} }
// If this is a variable search, defer the action to the corresponding
// variables view instance.
if (isVariable) {
DebuggerView.Variables.performSearch(token);
return;
}
DebuggerView.GlobalSearch.clearView();
this._performFileSearch(file);
this._performLineSearch(line);
this._performTokenSearch(token);
}, },
/** /**
* The key press listener for the search container. * The key press listener for the search container.
*/ */
_onKeyPress: function DVF__onScriptsKeyPress(e) { _onKeyPress: function DVF__onScriptsKeyPress(e) {
let [file, line, token, global] = this.searchboxInfo; let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
let action; let action;
switch (e.keyCode) { switch (e.keyCode) {
@ -835,18 +872,26 @@ FilterView.prototype = {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (global) { // Perform a global search based on the specified operator.
if (isGlobal) {
if (DebuggerView.GlobalSearch.hidden) { if (DebuggerView.GlobalSearch.hidden) {
DebuggerView.GlobalSearch.scheduleSearch(); DebuggerView.GlobalSearch.scheduleSearch();
} else { } else {
DebuggerView.GlobalSearch[["focusNextMatch", "focusPrevMatch"][action]](); DebuggerView.GlobalSearch[["focusNextMatch", "focusPrevMatch"][action]]();
} }
} else { return;
let editor = DebuggerView.editor; }
let offset = editor[["findNext", "findPrevious"][action]](true);
if (offset > -1) { // Perform a variable search based on the specified operator.
editor.setSelection(offset, offset + token.length) if (isVariable) {
} DebuggerView.Variables.expandFirstSearchResults();
return;
}
let editor = DebuggerView.editor;
let offset = editor[["findNext", "findPrevious"][action]](true);
if (offset > -1) {
editor.setSelection(offset, offset + token.length)
} }
}, },
@ -855,6 +900,7 @@ FilterView.prototype = {
*/ */
_onBlur: function DVF__onBlur() { _onBlur: function DVF__onBlur() {
DebuggerView.GlobalSearch.clearView(); DebuggerView.GlobalSearch.clearView();
DebuggerView.Variables.performSearch(null);
this._searchboxPanel.hidePopup(); this._searchboxPanel.hidePopup();
}, },
@ -902,6 +948,14 @@ FilterView.prototype = {
this._searchboxPanel.hidePopup(); this._searchboxPanel.hidePopup();
}, },
/**
* Called when the variable search filter key sequence was pressed.
*/
_doVariableSearch: function DVF__doVariableSearch() {
this._doSearch(SEARCH_VARIABLE_FLAG);
this._searchboxPanel.hidePopup();
},
_searchbox: null, _searchbox: null,
_searchboxPanel: null, _searchboxPanel: null,
_globalOperatorButton: null, _globalOperatorButton: null,

View File

@ -15,6 +15,7 @@ const GLOBAL_SEARCH_ACTION_DELAY = 150; // ms
const SEARCH_GLOBAL_FLAG = "!"; const SEARCH_GLOBAL_FLAG = "!";
const SEARCH_LINE_FLAG = ":"; const SEARCH_LINE_FLAG = ":";
const SEARCH_TOKEN_FLAG = "#"; const SEARCH_TOKEN_FLAG = "#";
const SEARCH_VARIABLE_FLAG = "*";
/** /**
* Object defining the debugger view components. * Object defining the debugger view components.
@ -38,10 +39,10 @@ let DebuggerView = {
this.GlobalSearch.initialize(); this.GlobalSearch.initialize();
this.Variables = new VariablesView(document.getElementById("variables")); this.Variables = new VariablesView(document.getElementById("variables"));
this.Variables.enableSearch();
this.Variables.searchPlaceholder = L10N.getStr("emptyVariablesFilterText"); this.Variables.searchPlaceholder = L10N.getStr("emptyVariablesFilterText");
this.Variables.emptyText = L10N.getStr("emptyVariablesText"); this.Variables.emptyText = L10N.getStr("emptyVariablesText");
this.Variables.nonEnumVisible = Prefs.nonEnumVisible; this.Variables.nonEnumVisible = Prefs.variablesNonEnumVisible;
this.Variables.searchEnabled = Prefs.variablesSearchboxVisible;
this.Variables.eval = DebuggerController.StackFrames.evaluate; this.Variables.eval = DebuggerController.StackFrames.evaluate;
this.Variables.lazyEmpty = true; this.Variables.lazyEmpty = true;

View File

@ -41,12 +41,16 @@
oncommand="DebuggerView.Filtering._doTokenSearch()"/> oncommand="DebuggerView.Filtering._doTokenSearch()"/>
<command id="globalSearchCommand" <command id="globalSearchCommand"
oncommand="DebuggerView.Filtering._doGlobalSearch()"/> oncommand="DebuggerView.Filtering._doGlobalSearch()"/>
<command id="variableSearchCommand"
oncommand="DebuggerView.Filtering._doVariableSearch()"/>
<command id="togglePauseOnExceptions" <command id="togglePauseOnExceptions"
oncommand="DebuggerView.Options._togglePauseOnExceptions()"/> oncommand="DebuggerView.Options._togglePauseOnExceptions()"/>
<command id="toggleShowPanesOnStartup" <command id="toggleShowPanesOnStartup"
oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/> oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/>
<command id="toggleShowNonEnum" <command id="toggleShowNonEnum"
oncommand="DebuggerView.Options._toggleShowNonEnum()"/> oncommand="DebuggerView.Options._toggleShowVariablesNonEnum()"/>
<command id="toggleShowVariablesSearchbox"
oncommand="DebuggerView.Options._toggleShowVariablesSearchbox()"/>
</commandset> </commandset>
<popupset id="debuggerPopupset"> <popupset id="debuggerPopupset">
@ -75,11 +79,16 @@
label="&debuggerUI.showPanesOnInit;" label="&debuggerUI.showPanesOnInit;"
accesskey="&debuggerUI.showPanesOnInit.key;" accesskey="&debuggerUI.showPanesOnInit.key;"
command="toggleShowPanesOnStartup"/> command="toggleShowPanesOnStartup"/>
<menuitem id="show-nonenum" <menuitem id="show-vars-nonenum"
type="checkbox" type="checkbox"
label="&debuggerUI.showNonEnums;" label="&debuggerUI.showNonEnums;"
accesskey="&debuggerUI.showNonEnums.key;" accesskey="&debuggerUI.showNonEnums.key;"
command="toggleShowNonEnum"/> command="toggleShowNonEnum"/>
<menuitem id="show-vars-searchbox"
type="checkbox"
label="&debuggerUI.showVarsSearch;"
accesskey="&debuggerUI.showVarsSearch.key;"
command="toggleShowVariablesSearchbox"/>
</menupopup> </menupopup>
</popupset> </popupset>
@ -115,6 +124,10 @@
key="F" key="F"
modifiers="control shift" modifiers="control shift"
command="globalSearchCommand"/> command="globalSearchCommand"/>
<key id="variableSearchKey"
key="V"
modifiers="control shift"
command="variableSearchCommand"/>
</keyset> </keyset>
<vbox id="body" flex="1"> <vbox id="body" flex="1">
@ -158,6 +171,7 @@
tooltiptext="&debuggerUI.closeButton.tooltip;"/> tooltiptext="&debuggerUI.closeButton.tooltip;"/>
#endif #endif
</toolbar> </toolbar>
<panel id="searchbox-panel" <panel id="searchbox-panel"
type="arrow" type="arrow"
noautofocus="true" noautofocus="true"
@ -179,8 +193,14 @@
command="lineSearchCommand"/> command="lineSearchCommand"/>
<label id="line-operator-label" class="plain operator"/> <label id="line-operator-label" class="plain operator"/>
</hbox> </hbox>
<hbox align="center">
<button id="variable-operator-button" class="operator"
command="variableSearchCommand"/>
<label id="variable-operator-label" class="plain operator"/>
</hbox>
</vbox> </vbox>
</panel> </panel>
<vbox id="dbg-content" flex="1"> <vbox id="dbg-content" flex="1">
<vbox id="globalsearch" hidden="true"/> <vbox id="globalsearch" hidden="true"/>
<splitter id="globalsearch-splitter" <splitter id="globalsearch-splitter"
@ -197,5 +217,6 @@
<vbox id="variables"/> <vbox id="variables"/>
</hbox> </hbox>
</vbox> </vbox>
</vbox> </vbox>
</window> </window>

View File

@ -35,6 +35,9 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_propertyview-edit.js \ browser_dbg_propertyview-edit.js \
browser_dbg_propertyview-filter-01.js \ browser_dbg_propertyview-filter-01.js \
browser_dbg_propertyview-filter-02.js \ browser_dbg_propertyview-filter-02.js \
browser_dbg_propertyview-filter-03.js \
browser_dbg_propertyview-filter-04.js \
browser_dbg_propertyview-filter-05.js \
browser_dbg_propertyview-reexpand.js \ browser_dbg_propertyview-reexpand.js \
browser_dbg_reload-same-script.js \ browser_dbg_reload-same-script.js \
browser_dbg_pane-collapse.js \ browser_dbg_pane-collapse.js \

View File

@ -55,8 +55,8 @@ function testNonEnumProperties() {
".nonenum container should be visible."); ".nonenum container should be visible.");
// Uncheck 'show hidden properties'. // Uncheck 'show hidden properties'.
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "false"); gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowNonEnum(); gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
ok(details.hasAttribute("open"), ok(details.hasAttribute("open"),
".details container should stay visible."); ".details container should stay visible.");
@ -65,8 +65,8 @@ function testNonEnumProperties() {
".nonenum container should become hidden."); ".nonenum container should become hidden.");
// Check 'show hidden properties'. // Check 'show hidden properties'.
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "true"); gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowNonEnum(); gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
ok(details.hasAttribute("open"), ok(details.hasAttribute("open"),
".details container should stay visible."); ".details container should stay visible.");
@ -83,8 +83,8 @@ function testNonEnumProperties() {
".nonenum container should be hidden."); ".nonenum container should be hidden.");
// Uncheck 'show hidden properties'. // Uncheck 'show hidden properties'.
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "false"); gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowNonEnum(); gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
ok(!details.hasAttribute("open"), ok(!details.hasAttribute("open"),
".details container should stay hidden."); ".details container should stay hidden.");
@ -93,8 +93,8 @@ function testNonEnumProperties() {
".nonenum container should stay hidden."); ".nonenum container should stay hidden.");
// Check 'show hidden properties'. // Check 'show hidden properties'.
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "true"); gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowNonEnum(); gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
gDebugger.DebuggerController.activeThread.resume(function() { gDebugger.DebuggerController.activeThread.resume(function() {
closeDebuggerAndFinish(); closeDebuggerAndFinish();

View File

@ -31,8 +31,14 @@ function test()
function testSearchbox() function testSearchbox()
{ {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode, ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should initially be a searchbox available in the variables view."); "There should be a searchbox available after enabling.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"), ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found."); "There searchbox element should be found.");
@ -70,6 +76,22 @@ function testSearchbox()
ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"), ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"),
placeholder, "There correct placeholder should be applied to the searchbox again."); placeholder, "There correct placeholder should be applied to the searchbox again.");
gDebugger.DebuggerView.Variables.searchEnabled = false;
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There shouldn't be a searchbox available after disabling again.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
gDebugger.DebuggerView.Variables.searchEnabled = true;
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available after enabling again.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"),
placeholder, "There correct placeholder should be applied to the searchbox again.");
} }
function testVariablesFiltering() function testVariablesFiltering()
@ -111,8 +133,8 @@ function testVariablesFiltering()
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 1, is(globalScope.querySelectorAll(".variable:not([non-match])").length, 1,
"There should be 1 variable displayed in the global scope"); "There should be 1 variable displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 5, is(innerScope.querySelectorAll(".property:not([non-match])").length, 6,
"There should be 5 properties displayed in the inner scope"); "There should be 6 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0, is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope"); "There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0, is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
@ -131,9 +153,11 @@ function testVariablesFiltering()
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
"location", "The third inner property displayed should be 'location'"); "location", "The third inner property displayed should be 'location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
"Location", "The fourth inner property displayed should be 'Location'"); "__proto__", "The fourth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
"Location", "The fifth inner property displayed should be 'Location'"); "Location", "The fifth inner property displayed should be 'Location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[5].getAttribute("value"),
"Location", "The sixth inner property displayed should be 'Location'");
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"), is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"Location", "The only global variable displayed should be 'Location'"); "Location", "The only global variable displayed should be 'Location'");
@ -195,8 +219,8 @@ function testVariablesFiltering()
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 1, is(globalScope.querySelectorAll(".variable:not([non-match])").length, 1,
"There should be 1 variable displayed in the global scope"); "There should be 1 variable displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 5, is(innerScope.querySelectorAll(".property:not([non-match])").length, 6,
"There should be 5 properties displayed in the inner scope"); "There should be 6 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0, is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope"); "There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0, is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
@ -215,9 +239,11 @@ function testVariablesFiltering()
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
"location", "The third inner property displayed should be 'location'"); "location", "The third inner property displayed should be 'location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
"Location", "The fourth inner property displayed should be 'Location'"); "__proto__", "The fourth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
"Location", "The fifth inner property displayed should be 'Location'"); "Location", "The fifth inner property displayed should be 'Location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[5].getAttribute("value"),
"Location", "The sixth inner property displayed should be 'Location'");
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"), is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"Location", "The only global variable displayed should be 'Location'"); "Location", "The only global variable displayed should be 'Location'");
@ -419,9 +445,11 @@ function ignoreExtraMatchedProperties()
{ {
for (let [_, item] of gDebugger.DebuggerView.Variables._currHierarchy) { for (let [_, item] of gDebugger.DebuggerView.Variables._currHierarchy) {
let name = item.name.toLowerCase(); let name = item.name.toLowerCase();
if (name.contains("tracemallocdumpallocations") || let value = item._valueString || "";
name.contains("geolocation") ||
name.contains("webgl")) { if ((name.contains("tracemallocdumpallocations")) ||
(name.contains("geolocation")) ||
(name.contains("webgl"))) {
item.target.setAttribute("non-match", ""); item.target.setAttribute("non-match", "");
} }
} }

View File

@ -31,8 +31,14 @@ function test()
function testSearchbox() function testSearchbox()
{ {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
gDebugger.DebuggerView.Variables.enableSearch();
ok(gDebugger.DebuggerView.Variables._searchboxNode, ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should initially be a searchbox available in the variables view."); "There should be a searchbox available after enabling.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"), ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found."); "There searchbox element should be found.");
} }
@ -74,8 +80,8 @@ function testVariablesFiltering()
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 2, is(globalScope.querySelectorAll(".variable:not([non-match])").length, 2,
"There should be 2 variables displayed in the global scope"); "There should be 2 variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 5, is(innerScope.querySelectorAll(".property:not([non-match])").length, 8,
"There should be 5 properties displayed in the inner scope"); "There should be 8 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0, is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope"); "There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0, is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
@ -94,9 +100,15 @@ function testVariablesFiltering()
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
"document", "The third inner property displayed should be 'document'"); "document", "The third inner property displayed should be 'document'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
"HTMLDocument", "The fourth inner property displayed should be 'HTMLDocument'"); "location", "The fourth inner property displayed should be 'location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
"HTMLDocument", "The fifth inner property displayed should be 'HTMLDocument'"); "__proto__", "The fifth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[5].getAttribute("value"),
"__proto__", "The sixth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[6].getAttribute("value"),
"HTMLDocument", "The seventh inner property displayed should be 'HTMLDocument'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[7].getAttribute("value"),
"HTMLDocument", "The eight inner property displayed should be 'HTMLDocument'");
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"), is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"document", "The first global variable displayed should be 'document'"); "document", "The first global variable displayed should be 'document'");
@ -149,8 +161,8 @@ function testVariablesFiltering()
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 2, is(globalScope.querySelectorAll(".variable:not([non-match])").length, 2,
"There should be 2 variables displayed in the global scope"); "There should be 2 variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 5, is(innerScope.querySelectorAll(".property:not([non-match])").length, 8,
"There should be 5 properties displayed in the inner scope"); "There should be 8 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0, is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope"); "There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0, is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
@ -169,9 +181,15 @@ function testVariablesFiltering()
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
"document", "The third inner property displayed should be 'document'"); "document", "The third inner property displayed should be 'document'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
"HTMLDocument", "The fourth inner property displayed should be 'HTMLDocument'"); "location", "The fourth inner property displayed should be 'location'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"), is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
"HTMLDocument", "The fifth inner property displayed should be 'HTMLDocument'"); "__proto__", "The fifth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[5].getAttribute("value"),
"__proto__", "The sixth inner property displayed should be '__proto__'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[6].getAttribute("value"),
"HTMLDocument", "The seventh inner property displayed should be 'HTMLDocument'");
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[7].getAttribute("value"),
"HTMLDocument", "The eight inner property displayed should be 'HTMLDocument'");
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"), is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"document", "The first global variable displayed should be 'document'"); "document", "The first global variable displayed should be 'document'");

View File

@ -0,0 +1,93 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that the property view filter prefs work properly.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_with-frame.html";
var gPane = null;
var gTab = null;
var gDebugger = null;
var gDebuggee = null;
var gPrevPref = null;
function test()
{
gPrevPref = Services.prefs.getBoolPref(
"devtools.debugger.ui.variables-searchbox-visible");
Services.prefs.setBoolPref(
"devtools.debugger.ui.variables-searchbox-visible", false);
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebuggee = aDebuggee;
testSearchbox();
testPref();
});
}
function testSearchbox()
{
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not initially be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
}
function testPref()
{
is(gDebugger.Prefs.variablesSearchboxVisible, false,
"The debugger searchbox should be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should not be checked.");
gDebugger.DebuggerView.Options._showVariablesSearchboxItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowVariablesSearchbox();
executeSoon(function() {
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, true,
"The debugger searchbox should now be preffed as visible.");
is(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should now be checked.");
gDebugger.DebuggerView.Options._showVariablesSearchboxItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowVariablesSearchbox();
executeSoon(function() {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, false,
"The debugger searchbox should now be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should now be unchecked.");
executeSoon(function() {
Services.prefs.setBoolPref(
"devtools.debugger.ui.variables-searchbox-visible", gPrevPref);
closeDebuggerAndFinish();
});
});
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebugger = null;
gDebuggee = null;
gPrevPref = null;
});

View File

@ -0,0 +1,93 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that the property view filter prefs work properly.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_with-frame.html";
var gPane = null;
var gTab = null;
var gDebugger = null;
var gDebuggee = null;
var gPrevPref = null;
function test()
{
gPrevPref = Services.prefs.getBoolPref(
"devtools.debugger.ui.variables-searchbox-visible");
Services.prefs.setBoolPref(
"devtools.debugger.ui.variables-searchbox-visible", true);
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebuggee = aDebuggee;
testSearchbox();
testPref();
});
}
function testSearchbox()
{
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should initially be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
}
function testPref()
{
is(gDebugger.Prefs.variablesSearchboxVisible, true,
"The debugger searchbox should be preffed as visible.");
is(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should be checked.");
gDebugger.DebuggerView.Options._showVariablesSearchboxItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowVariablesSearchbox();
executeSoon(function() {
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
"There should not be a searchbox available in the variables view.");
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should not be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, false,
"The debugger searchbox should now be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should now be unchecked.");
gDebugger.DebuggerView.Options._showVariablesSearchboxItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowVariablesSearchbox();
executeSoon(function() {
ok(gDebugger.DebuggerView.Variables._searchboxNode,
"There should be a searchbox available in the variables view.");
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
"There searchbox element should be found.");
is(gDebugger.Prefs.variablesSearchboxVisible, true,
"The debugger searchbox should now be preffed as visible.");
is(gDebugger.DebuggerView.Options._showVariablesSearchboxItem.getAttribute("checked"), "true",
"The options menu item should now be checked.");
executeSoon(function() {
Services.prefs.setBoolPref(
"devtools.debugger.ui.variables-searchbox-visible", gPrevPref);
closeDebuggerAndFinish();
});
});
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebugger = null;
gDebuggee = null;
gPrevPref = null;
});

View File

@ -0,0 +1,303 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that the property view correctly filters nodes by value.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_with-frame.html";
var gPane = null;
var gTab = null;
var gDebugger = null;
var gDebuggee = null;
var gSearchBox = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.contentWindow;
gDebuggee = aDebuggee;
prepareVariables(testVariablesFiltering);
});
}
function testVariablesFiltering()
{
function test1()
{
write("*one");
ignoreExtraMatchedProperties();
is(innerScope.querySelectorAll(".variable:not([non-match])").length, 1,
"There should be 1 variable displayed in the inner scope");
is(mathScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the math scope");
is(testScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the test scope");
is(loadScope.querySelectorAll(".variable:not([non-match])").length, 1,
"There should be 1 variable displayed in the load scope");
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 3,
"There should be 3 variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the test scope");
is(loadScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the load scope");
is(globalScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the global scope");
is(innerScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"one", "The only inner variable displayed should be 'one'");
is(loadScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"button", "The only load variable displayed should be 'button'");
let oneItem = innerScopeItem.get("one");
is(oneItem.expanded, false,
"The one item in the inner scope should not be expanded");
EventUtils.sendKey("RETURN");
is(oneItem.expanded, true,
"The one item in the inner scope should now be expanded");
}
function test2()
{
write("*two");
ignoreExtraMatchedProperties();
is(innerScope.querySelectorAll(".variable:not([non-match])").length, 1,
"There should be 1 variable displayed in the inner scope");
is(mathScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the math scope");
is(testScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the test scope");
is(loadScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the load scope");
is(globalScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be 0 variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the test scope");
is(loadScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the load scope");
is(globalScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the global scope");
is(innerScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[0].getAttribute("value"),
"two", "The only inner variable displayed should be 'two'");
let twoItem = innerScopeItem.get("two");
is(twoItem.expanded, false,
"The two item in the inner scope should not be expanded");
EventUtils.sendKey("RETURN");
is(twoItem.expanded, true,
"The two item in the inner scope should now be expanded");
}
function test3()
{
backspace(3);
ignoreExtraMatchedProperties();
is(gSearchBox.value, "*",
"Searchbox value is incorrect after 3 backspaces");
is(innerScope.querySelectorAll(".variable:not([non-match])").length, 3,
"There should be 3 variables displayed in the inner scope");
isnot(mathScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the math scope");
isnot(testScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the test scope");
isnot(loadScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the load scope");
isnot(globalScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the test scope");
is(loadScope.querySelectorAll(".property:not([non-match])").length, 1,
"There should be 1 property displayed in the load scope");
isnot(globalScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be some properties displayed in the global scope");
}
function test4()
{
backspace(1);
ignoreExtraMatchedProperties();
is(gSearchBox.value, "",
"Searchbox value is incorrect after 1 backspace");
is(innerScope.querySelectorAll(".variable:not([non-match])").length, 3,
"There should be 3 variables displayed in the inner scope");
isnot(mathScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the math scope");
isnot(testScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the test scope");
isnot(loadScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the load scope");
isnot(globalScope.querySelectorAll(".variable:not([non-match])").length, 0,
"There should be some variables displayed in the global scope");
is(innerScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the inner scope");
is(mathScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the math scope");
is(testScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be 0 properties displayed in the test scope");
is(loadScope.querySelectorAll(".property:not([non-match])").length, 1,
"There should be 1 property displayed in the load scope");
isnot(globalScope.querySelectorAll(".property:not([non-match])").length, 0,
"There should be some properties displayed in the global scope");
}
var scopes = gDebugger.DebuggerView.Variables._list,
innerScope = scopes.querySelectorAll(".scope")[0],
mathScope = scopes.querySelectorAll(".scope")[1],
testScope = scopes.querySelectorAll(".scope")[2],
loadScope = scopes.querySelectorAll(".scope")[3],
globalScope = scopes.querySelectorAll(".scope")[4];
let innerScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
innerScope.querySelector(".name").getAttribute("value"));
let mathScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
mathScope.querySelector(".name").getAttribute("value"));
let testScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
testScope.querySelector(".name").getAttribute("value"));
let loadScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
loadScope.querySelector(".name").getAttribute("value"));
let globalScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
globalScope.querySelector(".name").getAttribute("value"));
gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
executeSoon(function() {
test1();
executeSoon(function() {
test2();
executeSoon(function() {
test3();
executeSoon(function() {
test4();
executeSoon(function() {
closeDebuggerAndFinish();
});
});
});
});
});
}
function prepareVariables(aCallback)
{
let count = 0;
gDebugger.addEventListener("Debugger:FetchedVariables", function test() {
// We expect 4 Debugger:FetchedVariables events, one from the global object
// scope, two from the |with| scopes and the regular one.
if (++count < 4) {
info("Number of received Debugger:FetchedVariables events: " + count);
return;
}
gDebugger.removeEventListener("Debugger:FetchedVariables", test, false);
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.StackFrames._container._list,
scopes = gDebugger.DebuggerView.Variables._list,
innerScope = scopes.querySelectorAll(".scope")[0],
mathScope = scopes.querySelectorAll(".scope")[1],
testScope = scopes.querySelectorAll(".scope")[2],
loadScope = scopes.querySelectorAll(".scope")[3],
globalScope = scopes.querySelectorAll(".scope")[4];
let innerScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
innerScope.querySelector(".name").getAttribute("value"));
let mathScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
mathScope.querySelector(".name").getAttribute("value"));
let testScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
testScope.querySelector(".name").getAttribute("value"));
let loadScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
loadScope.querySelector(".name").getAttribute("value"));
let globalScopeItem = gDebugger.DebuggerView.Variables._currHierarchy.get(
globalScope.querySelector(".name").getAttribute("value"));
EventUtils.sendMouseEvent({ type: "mousedown" }, mathScope.querySelector(".arrow"), gDebuggee);
EventUtils.sendMouseEvent({ type: "mousedown" }, testScope.querySelector(".arrow"), gDebuggee);
EventUtils.sendMouseEvent({ type: "mousedown" }, loadScope.querySelector(".arrow"), gDebuggee);
EventUtils.sendMouseEvent({ type: "mousedown" }, globalScope.querySelector(".arrow"), gDebuggee);
executeSoon(function() {
aCallback();
});
}}, 0);
}, false);
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee.window);
}
function ignoreExtraMatchedProperties()
{
for (let [_, item] of gDebugger.DebuggerView.Variables._currHierarchy) {
let name = item.name.toLowerCase();
let value = item._valueString || "";
if ((value.contains("DOM")) ||
(value.contains("XPC") && !name.contains("__proto__"))) {
item.target.setAttribute("non-match", "");
}
}
}
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")
}
}
function append(text) {
gSearchBox.focus();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i]);
}
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebugger = null;
gDebuggee = null;
gSearchBox = null;
});

View File

@ -49,6 +49,11 @@
<!ENTITY debuggerUI.showPanesOnInit "Show panes on startup"> <!ENTITY debuggerUI.showPanesOnInit "Show panes on startup">
<!ENTITY debuggerUI.showPanesOnInit.key "S"> <!ENTITY debuggerUI.showPanesOnInit.key "S">
<!-- LOCALIZATION NOTE (debuggerUI.showVarsSearch): This is the label for the
- checkbox that toggles visibility of a designated variables searchbox. -->
<!ENTITY debuggerUI.showVarsSearch "Show variables searchbox">
<!ENTITY debuggerUI.showVarsSearch.key "V">
<!-- LOCALIZATION NOTE (debuggerUI.showNonEnums): This is the label for the <!-- LOCALIZATION NOTE (debuggerUI.showNonEnums): This is the label for the
- checkbox that toggles visibility of hidden (non-enumerable) variables and - checkbox that toggles visibility of hidden (non-enumerable) variables and
- properties in stack views. --> - properties in stack views. -->

View File

@ -124,6 +124,10 @@ searchPanelToken=Find in this file (%S)
# filter panel popup for the line search operation. # filter panel popup for the line search operation.
searchPanelLine=Jump to line (%S) searchPanelLine=Jump to line (%S)
# LOCALIZATION NOTE (searchPanelVariable): This is the text that appears in the
# filter panel popup for the variables search operation.
searchPanelVariable=Filter variables (%S)
# LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that # LOCALIZATION NOTE (breakpointMenuItem): The text for all the elements that
# are displayed in the breakpoints menu item popup. # are displayed in the breakpoints menu item popup.
breakpointMenuItem.enableSelf=Enable breakpoint breakpointMenuItem.enableSelf=Enable breakpoint