зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central into mozilla-inbound
This commit is contained in:
Коммит
2305a6fff8
|
@ -137,8 +137,7 @@ DeviceTabActor.prototype._pushContext = function DTA_pushContext() {
|
|||
this._contextPool = new ActorPool(this.conn);
|
||||
this.conn.addActorPool(this._contextPool);
|
||||
|
||||
this.threadActor = new ThreadActor(this);
|
||||
this._addDebuggees(this.browser.wrappedJSObject);
|
||||
this.threadActor = new ThreadActor(this, this.browser.wrappedJSObject);
|
||||
this._contextPool.addActor(this.threadActor);
|
||||
};
|
||||
|
||||
|
|
|
@ -1052,7 +1052,8 @@ pref("devtools.debugger.ui.remote-win.height", 400);
|
|||
pref("devtools.debugger.ui.stackframes-width", 200);
|
||||
pref("devtools.debugger.ui.variables-width", 300);
|
||||
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
|
||||
pref("devtools.styleinspector.enabled", true);
|
||||
|
|
|
@ -660,9 +660,9 @@ StackFrames.prototype = {
|
|||
|
||||
// Add the variable's __proto__.
|
||||
if (prototype.type != "null") {
|
||||
aVar.addProperties({ "__proto__ ": { value: prototype } });
|
||||
aVar.addProperty("__proto__", { value: prototype });
|
||||
// Expansion handlers must be set after the properties are added.
|
||||
this._addExpander(aVar.get("__proto__ "), prototype);
|
||||
this._addExpander(aVar.get("__proto__"), prototype);
|
||||
}
|
||||
|
||||
aVar.fetched = true;
|
||||
|
@ -734,6 +734,7 @@ SourceScripts.prototype = {
|
|||
* Connect to the current thread client.
|
||||
*/
|
||||
connect: function SS_connect() {
|
||||
dumpn("SourceScripts is connecting...");
|
||||
this.debuggerClient.addListener("newScript", this._onNewScript);
|
||||
this.debuggerClient.addListener("newGlobal", this._onNewGlobal);
|
||||
this._handleTabNavigation();
|
||||
|
@ -746,6 +747,7 @@ SourceScripts.prototype = {
|
|||
if (!this.activeThread) {
|
||||
return;
|
||||
}
|
||||
dumpn("SourceScripts is disconnecting...");
|
||||
this.debuggerClient.removeListener("newScript", this._onNewScript);
|
||||
this.debuggerClient.removeListener("newGlobal", this._onNewGlobal);
|
||||
},
|
||||
|
@ -1248,7 +1250,8 @@ XPCOMUtils.defineLazyGetter(L10N, "ellipsis", function() {
|
|||
const STACKFRAMES_WIDTH = "devtools.debugger.ui.stackframes-width";
|
||||
const VARIABLES_WIDTH = "devtools.debugger.ui.variables-width";
|
||||
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_PORT = "devtools.debugger.remote-port";
|
||||
const REMOTE_AUTO_CONNECT = "devtools.debugger.remote-autoconnect";
|
||||
|
@ -1324,11 +1327,11 @@ let Prefs = {
|
|||
* properties and variables in the scope view.
|
||||
* @return boolean
|
||||
*/
|
||||
get nonEnumVisible() {
|
||||
if (this._nonEnumVisible === undefined) {
|
||||
this._nonEnumVisible = Services.prefs.getBoolPref(NON_ENUM_VISIBLE);
|
||||
get variablesNonEnumVisible() {
|
||||
if (this._varNonEnum === undefined) {
|
||||
this._varNonEnum = Services.prefs.getBoolPref(VARIABLES_NON_ENUM_VISIBLE);
|
||||
}
|
||||
return this._nonEnumVisible;
|
||||
return this._varNonEnum;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1336,9 +1339,29 @@ let Prefs = {
|
|||
* properties and variables in the scope view.
|
||||
* @param boolean value
|
||||
*/
|
||||
set nonEnumVisible(value) {
|
||||
Services.prefs.setBoolPref(NON_ENUM_VISIBLE, value);
|
||||
this._nonEnumVisible = value;
|
||||
set variablesNonEnumVisible(value) {
|
||||
Services.prefs.setBoolPref(VARIABLES_NON_ENUM_VISIBLE, 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;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1212,7 +1212,7 @@ SourceResults.prototype = {
|
|||
*/
|
||||
toggle: function SR_toggle(e) {
|
||||
if (e instanceof Event) {
|
||||
this._toggled = true;
|
||||
this._userToggled = true;
|
||||
}
|
||||
this.expanded ^= 1;
|
||||
},
|
||||
|
@ -1230,9 +1230,10 @@ SourceResults.prototype = {
|
|||
set expanded(aFlag) this[aFlag ? "expand" : "collapse"](),
|
||||
|
||||
/**
|
||||
* Returns true if this element was toggled via user interaction.
|
||||
* Returns if this element was ever toggled via user interaction.
|
||||
* @return boolean
|
||||
*/
|
||||
get toggled() this._toggled,
|
||||
get toggled() this._userToggled,
|
||||
|
||||
/**
|
||||
* Gets the element associated with this item.
|
||||
|
@ -1313,7 +1314,7 @@ SourceResults.prototype = {
|
|||
|
||||
_store: null,
|
||||
_target: null,
|
||||
_toggled: false
|
||||
_userToggled: false
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -199,7 +199,8 @@ function OptionsView() {
|
|||
dumpn("OptionsView was instantiated");
|
||||
this._togglePauseOnExceptions = this._togglePauseOnExceptions.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 = {
|
||||
|
@ -211,11 +212,13 @@ OptionsView.prototype = {
|
|||
this._button = document.getElementById("debugger-options");
|
||||
this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
|
||||
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._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.
|
||||
*/
|
||||
_toggleShowNonEnum: function DVO__toggleShowNonEnum() {
|
||||
DebuggerView.Variables.nonEnumVisible = Prefs.nonEnumVisible =
|
||||
this._showNonEnumItem.getAttribute("checked") == "true";
|
||||
_toggleShowVariablesNonEnum: function DVO__toggleShowVariablesNonEnum() {
|
||||
DebuggerView.Variables.nonEnumVisible = Prefs.variablesNonEnumVisible =
|
||||
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,
|
||||
_pauseOnExceptionsItem: null,
|
||||
_showPanesOnStartupItem: null,
|
||||
_showNonEnumItem: null
|
||||
_showVariablesNonEnumItem: null,
|
||||
_showVariablesSearchboxItem: null
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -562,11 +574,14 @@ FilterView.prototype = {
|
|||
this._tokenOperatorLabel = document.getElementById("token-operator-label");
|
||||
this._lineOperatorButton = document.getElementById("line-operator-button");
|
||||
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._fileSearchKey = LayoutHelpers.prettyKey(document.getElementById("fileSearchKey"));
|
||||
this._lineSearchKey = LayoutHelpers.prettyKey(document.getElementById("lineSearchKey"));
|
||||
this._tokenSearchKey = LayoutHelpers.prettyKey(document.getElementById("tokenSearchKey"));
|
||||
this._variableSearchKey = LayoutHelpers.prettyKey(document.getElementById("variableSearchKey"));
|
||||
|
||||
this._searchbox.addEventListener("click", this._onClick, false);
|
||||
this._searchbox.addEventListener("select", this._onSearch, false);
|
||||
|
@ -577,6 +592,7 @@ FilterView.prototype = {
|
|||
this._globalOperatorButton.setAttribute("label", SEARCH_GLOBAL_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]));
|
||||
|
@ -584,6 +600,8 @@ FilterView.prototype = {
|
|||
L10N.getFormatStr("searchPanelToken", [this._tokenSearchKey]));
|
||||
this._lineOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelLine", [this._lineSearchKey]));
|
||||
this._variableOperatorLabel.setAttribute("value",
|
||||
L10N.getFormatStr("searchPanelVariable", [this._variableSearchKey]));
|
||||
|
||||
// TODO: bug 806775
|
||||
// if (window._isChromeDebugger) {
|
||||
|
@ -628,16 +646,17 @@ FilterView.prototype = {
|
|||
* @return array
|
||||
*/
|
||||
get searchboxInfo() {
|
||||
let file, line, token, global;
|
||||
let file, line, token, isGlobal, isVariable;
|
||||
|
||||
let rawValue = this._searchbox.value;
|
||||
let rawLength = rawValue.length;
|
||||
let globalFlagIndex = rawValue.indexOf(SEARCH_GLOBAL_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 search, allow file or line flags.
|
||||
if (globalFlagIndex != 0) {
|
||||
// This is not a global or variable search, allow file or line flags.
|
||||
if (globalFlagIndex != 0 && variableFlagIndex != 0) {
|
||||
let fileEnd = lineFlagIndex != -1
|
||||
? lineFlagIndex
|
||||
: tokenFlagIndex != -1 ? tokenFlagIndex : rawLength;
|
||||
|
@ -649,17 +668,27 @@ FilterView.prototype = {
|
|||
file = rawValue.slice(0, fileEnd);
|
||||
line = ~~(rawValue.slice(fileEnd + 1, lineEnd)) || -1;
|
||||
token = rawValue.slice(lineEnd + 1);
|
||||
global = false;
|
||||
isGlobal = false;
|
||||
isVariable = false;
|
||||
}
|
||||
// Global searches dissalow the use of file or line flags.
|
||||
else {
|
||||
else if (globalFlagIndex == 0) {
|
||||
file = "";
|
||||
line = -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() {
|
||||
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,
|
||||
// or hide the corresponding pane otherwise.
|
||||
if (global) {
|
||||
if (isGlobal) {
|
||||
DebuggerView.GlobalSearch.scheduleSearch();
|
||||
} else {
|
||||
DebuggerView.GlobalSearch.clearView();
|
||||
this._performFileSearch(file);
|
||||
this._performLineSearch(line);
|
||||
this._performTokenSearch(token);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
_onKeyPress: function DVF__onScriptsKeyPress(e) {
|
||||
let [file, line, token, global] = this.searchboxInfo;
|
||||
let [file, line, token, isGlobal, isVariable] = this.searchboxInfo;
|
||||
let action;
|
||||
|
||||
switch (e.keyCode) {
|
||||
|
@ -835,18 +872,26 @@ FilterView.prototype = {
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (global) {
|
||||
// Perform a global search based on the specified operator.
|
||||
if (isGlobal) {
|
||||
if (DebuggerView.GlobalSearch.hidden) {
|
||||
DebuggerView.GlobalSearch.scheduleSearch();
|
||||
} else {
|
||||
DebuggerView.GlobalSearch[["focusNextMatch", "focusPrevMatch"][action]]();
|
||||
}
|
||||
} else {
|
||||
let editor = DebuggerView.editor;
|
||||
let offset = editor[["findNext", "findPrevious"][action]](true);
|
||||
if (offset > -1) {
|
||||
editor.setSelection(offset, offset + token.length)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform a variable search based on the specified operator.
|
||||
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() {
|
||||
DebuggerView.GlobalSearch.clearView();
|
||||
DebuggerView.Variables.performSearch(null);
|
||||
this._searchboxPanel.hidePopup();
|
||||
},
|
||||
|
||||
|
@ -902,6 +948,14 @@ FilterView.prototype = {
|
|||
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,
|
||||
_searchboxPanel: null,
|
||||
_globalOperatorButton: null,
|
||||
|
|
|
@ -15,6 +15,7 @@ const GLOBAL_SEARCH_ACTION_DELAY = 150; // ms
|
|||
const SEARCH_GLOBAL_FLAG = "!";
|
||||
const SEARCH_LINE_FLAG = ":";
|
||||
const SEARCH_TOKEN_FLAG = "#";
|
||||
const SEARCH_VARIABLE_FLAG = "*";
|
||||
|
||||
/**
|
||||
* Object defining the debugger view components.
|
||||
|
@ -38,8 +39,10 @@ let DebuggerView = {
|
|||
this.GlobalSearch.initialize();
|
||||
|
||||
this.Variables = new VariablesView(document.getElementById("variables"));
|
||||
this.Variables.searchPlaceholder = L10N.getStr("emptyVariablesFilterText");
|
||||
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.lazyEmpty = true;
|
||||
|
||||
|
|
|
@ -63,6 +63,21 @@
|
|||
display: -moz-box;
|
||||
}
|
||||
|
||||
.scope[non-header] > .title,
|
||||
.variable[non-header] > .title,
|
||||
.property[non-header] > .title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variables and properties searching
|
||||
*/
|
||||
|
||||
.variable[non-match] > .title,
|
||||
.property[non-match] > .title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toolbar
|
||||
*/
|
||||
|
|
|
@ -41,12 +41,16 @@
|
|||
oncommand="DebuggerView.Filtering._doTokenSearch()"/>
|
||||
<command id="globalSearchCommand"
|
||||
oncommand="DebuggerView.Filtering._doGlobalSearch()"/>
|
||||
<command id="variableSearchCommand"
|
||||
oncommand="DebuggerView.Filtering._doVariableSearch()"/>
|
||||
<command id="togglePauseOnExceptions"
|
||||
oncommand="DebuggerView.Options._togglePauseOnExceptions()"/>
|
||||
<command id="toggleShowPanesOnStartup"
|
||||
oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/>
|
||||
<command id="toggleShowNonEnum"
|
||||
oncommand="DebuggerView.Options._toggleShowNonEnum()"/>
|
||||
oncommand="DebuggerView.Options._toggleShowVariablesNonEnum()"/>
|
||||
<command id="toggleShowVariablesSearchbox"
|
||||
oncommand="DebuggerView.Options._toggleShowVariablesSearchbox()"/>
|
||||
</commandset>
|
||||
|
||||
<popupset id="debuggerPopupset">
|
||||
|
@ -75,11 +79,16 @@
|
|||
label="&debuggerUI.showPanesOnInit;"
|
||||
accesskey="&debuggerUI.showPanesOnInit.key;"
|
||||
command="toggleShowPanesOnStartup"/>
|
||||
<menuitem id="show-nonenum"
|
||||
<menuitem id="show-vars-nonenum"
|
||||
type="checkbox"
|
||||
label="&debuggerUI.showNonEnums;"
|
||||
accesskey="&debuggerUI.showNonEnums.key;"
|
||||
command="toggleShowNonEnum"/>
|
||||
<menuitem id="show-vars-searchbox"
|
||||
type="checkbox"
|
||||
label="&debuggerUI.showVarsSearch;"
|
||||
accesskey="&debuggerUI.showVarsSearch.key;"
|
||||
command="toggleShowVariablesSearchbox"/>
|
||||
</menupopup>
|
||||
</popupset>
|
||||
|
||||
|
@ -115,6 +124,10 @@
|
|||
key="F"
|
||||
modifiers="control shift"
|
||||
command="globalSearchCommand"/>
|
||||
<key id="variableSearchKey"
|
||||
key="V"
|
||||
modifiers="control shift"
|
||||
command="variableSearchCommand"/>
|
||||
</keyset>
|
||||
|
||||
<vbox id="body" flex="1">
|
||||
|
@ -158,6 +171,7 @@
|
|||
tooltiptext="&debuggerUI.closeButton.tooltip;"/>
|
||||
#endif
|
||||
</toolbar>
|
||||
|
||||
<panel id="searchbox-panel"
|
||||
type="arrow"
|
||||
noautofocus="true"
|
||||
|
@ -179,8 +193,14 @@
|
|||
command="lineSearchCommand"/>
|
||||
<label id="line-operator-label" class="plain operator"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<button id="variable-operator-button" class="operator"
|
||||
command="variableSearchCommand"/>
|
||||
<label id="variable-operator-label" class="plain operator"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</panel>
|
||||
|
||||
<vbox id="dbg-content" flex="1">
|
||||
<vbox id="globalsearch" hidden="true"/>
|
||||
<splitter id="globalsearch-splitter"
|
||||
|
@ -197,5 +217,6 @@
|
|||
<vbox id="variables"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
</vbox>
|
||||
</window>
|
||||
|
|
|
@ -33,6 +33,12 @@ MOCHITEST_BROWSER_TESTS = \
|
|||
browser_dbg_propertyview-09.js \
|
||||
browser_dbg_propertyview-10.js \
|
||||
browser_dbg_propertyview-edit.js \
|
||||
browser_dbg_propertyview-data.js \
|
||||
browser_dbg_propertyview-filter-01.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_reload-same-script.js \
|
||||
browser_dbg_pane-collapse.js \
|
||||
|
|
|
@ -55,8 +55,8 @@ function testNonEnumProperties() {
|
|||
".nonenum container should be visible.");
|
||||
|
||||
// Uncheck 'show hidden properties'.
|
||||
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "false");
|
||||
gDebugger.DebuggerView.Options._toggleShowNonEnum();
|
||||
gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "false");
|
||||
gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
|
||||
|
||||
ok(details.hasAttribute("open"),
|
||||
".details container should stay visible.");
|
||||
|
@ -65,8 +65,8 @@ function testNonEnumProperties() {
|
|||
".nonenum container should become hidden.");
|
||||
|
||||
// Check 'show hidden properties'.
|
||||
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "true");
|
||||
gDebugger.DebuggerView.Options._toggleShowNonEnum();
|
||||
gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "true");
|
||||
gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
|
||||
|
||||
ok(details.hasAttribute("open"),
|
||||
".details container should stay visible.");
|
||||
|
@ -83,8 +83,8 @@ function testNonEnumProperties() {
|
|||
".nonenum container should be hidden.");
|
||||
|
||||
// Uncheck 'show hidden properties'.
|
||||
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "false");
|
||||
gDebugger.DebuggerView.Options._toggleShowNonEnum();
|
||||
gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "false");
|
||||
gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
|
||||
|
||||
ok(!details.hasAttribute("open"),
|
||||
".details container should stay hidden.");
|
||||
|
@ -93,8 +93,8 @@ function testNonEnumProperties() {
|
|||
".nonenum container should stay hidden.");
|
||||
|
||||
// Check 'show hidden properties'.
|
||||
gDebugger.DebuggerView.Options._showNonEnumItem.setAttribute("checked", "true");
|
||||
gDebugger.DebuggerView.Options._toggleShowNonEnum();
|
||||
gDebugger.DebuggerView.Options._showVariablesNonEnumItem.setAttribute("checked", "true");
|
||||
gDebugger.DebuggerView.Options._toggleShowVariablesNonEnum();
|
||||
|
||||
gDebugger.DebuggerController.activeThread.resume(function() {
|
||||
closeDebuggerAndFinish();
|
||||
|
|
|
@ -0,0 +1,485 @@
|
|||
/* 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 populates itself.
|
||||
*/
|
||||
|
||||
var gPane = null;
|
||||
var gTab = null;
|
||||
var gDebugger = null;
|
||||
var gVariablesView = null;
|
||||
var gScope = null;
|
||||
var gVariable = null;
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB1_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.contentWindow;
|
||||
gVariablesView = gDebugger.DebuggerView.Variables;
|
||||
|
||||
testVariablesView();
|
||||
});
|
||||
}
|
||||
|
||||
function testVariablesView()
|
||||
{
|
||||
let arr = [
|
||||
42,
|
||||
true,
|
||||
"nasu",
|
||||
undefined,
|
||||
null,
|
||||
[0, 1, 2],
|
||||
{ prop1: 9, prop2: 8 }
|
||||
];
|
||||
|
||||
let obj = {
|
||||
"p0": 42,
|
||||
"p1": true,
|
||||
"p2": "nasu",
|
||||
"p3": undefined,
|
||||
"p4": null,
|
||||
"p5": [3, 4, 5],
|
||||
"p6": { prop1: 7, prop2: 6 },
|
||||
get p7() { return arr; },
|
||||
set p8(value) { arr[0] = value }
|
||||
};
|
||||
|
||||
let test = {
|
||||
someProp0: 42,
|
||||
someProp1: true,
|
||||
someProp2: "nasu",
|
||||
someProp3: undefined,
|
||||
someProp4: null,
|
||||
someProp5: arr,
|
||||
someProp6: obj,
|
||||
get someProp7() { return arr; },
|
||||
set someProp7(value) { arr[0] = value }
|
||||
};
|
||||
|
||||
gVariablesView.rawObject = test;
|
||||
|
||||
testHierarchy();
|
||||
testHeader();
|
||||
testFirstLevelContents();
|
||||
testSecondLevelContents();
|
||||
testThirdLevelContents();
|
||||
testIntegrity(arr, obj);
|
||||
|
||||
closeDebuggerAndFinish();
|
||||
}
|
||||
|
||||
function testHierarchy() {
|
||||
is(gVariablesView._currHierarchy.size, 13,
|
||||
"There should be 1 scope, 1 var, 1 proto, 8 props, 1 getter and 1 setter.");
|
||||
|
||||
gScope = gVariablesView._currHierarchy.get("");
|
||||
gVariable = gVariablesView._currHierarchy.get(".");
|
||||
|
||||
is(gVariablesView._store.size, 1,
|
||||
"There should be only one scope in the view");
|
||||
is(gScope._store.size, 1,
|
||||
"There should be only one variable in the scope");
|
||||
is(gVariable._store.size, 9,
|
||||
"There should be 1 __proto__ and 8 properties in the variable");
|
||||
}
|
||||
|
||||
function testHeader() {
|
||||
is(gScope.header, false,
|
||||
"The scope title header should be hidden");
|
||||
is(gVariable.header, false,
|
||||
"The variable title header should be hidden");
|
||||
|
||||
gScope.showHeader();
|
||||
gVariable.showHeader();
|
||||
|
||||
is(gScope.header, true,
|
||||
"The scope title header should now be visible");
|
||||
is(gVariable.header, true,
|
||||
"The variable title header should now be visible");
|
||||
|
||||
gScope.hideHeader();
|
||||
gVariable.hideHeader();
|
||||
|
||||
is(gScope.header, false,
|
||||
"The scope title header should now be hidden");
|
||||
is(gVariable.header, false,
|
||||
"The variable title header should now be hidden");
|
||||
}
|
||||
|
||||
function testFirstLevelContents() {
|
||||
let someProp0 = gVariable.get("someProp0");
|
||||
let someProp1 = gVariable.get("someProp1");
|
||||
let someProp2 = gVariable.get("someProp2");
|
||||
let someProp3 = gVariable.get("someProp3");
|
||||
let someProp4 = gVariable.get("someProp4");
|
||||
let someProp5 = gVariable.get("someProp5");
|
||||
let someProp6 = gVariable.get("someProp6");
|
||||
let someProp7 = gVariable.get("someProp7");
|
||||
let __proto__ = gVariable.get("__proto__");
|
||||
|
||||
is(someProp0.visible, true, "The first property visible state is correct.");
|
||||
is(someProp1.visible, true, "The second property visible state is correct.");
|
||||
is(someProp2.visible, true, "The third property visible state is correct.");
|
||||
is(someProp3.visible, true, "The fourth property visible state is correct.");
|
||||
is(someProp4.visible, true, "The fifth property visible state is correct.");
|
||||
is(someProp5.visible, true, "The sixth property visible state is correct.");
|
||||
is(someProp6.visible, true, "The seventh property visible state is correct.");
|
||||
is(someProp7.visible, true, "The eight property visible state is correct.");
|
||||
is(__proto__.visible, true, "The __proto__ property visible state is correct.");
|
||||
|
||||
is(someProp0.expanded, false, "The first property expanded state is correct.");
|
||||
is(someProp1.expanded, false, "The second property expanded state is correct.");
|
||||
is(someProp2.expanded, false, "The third property expanded state is correct.");
|
||||
is(someProp3.expanded, false, "The fourth property expanded state is correct.");
|
||||
is(someProp4.expanded, false, "The fifth property expanded state is correct.");
|
||||
is(someProp5.expanded, false, "The sixth property expanded state is correct.");
|
||||
is(someProp6.expanded, false, "The seventh property expanded state is correct.");
|
||||
is(someProp7.expanded, true, "The eight property expanded state is correct.");
|
||||
is(__proto__.expanded, false, "The __proto__ property expanded state is correct.");
|
||||
|
||||
is(someProp0.header, true, "The first property header state is correct.");
|
||||
is(someProp1.header, true, "The second property header state is correct.");
|
||||
is(someProp2.header, true, "The third property header state is correct.");
|
||||
is(someProp3.header, true, "The fourth property header state is correct.");
|
||||
is(someProp4.header, true, "The fifth property header state is correct.");
|
||||
is(someProp5.header, true, "The sixth property header state is correct.");
|
||||
is(someProp6.header, true, "The seventh property header state is correct.");
|
||||
is(someProp7.header, true, "The eight property header state is correct.");
|
||||
is(__proto__.header, true, "The __proto__ property header state is correct.");
|
||||
|
||||
is(someProp0.twisty, false, "The first property twisty state is correct.");
|
||||
is(someProp1.twisty, false, "The second property twisty state is correct.");
|
||||
is(someProp2.twisty, false, "The third property twisty state is correct.");
|
||||
is(someProp3.twisty, false, "The fourth property twisty state is correct.");
|
||||
is(someProp4.twisty, false, "The fifth property twisty state is correct.");
|
||||
is(someProp5.twisty, true, "The sixth property twisty state is correct.");
|
||||
is(someProp6.twisty, true, "The seventh property twisty state is correct.");
|
||||
is(someProp7.twisty, true, "The eight property twisty state is correct.");
|
||||
is(__proto__.twisty, true, "The __proto__ property twisty state is correct.");
|
||||
|
||||
is(someProp0.name, "someProp0", "The first property name is correct.");
|
||||
is(someProp1.name, "someProp1", "The second property name is correct.");
|
||||
is(someProp2.name, "someProp2", "The third property name is correct.");
|
||||
is(someProp3.name, "someProp3", "The fourth property name is correct.");
|
||||
is(someProp4.name, "someProp4", "The fifth property name is correct.");
|
||||
is(someProp5.name, "someProp5", "The sixth property name is correct.");
|
||||
is(someProp6.name, "someProp6", "The seventh property name is correct.");
|
||||
is(someProp7.name, "someProp7", "The eight property name is correct.");
|
||||
is(__proto__.name, "__proto__", "The __proto__ property name is correct.");
|
||||
|
||||
is(someProp0.value, 42, "The first property value is correct.");
|
||||
is(someProp1.value, true, "The second property value is correct.");
|
||||
is(someProp2.value, "nasu", "The third property value is correct.");
|
||||
is(someProp3.value.type, "undefined", "The fourth property value is correct.");
|
||||
is(someProp4.value.type, "null", "The fifth property value is correct.");
|
||||
is(someProp5.value.type, "object", "The sixth property value type is correct.");
|
||||
is(someProp5.value.class, "Array", "The sixth property value class is correct.");
|
||||
is(someProp6.value.type, "object", "The seventh property value type is correct.");
|
||||
is(someProp6.value.class, "Object", "The seventh property value class is correct.");
|
||||
is(someProp7.value, null, "The eight property value is correct.");
|
||||
isnot(someProp7.getter, null, "The eight property getter is correct.");
|
||||
isnot(someProp7.setter, null, "The eight property setter is correct.");
|
||||
is(someProp7.getter.type, "object", "The eight property getter type is correct.");
|
||||
is(someProp7.getter.class, "Function", "The eight property getter class is correct.");
|
||||
is(someProp7.setter.type, "object", "The eight property setter type is correct.");
|
||||
is(someProp7.setter.class, "Function", "The eight property setter class is correct.");
|
||||
is(__proto__.value.type, "object", "The __proto__ property value type is correct.");
|
||||
is(__proto__.value.class, "Object", "The __proto__ property value class is correct.");
|
||||
|
||||
|
||||
someProp0.expand();
|
||||
someProp1.expand();
|
||||
someProp2.expand();
|
||||
someProp3.expand();
|
||||
someProp4.expand();
|
||||
someProp7.expand();
|
||||
|
||||
ok(!someProp0.get("__proto__"), "Number primitives should not have a prototype");
|
||||
ok(!someProp1.get("__proto__"), "Boolean primitives should not have a prototype");
|
||||
ok(!someProp2.get("__proto__"), "String literals should not have a prototype");
|
||||
ok(!someProp3.get("__proto__"), "Undefined values should not have a prototype");
|
||||
ok(!someProp4.get("__proto__"), "Null values should not have a prototype");
|
||||
ok(!someProp7.get("__proto__"), "Getter properties should not have a prototype");
|
||||
}
|
||||
|
||||
function testSecondLevelContents() {
|
||||
let someProp5 = gVariable.get("someProp5");
|
||||
|
||||
is(someProp5._store.size, 0, "No properties should be in someProp5 before expanding");
|
||||
someProp5.expand();
|
||||
is(someProp5._store.size, 9, "Some properties should be in someProp5 before expanding");
|
||||
|
||||
let arrayItem0 = someProp5.get("0");
|
||||
let arrayItem1 = someProp5.get("1");
|
||||
let arrayItem2 = someProp5.get("2");
|
||||
let arrayItem3 = someProp5.get("3");
|
||||
let arrayItem4 = someProp5.get("4");
|
||||
let arrayItem5 = someProp5.get("5");
|
||||
let arrayItem6 = someProp5.get("6");
|
||||
let __proto__ = someProp5.get("__proto__");
|
||||
|
||||
is(arrayItem0.visible, true, "The first array item visible state is correct.");
|
||||
is(arrayItem1.visible, true, "The second array item visible state is correct.");
|
||||
is(arrayItem2.visible, true, "The third array item visible state is correct.");
|
||||
is(arrayItem3.visible, true, "The fourth array item visible state is correct.");
|
||||
is(arrayItem4.visible, true, "The fifth array item visible state is correct.");
|
||||
is(arrayItem5.visible, true, "The sixth array item visible state is correct.");
|
||||
is(arrayItem6.visible, true, "The seventh array item visible state is correct.");
|
||||
is(__proto__.visible, true, "The __proto__ property visible state is correct.");
|
||||
|
||||
is(arrayItem0.expanded, false, "The first array item expanded state is correct.");
|
||||
is(arrayItem1.expanded, false, "The second array item expanded state is correct.");
|
||||
is(arrayItem2.expanded, false, "The third array item expanded state is correct.");
|
||||
is(arrayItem3.expanded, false, "The fourth array item expanded state is correct.");
|
||||
is(arrayItem4.expanded, false, "The fifth array item expanded state is correct.");
|
||||
is(arrayItem5.expanded, false, "The sixth array item expanded state is correct.");
|
||||
is(arrayItem6.expanded, false, "The seventh array item expanded state is correct.");
|
||||
is(__proto__.expanded, false, "The __proto__ property expanded state is correct.");
|
||||
|
||||
is(arrayItem0.header, true, "The first array item header state is correct.");
|
||||
is(arrayItem1.header, true, "The second array item header state is correct.");
|
||||
is(arrayItem2.header, true, "The third array item header state is correct.");
|
||||
is(arrayItem3.header, true, "The fourth array item header state is correct.");
|
||||
is(arrayItem4.header, true, "The fifth array item header state is correct.");
|
||||
is(arrayItem5.header, true, "The sixth array item header state is correct.");
|
||||
is(arrayItem6.header, true, "The seventh array item header state is correct.");
|
||||
is(__proto__.header, true, "The __proto__ property header state is correct.");
|
||||
|
||||
is(arrayItem0.twisty, false, "The first array item twisty state is correct.");
|
||||
is(arrayItem1.twisty, false, "The second array item twisty state is correct.");
|
||||
is(arrayItem2.twisty, false, "The third array item twisty state is correct.");
|
||||
is(arrayItem3.twisty, false, "The fourth array item twisty state is correct.");
|
||||
is(arrayItem4.twisty, false, "The fifth array item twisty state is correct.");
|
||||
is(arrayItem5.twisty, true, "The sixth array item twisty state is correct.");
|
||||
is(arrayItem6.twisty, true, "The seventh array item twisty state is correct.");
|
||||
is(__proto__.twisty, true, "The __proto__ property twisty state is correct.");
|
||||
|
||||
is(arrayItem0.name, "0", "The first array item name is correct.");
|
||||
is(arrayItem1.name, "1", "The second array item name is correct.");
|
||||
is(arrayItem2.name, "2", "The third array item name is correct.");
|
||||
is(arrayItem3.name, "3", "The fourth array item name is correct.");
|
||||
is(arrayItem4.name, "4", "The fifth array item name is correct.");
|
||||
is(arrayItem5.name, "5", "The sixth array item name is correct.");
|
||||
is(arrayItem6.name, "6", "The seventh array item name is correct.");
|
||||
is(__proto__.name, "__proto__", "The __proto__ property name is correct.");
|
||||
|
||||
is(arrayItem0.value, 42, "The first array item value is correct.");
|
||||
is(arrayItem1.value, true, "The second array item value is correct.");
|
||||
is(arrayItem2.value, "nasu", "The third array item value is correct.");
|
||||
is(arrayItem3.value.type, "undefined", "The fourth array item value is correct.");
|
||||
is(arrayItem4.value.type, "null", "The fifth array item value is correct.");
|
||||
is(arrayItem5.value.type, "object", "The sixth array item value type is correct.");
|
||||
is(arrayItem5.value.class, "Array", "The sixth array item value class is correct.");
|
||||
is(arrayItem6.value.type, "object", "The seventh array item value type is correct.");
|
||||
is(arrayItem6.value.class, "Object", "The seventh array item value class is correct.");
|
||||
is(__proto__.value.type, "object", "The __proto__ property value type is correct.");
|
||||
is(__proto__.value.class, "Array", "The __proto__ property value class is correct.");
|
||||
|
||||
|
||||
let someProp6 = gVariable.get("someProp6");
|
||||
|
||||
is(someProp6._store.size, 0, "No properties should be in someProp6 before expanding");
|
||||
someProp6.expand();
|
||||
is(someProp6._store.size, 10, "Some properties should be in someProp6 before expanding");
|
||||
|
||||
let objectItem0 = someProp6.get("p0");
|
||||
let objectItem1 = someProp6.get("p1");
|
||||
let objectItem2 = someProp6.get("p2");
|
||||
let objectItem3 = someProp6.get("p3");
|
||||
let objectItem4 = someProp6.get("p4");
|
||||
let objectItem5 = someProp6.get("p5");
|
||||
let objectItem6 = someProp6.get("p6");
|
||||
let objectItem7 = someProp6.get("p7");
|
||||
let objectItem8 = someProp6.get("p8");
|
||||
let __proto__ = someProp6.get("__proto__");
|
||||
|
||||
is(objectItem0.visible, true, "The first object item visible state is correct.");
|
||||
is(objectItem1.visible, true, "The second object item visible state is correct.");
|
||||
is(objectItem2.visible, true, "The third object item visible state is correct.");
|
||||
is(objectItem3.visible, true, "The fourth object item visible state is correct.");
|
||||
is(objectItem4.visible, true, "The fifth object item visible state is correct.");
|
||||
is(objectItem5.visible, true, "The sixth object item visible state is correct.");
|
||||
is(objectItem6.visible, true, "The seventh object item visible state is correct.");
|
||||
is(objectItem7.visible, true, "The eight object item visible state is correct.");
|
||||
is(objectItem8.visible, true, "The ninth object item visible state is correct.");
|
||||
is(__proto__.visible, true, "The __proto__ property visible state is correct.");
|
||||
|
||||
is(objectItem0.expanded, false, "The first object item expanded state is correct.");
|
||||
is(objectItem1.expanded, false, "The second object item expanded state is correct.");
|
||||
is(objectItem2.expanded, false, "The third object item expanded state is correct.");
|
||||
is(objectItem3.expanded, false, "The fourth object item expanded state is correct.");
|
||||
is(objectItem4.expanded, false, "The fifth object item expanded state is correct.");
|
||||
is(objectItem5.expanded, false, "The sixth object item expanded state is correct.");
|
||||
is(objectItem6.expanded, false, "The seventh object item expanded state is correct.");
|
||||
is(objectItem7.expanded, true, "The eight object item expanded state is correct.");
|
||||
is(objectItem8.expanded, true, "The ninth object item expanded state is correct.");
|
||||
is(__proto__.expanded, false, "The __proto__ property expanded state is correct.");
|
||||
|
||||
is(objectItem0.header, true, "The first object item header state is correct.");
|
||||
is(objectItem1.header, true, "The second object item header state is correct.");
|
||||
is(objectItem2.header, true, "The third object item header state is correct.");
|
||||
is(objectItem3.header, true, "The fourth object item header state is correct.");
|
||||
is(objectItem4.header, true, "The fifth object item header state is correct.");
|
||||
is(objectItem5.header, true, "The sixth object item header state is correct.");
|
||||
is(objectItem6.header, true, "The seventh object item header state is correct.");
|
||||
is(objectItem7.header, true, "The eight object item header state is correct.");
|
||||
is(objectItem8.header, true, "The ninth object item header state is correct.");
|
||||
is(__proto__.header, true, "The __proto__ property header state is correct.");
|
||||
|
||||
is(objectItem0.twisty, false, "The first object item twisty state is correct.");
|
||||
is(objectItem1.twisty, false, "The second object item twisty state is correct.");
|
||||
is(objectItem2.twisty, false, "The third object item twisty state is correct.");
|
||||
is(objectItem3.twisty, false, "The fourth object item twisty state is correct.");
|
||||
is(objectItem4.twisty, false, "The fifth object item twisty state is correct.");
|
||||
is(objectItem5.twisty, true, "The sixth object item twisty state is correct.");
|
||||
is(objectItem6.twisty, true, "The seventh object item twisty state is correct.");
|
||||
is(objectItem7.twisty, true, "The eight object item twisty state is correct.");
|
||||
is(objectItem8.twisty, true, "The ninth object item twisty state is correct.");
|
||||
is(__proto__.twisty, true, "The __proto__ property twisty state is correct.");
|
||||
|
||||
is(objectItem0.name, "p0", "The first object item name is correct.");
|
||||
is(objectItem1.name, "p1", "The second object item name is correct.");
|
||||
is(objectItem2.name, "p2", "The third object item name is correct.");
|
||||
is(objectItem3.name, "p3", "The fourth object item name is correct.");
|
||||
is(objectItem4.name, "p4", "The fifth object item name is correct.");
|
||||
is(objectItem5.name, "p5", "The sixth object item name is correct.");
|
||||
is(objectItem6.name, "p6", "The seventh object item name is correct.");
|
||||
is(objectItem7.name, "p7", "The eight seventh object item name is correct.");
|
||||
is(objectItem8.name, "p8", "The ninth seventh object item name is correct.");
|
||||
is(__proto__.name, "__proto__", "The __proto__ property name is correct.");
|
||||
|
||||
is(objectItem0.value, 42, "The first object item value is correct.");
|
||||
is(objectItem1.value, true, "The second object item value is correct.");
|
||||
is(objectItem2.value, "nasu", "The third object item value is correct.");
|
||||
is(objectItem3.value.type, "undefined", "The fourth object item value is correct.");
|
||||
is(objectItem4.value.type, "null", "The fifth object item value is correct.");
|
||||
is(objectItem5.value.type, "object", "The sixth object item value type is correct.");
|
||||
is(objectItem5.value.class, "Array", "The sixth object item value class is correct.");
|
||||
is(objectItem6.value.type, "object", "The seventh object item value type is correct.");
|
||||
is(objectItem6.value.class, "Object", "The seventh object item value class is correct.");
|
||||
is(objectItem7.value, null, "The eight object item value is correct.");
|
||||
isnot(objectItem7.getter, null, "The eight object item getter is correct.");
|
||||
isnot(objectItem7.setter, null, "The eight object item setter is correct.");
|
||||
is(objectItem7.setter.type, "undefined", "The eight object item setter type is correct.");
|
||||
is(objectItem7.getter.type, "object", "The eight object item getter type is correct.");
|
||||
is(objectItem7.getter.class, "Function", "The eight object item getter class is correct.");
|
||||
is(objectItem8.value, null, "The ninth object item value is correct.");
|
||||
isnot(objectItem8.getter, null, "The ninth object item getter is correct.");
|
||||
isnot(objectItem8.setter, null, "The ninth object item setter is correct.");
|
||||
is(objectItem8.getter.type, "undefined", "The eight object item getter type is correct.");
|
||||
is(objectItem8.setter.type, "object", "The ninth object item setter type is correct.");
|
||||
is(objectItem8.setter.class, "Function", "The ninth object item setter class is correct.");
|
||||
is(__proto__.value.type, "object", "The __proto__ property value type is correct.");
|
||||
is(__proto__.value.class, "Object", "The __proto__ property value class is correct.");
|
||||
}
|
||||
|
||||
function testThirdLevelContents() {
|
||||
(function() {
|
||||
let someProp5 = gVariable.get("someProp5");
|
||||
let arrayItem5 = someProp5.get("5");
|
||||
let arrayItem6 = someProp5.get("6");
|
||||
|
||||
is(arrayItem5._store.size, 0, "No properties should be in arrayItem5 before expanding");
|
||||
arrayItem5.expand();
|
||||
is(arrayItem5._store.size, 5, "Some properties should be in arrayItem5 before expanding");
|
||||
|
||||
is(arrayItem6._store.size, 0, "No properties should be in arrayItem6 before expanding");
|
||||
arrayItem6.expand();
|
||||
is(arrayItem6._store.size, 3, "Some properties should be in arrayItem6 before expanding");
|
||||
|
||||
let arraySubItem0 = arrayItem5.get("0");
|
||||
let arraySubItem1 = arrayItem5.get("1");
|
||||
let arraySubItem2 = arrayItem5.get("2");
|
||||
let objectSubItem0 = arrayItem6.get("prop1");
|
||||
let objectSubItem1 = arrayItem6.get("prop2");
|
||||
|
||||
is(arraySubItem0.value, 0, "The first array sub-item value is correct.");
|
||||
is(arraySubItem1.value, 1, "The second array sub-item value is correct.");
|
||||
is(arraySubItem2.value, 2, "The third array sub-item value is correct.");
|
||||
|
||||
is(objectSubItem0.value, 9, "The first object sub-item value is correct.");
|
||||
is(objectSubItem1.value, 8, "The second object sub-item value is correct.");
|
||||
|
||||
let array__proto__ = arrayItem5.get("__proto__");
|
||||
let object__proto__ = arrayItem6.get("__proto__");
|
||||
|
||||
ok(array__proto__, "The array should have a __proto__ property");
|
||||
ok(object__proto__, "The object should have a __proto__ property");
|
||||
})();
|
||||
|
||||
(function() {
|
||||
let someProp6 = gVariable.get("someProp6");
|
||||
let objectItem5 = someProp6.get("p5");
|
||||
let objectItem6 = someProp6.get("p6");
|
||||
|
||||
is(objectItem5._store.size, 0, "No properties should be in objectItem5 before expanding");
|
||||
objectItem5.expand();
|
||||
is(objectItem5._store.size, 5, "Some properties should be in objectItem5 before expanding");
|
||||
|
||||
is(objectItem6._store.size, 0, "No properties should be in objectItem6 before expanding");
|
||||
objectItem6.expand();
|
||||
is(objectItem6._store.size, 3, "Some properties should be in objectItem6 before expanding");
|
||||
|
||||
let arraySubItem0 = objectItem5.get("0");
|
||||
let arraySubItem1 = objectItem5.get("1");
|
||||
let arraySubItem2 = objectItem5.get("2");
|
||||
let objectSubItem0 = objectItem6.get("prop1");
|
||||
let objectSubItem1 = objectItem6.get("prop2");
|
||||
|
||||
is(arraySubItem0.value, 3, "The first array sub-item value is correct.");
|
||||
is(arraySubItem1.value, 4, "The second array sub-item value is correct.");
|
||||
is(arraySubItem2.value, 5, "The third array sub-item value is correct.");
|
||||
|
||||
is(objectSubItem0.value, 7, "The first object sub-item value is correct.");
|
||||
is(objectSubItem1.value, 6, "The second object sub-item value is correct.");
|
||||
|
||||
let array__proto__ = objectItem5.get("__proto__");
|
||||
let object__proto__ = objectItem6.get("__proto__");
|
||||
|
||||
ok(array__proto__, "The array should have a __proto__ property");
|
||||
ok(object__proto__, "The object should have a __proto__ property");
|
||||
})();
|
||||
}
|
||||
|
||||
function testIntegrity(arr, obj) {
|
||||
is(arr[0], 42, "The first array item should not have changed");
|
||||
is(arr[1], true, "The second array item should not have changed");
|
||||
is(arr[2], "nasu", "The third array item should not have changed");
|
||||
is(arr[3], undefined, "The fourth array item should not have changed");
|
||||
is(arr[4], null, "The fifth array item should not have changed");
|
||||
ok(arr[5] instanceof Array, "The sixth array item should be an Array");
|
||||
is(arr[5][0], 0, "The sixth array item should not have changed");
|
||||
is(arr[5][1], 1, "The sixth array item should not have changed");
|
||||
is(arr[5][2], 2, "The sixth array item should not have changed");
|
||||
ok(arr[6] instanceof Object, "The seventh array item should be an Object");
|
||||
is(arr[6].prop1, 9, "The seventh array item should not have changed");
|
||||
is(arr[6].prop2, 8, "The seventh array item should not have changed");
|
||||
|
||||
is(obj.p0, 42, "The first object property should not have changed");
|
||||
is(obj.p1, true, "The first object property should not have changed");
|
||||
is(obj.p2, "nasu", "The first object property should not have changed");
|
||||
is(obj.p3, undefined, "The first object property should not have changed");
|
||||
is(obj.p4, null, "The first object property should not have changed");
|
||||
ok(obj.p5 instanceof Array, "The sixth object property should be an Array");
|
||||
is(obj.p5[0], 3, "The sixth object property should not have changed");
|
||||
is(obj.p5[1], 4, "The sixth object property should not have changed");
|
||||
is(obj.p5[2], 5, "The sixth object property should not have changed");
|
||||
ok(obj.p6 instanceof Object, "The seventh object property should be an Object");
|
||||
is(obj.p6.prop1, 7, "The seventh object property should not have changed");
|
||||
is(obj.p6.prop2, 6, "The seventh object property should not have changed");
|
||||
}
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
removeTab(gTab);
|
||||
gPane = null;
|
||||
gTab = null;
|
||||
gDebugger = null;
|
||||
gVariablesView = null;
|
||||
gScope = null;
|
||||
gVariable = null;
|
||||
});
|
|
@ -0,0 +1,483 @@
|
|||
/* 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 name.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.contentWindow;
|
||||
gDebuggee = aDebuggee;
|
||||
|
||||
testSearchbox();
|
||||
prepareVariables(testVariablesFiltering);
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
"There should be a searchbox available after enabling.");
|
||||
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
|
||||
"There searchbox element should be found.");
|
||||
|
||||
|
||||
gDebugger.DebuggerView.Variables.disableSearch();
|
||||
ok(!gDebugger.DebuggerView.Variables._searchboxNode,
|
||||
"There shouldn't be a searchbox available after disabling.");
|
||||
ok(!gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
|
||||
"There searchbox element should not be found.");
|
||||
|
||||
gDebugger.DebuggerView.Variables.enableSearch();
|
||||
ok(gDebugger.DebuggerView.Variables._searchboxNode,
|
||||
"There should be a searchbox available after enabling.");
|
||||
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
|
||||
"There searchbox element should be found.");
|
||||
|
||||
let placeholder = "freshly squeezed mango juice";
|
||||
|
||||
gDebugger.DebuggerView.Variables.searchPlaceholder = placeholder;
|
||||
ok(gDebugger.DebuggerView.Variables._searchboxNode.getAttribute("placeholder"),
|
||||
placeholder, "There correct placeholder should be applied to the searchbox.");
|
||||
|
||||
|
||||
gDebugger.DebuggerView.Variables.disableSearch();
|
||||
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.enableSearch();
|
||||
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.");
|
||||
|
||||
|
||||
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 test1()
|
||||
{
|
||||
write("location");
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, true,
|
||||
"The mathScope expanded getter should return true");
|
||||
is(testScopeItem.expanded, true,
|
||||
"The testScope expanded getter should return true");
|
||||
is(loadScopeItem.expanded, true,
|
||||
"The loadScope expanded getter should return true");
|
||||
is(globalScopeItem.expanded, true,
|
||||
"The globalScope expanded getter should return true");
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded");
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded");
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded");
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded");
|
||||
|
||||
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, 1,
|
||||
"There should be 1 variable displayed in the global scope");
|
||||
|
||||
is(innerScope.querySelectorAll(".property:not([non-match])").length, 6,
|
||||
"There should be 6 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"),
|
||||
"this", "The only inner variable displayed should be 'this'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
"window", "The first inner property displayed should be 'window'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"document", "The second inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
"location", "The third inner property displayed should be 'location'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
"__proto__", "The fourth inner property displayed should be '__proto__'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
|
||||
"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"),
|
||||
"Location", "The only global variable displayed should be 'Location'");
|
||||
}
|
||||
|
||||
function test2()
|
||||
{
|
||||
innerScopeItem.collapse();
|
||||
mathScopeItem.collapse();
|
||||
testScopeItem.collapse();
|
||||
loadScopeItem.collapse();
|
||||
globalScopeItem.collapse();
|
||||
thisItem.collapse();
|
||||
windowItem.collapse();
|
||||
documentItem.collapse();
|
||||
locationItem.collapse();
|
||||
|
||||
is(innerScopeItem.expanded, false,
|
||||
"The innerScope expanded getter should return false");
|
||||
is(mathScopeItem.expanded, false,
|
||||
"The mathScope expanded getter should return false");
|
||||
is(testScopeItem.expanded, false,
|
||||
"The testScope expanded getter should return false");
|
||||
is(loadScopeItem.expanded, false,
|
||||
"The loadScope expanded getter should return false");
|
||||
is(globalScopeItem.expanded, false,
|
||||
"The globalScope expanded getter should return false");
|
||||
|
||||
is(thisItem.expanded, false,
|
||||
"The local scope 'this' should not be expanded");
|
||||
is(windowItem.expanded, false,
|
||||
"The local scope 'this.window' should not be expanded");
|
||||
is(documentItem.expanded, false,
|
||||
"The local scope 'this.window.document' should not be expanded");
|
||||
is(locationItem.expanded, false,
|
||||
"The local scope 'this.window.document.location' should not be expanded");
|
||||
|
||||
write("location");
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded");
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded");
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded");
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded");
|
||||
|
||||
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, 1,
|
||||
"There should be 1 variable displayed in the global scope");
|
||||
|
||||
is(innerScope.querySelectorAll(".property:not([non-match])").length, 6,
|
||||
"There should be 6 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"),
|
||||
"this", "The only inner variable displayed should be 'this'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
"window", "The first inner property displayed should be 'window'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"document", "The second inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
"location", "The third inner property displayed should be 'location'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
"__proto__", "The fourth inner property displayed should be '__proto__'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
|
||||
"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"),
|
||||
"Location", "The only global variable displayed should be 'Location'");
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
let thisItem = innerScopeItem.get("this");
|
||||
let windowItem = thisItem.get("window");
|
||||
let documentItem = windowItem.get("document");
|
||||
let locationItem = documentItem.get("location");
|
||||
|
||||
gSearchBox = gDebugger.DebuggerView.Variables._searchboxNode;
|
||||
|
||||
executeSoon(function() {
|
||||
test1();
|
||||
executeSoon(function() {
|
||||
test2();
|
||||
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"));
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, false,
|
||||
"The mathScope expanded getter should return false");
|
||||
is(testScopeItem.expanded, false,
|
||||
"The testScope expanded getter should return false");
|
||||
is(loadScopeItem.expanded, false,
|
||||
"The loadScope expanded getter should return false");
|
||||
is(globalScopeItem.expanded, false,
|
||||
"The globalScope expanded getter should return false");
|
||||
|
||||
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);
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, true,
|
||||
"The mathScope expanded getter should return true");
|
||||
is(testScopeItem.expanded, true,
|
||||
"The testScope expanded getter should return true");
|
||||
is(loadScopeItem.expanded, true,
|
||||
"The loadScope expanded getter should return true");
|
||||
is(globalScopeItem.expanded, true,
|
||||
"The globalScope expanded getter should return true");
|
||||
|
||||
|
||||
let thisItem = innerScopeItem.get("this");
|
||||
is(thisItem.expanded, false,
|
||||
"The local scope 'this' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test2() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test2, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let windowItem = thisItem.get("window");
|
||||
is(windowItem.expanded, false,
|
||||
"The local scope 'this.window' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test3() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test3, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let documentItem = windowItem.get("document");
|
||||
is(documentItem.expanded, false,
|
||||
"The local scope 'this.window.document' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test4() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test4, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let locationItem = documentItem.get("location");
|
||||
is(locationItem.expanded, false,
|
||||
"The local scope 'this.window.document.location' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test5() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test5, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded");
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded");
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded");
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded");
|
||||
|
||||
executeSoon(function() {
|
||||
aCallback();
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
locationItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
documentItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
windowItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
thisItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded now");
|
||||
});
|
||||
}}, 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 ((name.contains("tracemallocdumpallocations")) ||
|
||||
(name.contains("geolocation")) ||
|
||||
(name.contains("webgl"))) {
|
||||
item.target.setAttribute("non-match", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
gSearchBox.focus();
|
||||
gSearchBox.value = "";
|
||||
}
|
||||
|
||||
function write(text) {
|
||||
clear();
|
||||
append(text);
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
|
@ -0,0 +1,417 @@
|
|||
/* 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;
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
function test()
|
||||
{
|
||||
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||
gTab = aTab;
|
||||
gPane = aPane;
|
||||
gDebugger = gPane.contentWindow;
|
||||
gDebuggee = aDebuggee;
|
||||
|
||||
testSearchbox();
|
||||
prepareVariables(testVariablesFiltering);
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
"There should be a searchbox available after enabling.");
|
||||
ok(gDebugger.DebuggerView.Variables._parent.querySelector(".devtools-searchinput"),
|
||||
"There searchbox element should be found.");
|
||||
}
|
||||
|
||||
function testVariablesFiltering()
|
||||
{
|
||||
function test1()
|
||||
{
|
||||
write("htmldocument");
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, true,
|
||||
"The mathScope expanded getter should return true");
|
||||
is(testScopeItem.expanded, true,
|
||||
"The testScope expanded getter should return true");
|
||||
is(loadScopeItem.expanded, true,
|
||||
"The loadScope expanded getter should return true");
|
||||
is(globalScopeItem.expanded, true,
|
||||
"The globalScope expanded getter should return true");
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded");
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded");
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded");
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded");
|
||||
|
||||
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, 2,
|
||||
"There should be 2 variables displayed in the global scope");
|
||||
|
||||
is(innerScope.querySelectorAll(".property:not([non-match])").length, 8,
|
||||
"There should be 8 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"),
|
||||
"this", "The only inner variable displayed should be 'this'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
"document", "The first inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"window", "The second inner property displayed should be 'window'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
"document", "The third inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
"location", "The fourth inner property displayed should be 'location'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
|
||||
"__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"),
|
||||
"document", "The first global variable displayed should be 'document'");
|
||||
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"HTMLDocument", "The first global variable displayed should be 'HTMLDocument'");
|
||||
}
|
||||
|
||||
function test2()
|
||||
{
|
||||
innerScopeItem.collapse();
|
||||
mathScopeItem.collapse();
|
||||
testScopeItem.collapse();
|
||||
loadScopeItem.collapse();
|
||||
globalScopeItem.collapse();
|
||||
thisItem.collapse();
|
||||
windowItem.collapse();
|
||||
documentItem.collapse();
|
||||
locationItem.collapse();
|
||||
|
||||
is(innerScopeItem.expanded, false,
|
||||
"The innerScope expanded getter should return false");
|
||||
is(mathScopeItem.expanded, false,
|
||||
"The mathScope expanded getter should return false");
|
||||
is(testScopeItem.expanded, false,
|
||||
"The testScope expanded getter should return false");
|
||||
is(loadScopeItem.expanded, false,
|
||||
"The loadScope expanded getter should return false");
|
||||
is(globalScopeItem.expanded, false,
|
||||
"The globalScope expanded getter should return false");
|
||||
|
||||
is(thisItem.expanded, false,
|
||||
"The local scope 'this' should not be expanded");
|
||||
is(windowItem.expanded, false,
|
||||
"The local scope 'this.window' should not be expanded");
|
||||
is(documentItem.expanded, false,
|
||||
"The local scope 'this.window.document' should not be expanded");
|
||||
is(locationItem.expanded, false,
|
||||
"The local scope 'this.window.document.location' should not be expanded");
|
||||
|
||||
write("htmldocument");
|
||||
|
||||
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, 2,
|
||||
"There should be 2 variables displayed in the global scope");
|
||||
|
||||
is(innerScope.querySelectorAll(".property:not([non-match])").length, 8,
|
||||
"There should be 8 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"),
|
||||
"this", "The only inner variable displayed should be 'this'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[0].getAttribute("value"),
|
||||
"document", "The first inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"window", "The second inner property displayed should be 'window'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[2].getAttribute("value"),
|
||||
"document", "The third inner property displayed should be 'document'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[3].getAttribute("value"),
|
||||
"location", "The fourth inner property displayed should be 'location'");
|
||||
is(innerScope.querySelectorAll(".property:not([non-match]) > .title > .name")[4].getAttribute("value"),
|
||||
"__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"),
|
||||
"document", "The first global variable displayed should be 'document'");
|
||||
is(globalScope.querySelectorAll(".variable:not([non-match]) > .title > .name")[1].getAttribute("value"),
|
||||
"HTMLDocument", "The first global variable displayed should be 'HTMLDocument'");
|
||||
}
|
||||
|
||||
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"));
|
||||
|
||||
let thisItem = innerScopeItem.get("this");
|
||||
let windowItem = thisItem.get("window");
|
||||
let documentItem = windowItem.get("document");
|
||||
let locationItem = documentItem.get("location");
|
||||
|
||||
gSearchBox = gDebugger.DebuggerView.Variables._searchboxNode;
|
||||
|
||||
executeSoon(function() {
|
||||
test1();
|
||||
executeSoon(function() {
|
||||
test2();
|
||||
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"));
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, false,
|
||||
"The mathScope expanded getter should return false");
|
||||
is(testScopeItem.expanded, false,
|
||||
"The testScope expanded getter should return false");
|
||||
is(loadScopeItem.expanded, false,
|
||||
"The loadScope expanded getter should return false");
|
||||
is(globalScopeItem.expanded, false,
|
||||
"The globalScope expanded getter should return false");
|
||||
|
||||
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);
|
||||
|
||||
is(innerScopeItem.expanded, true,
|
||||
"The innerScope expanded getter should return true");
|
||||
is(mathScopeItem.expanded, true,
|
||||
"The mathScope expanded getter should return true");
|
||||
is(testScopeItem.expanded, true,
|
||||
"The testScope expanded getter should return true");
|
||||
is(loadScopeItem.expanded, true,
|
||||
"The loadScope expanded getter should return true");
|
||||
is(globalScopeItem.expanded, true,
|
||||
"The globalScope expanded getter should return true");
|
||||
|
||||
|
||||
let thisItem = innerScopeItem.get("this");
|
||||
is(thisItem.expanded, false,
|
||||
"The local scope 'this' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test2() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test2, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let windowItem = thisItem.get("window");
|
||||
is(windowItem.expanded, false,
|
||||
"The local scope 'this.window' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test3() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test3, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let documentItem = windowItem.get("document");
|
||||
is(documentItem.expanded, false,
|
||||
"The local scope 'this.window.document' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test4() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test4, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let locationItem = documentItem.get("location");
|
||||
is(locationItem.expanded, false,
|
||||
"The local scope 'this.window.document.location' should not be expanded yet");
|
||||
|
||||
gDebugger.addEventListener("Debugger:FetchedProperties", function test5() {
|
||||
gDebugger.removeEventListener("Debugger:FetchedProperties", test5, false);
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded");
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded");
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded");
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded");
|
||||
|
||||
executeSoon(function() {
|
||||
aCallback();
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
locationItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(locationItem.expanded, true,
|
||||
"The local scope 'this.window.document.location' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
documentItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(documentItem.expanded, true,
|
||||
"The local scope 'this.window.document' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
windowItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(windowItem.expanded, true,
|
||||
"The local scope 'this.window' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
executeSoon(function() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
thisItem.target.querySelector(".arrow"),
|
||||
gDebuggee.window);
|
||||
|
||||
is(thisItem.expanded, true,
|
||||
"The local scope 'this' should be expanded now");
|
||||
});
|
||||
}}, 0);
|
||||
}, false);
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebuggee.document.querySelector("button"),
|
||||
gDebuggee.window);
|
||||
}
|
||||
|
||||
function clear() {
|
||||
gSearchBox.focus();
|
||||
gSearchBox.value = "";
|
||||
}
|
||||
|
||||
function write(text) {
|
||||
clear();
|
||||
append(text);
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
|
@ -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;
|
||||
});
|
|
@ -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;
|
||||
});
|
|
@ -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;
|
||||
});
|
|
@ -29,12 +29,27 @@ function VariablesView(aParentNode) {
|
|||
this._parent = aParentNode;
|
||||
this._appendEmptyNotice();
|
||||
|
||||
this._onSearchboxInput = this._onSearchboxInput.bind(this);
|
||||
this._onSearchboxKeyPress = this._onSearchboxKeyPress.bind(this);
|
||||
|
||||
// Create an internal list container.
|
||||
this._list = this.document.createElement("vbox");
|
||||
this._parent.appendChild(this._list);
|
||||
}
|
||||
|
||||
VariablesView.prototype = {
|
||||
/**
|
||||
* Helper setter for populating this container with a raw object.
|
||||
*
|
||||
* @param object aData
|
||||
* The raw object to display. You can only provide this object
|
||||
* if you want the variables view to work in sync mode.
|
||||
*/
|
||||
set rawObject(aObject) {
|
||||
this.empty();
|
||||
this.addScope().addVar().populate(aObject);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a scope to contain any inspected variables.
|
||||
*
|
||||
|
@ -43,12 +58,13 @@ VariablesView.prototype = {
|
|||
* @return Scope
|
||||
* The newly created Scope instance.
|
||||
*/
|
||||
addScope: function VV_addScope(aName) {
|
||||
addScope: function VV_addScope(aName = "") {
|
||||
this._removeEmptyNotice();
|
||||
|
||||
let scope = new Scope(this, aName);
|
||||
this._store.set(scope.id, scope);
|
||||
this._currHierarchy.set(aName, scope);
|
||||
scope.header = !!aName;
|
||||
return scope;
|
||||
},
|
||||
|
||||
|
@ -140,6 +156,125 @@ VariablesView.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables variable and property searching in this view.
|
||||
*/
|
||||
enableSearch: function VV_enableSearch() {
|
||||
// If searching was already enabled, no need to re-enable it again.
|
||||
if (this._searchboxContainer) {
|
||||
return;
|
||||
}
|
||||
let document = this.document;
|
||||
let parent = this._parent;
|
||||
|
||||
let container = this._searchboxContainer = document.createElement("hbox");
|
||||
container.className = "devtools-toolbar";
|
||||
|
||||
let searchbox = this._searchboxNode = document.createElement("textbox");
|
||||
searchbox.className = "devtools-searchinput";
|
||||
searchbox.setAttribute("placeholder", this._searchboxPlaceholder);
|
||||
searchbox.setAttribute("type", "search");
|
||||
searchbox.setAttribute("flex", "1");
|
||||
searchbox.addEventListener("input", this._onSearchboxInput, false);
|
||||
searchbox.addEventListener("keypress", this._onSearchboxKeyPress, false);
|
||||
|
||||
container.appendChild(searchbox);
|
||||
parent.insertBefore(container, parent.firstChild);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables variable and property searching in this view.
|
||||
*/
|
||||
disableSearch: function VV_disableSearch() {
|
||||
// If searching was already disabled, no need to re-disable it again.
|
||||
if (!this._searchboxContainer) {
|
||||
return;
|
||||
}
|
||||
this._parent.removeChild(this._searchboxContainer);
|
||||
this._searchboxNode.addEventListener("input", this._onSearchboxInput, false);
|
||||
this._searchboxNode.addEventListener("keypress", this._onSearchboxKeyPress, false);
|
||||
|
||||
this._searchboxContainer = 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
|
||||
* the query, and hides non-matched items.
|
||||
*
|
||||
* @param string aQuery
|
||||
* The variable or property to search for.
|
||||
*/
|
||||
performSearch: function VV_performSerch(aQuery) {
|
||||
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 [_, variable] in scope) {
|
||||
if (variable._isMatch) {
|
||||
variable.expand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the text displayed for the searchbox in this container.
|
||||
* @param string aValue
|
||||
*/
|
||||
set searchPlaceholder(aValue) {
|
||||
if (this._searchboxNode) {
|
||||
this._searchboxNode.setAttribute("placeholder", aValue);
|
||||
}
|
||||
this._searchboxPlaceholder = aValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener handling the searchbox input event.
|
||||
*/
|
||||
_onSearchboxInput: function VV__onSearchboxInput() {
|
||||
this.performSearch(this._searchboxNode.value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener handling the searchbox key press event.
|
||||
*/
|
||||
_onSearchboxKeyPress: function VV__onSearchboxKeyPress(e) {
|
||||
switch(e.keyCode) {
|
||||
case e.DOM_VK_RETURN:
|
||||
case e.DOM_VK_ENTER:
|
||||
this._onSearchboxInput();
|
||||
return;
|
||||
case e.DOM_VK_ESCAPE:
|
||||
this._searchboxNode.value = "";
|
||||
this._onSearchboxInput();
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the text displayed in this container when there are no available items.
|
||||
* @param string aValue
|
||||
|
@ -205,8 +340,11 @@ VariablesView.prototype = {
|
|||
_emptyTimeout: null,
|
||||
_enumVisible: true,
|
||||
_nonEnumVisible: true,
|
||||
_list: null,
|
||||
_parent: null,
|
||||
_list: null,
|
||||
_searchboxNode: null,
|
||||
_searchboxContainer: null,
|
||||
_searchboxPlaceholder: "",
|
||||
_emptyTextNode: null,
|
||||
_emptyTextValue: ""
|
||||
};
|
||||
|
@ -257,7 +395,7 @@ Scope.prototype = {
|
|||
* @return Variable
|
||||
* The newly created Variable instance, null if it already exists.
|
||||
*/
|
||||
addVar: function S_addVar(aName, aDescriptor = {}) {
|
||||
addVar: function S_addVar(aName = "", aDescriptor = {}) {
|
||||
if (this._store.has(aName)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -265,6 +403,7 @@ Scope.prototype = {
|
|||
let variable = new Variable(this, aName, aDescriptor);
|
||||
this._store.set(aName, variable);
|
||||
this._variablesView._currHierarchy.set(variable._absoluteName, variable);
|
||||
variable.header = !!aName;
|
||||
return variable;
|
||||
},
|
||||
|
||||
|
@ -309,7 +448,7 @@ Scope.prototype = {
|
|||
* Pass true to not show an opening animation.
|
||||
*/
|
||||
expand: function S_expand(aSkipAnimationFlag) {
|
||||
if (this._locked) {
|
||||
if (this._isExpanded || this._locked) {
|
||||
return;
|
||||
}
|
||||
if (this._variablesView._enumVisible) {
|
||||
|
@ -334,7 +473,7 @@ Scope.prototype = {
|
|||
* Collapses the scope, hiding all the added details.
|
||||
*/
|
||||
collapse: function S_collapse() {
|
||||
if (this._locked) {
|
||||
if (!this._isExpanded || this._locked) {
|
||||
return;
|
||||
}
|
||||
this._arrow.removeAttribute("open");
|
||||
|
@ -353,6 +492,7 @@ Scope.prototype = {
|
|||
* Toggles between the scope's collapsed and expanded state.
|
||||
*/
|
||||
toggle: function S_toggle() {
|
||||
this._wasToggled = true;
|
||||
this.expanded ^= 1;
|
||||
|
||||
if (this.ontoggle) {
|
||||
|
@ -360,6 +500,24 @@ Scope.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the scope's title header.
|
||||
*/
|
||||
showHeader: function S_showHeader() {
|
||||
this._target.removeAttribute("non-header");
|
||||
this._isHeaderVisible = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides the scope's title header.
|
||||
* This action will automatically expand the scope.
|
||||
*/
|
||||
hideHeader: function S_hideHeader() {
|
||||
this.expand();
|
||||
this._target.setAttribute("non-header", "");
|
||||
this._isHeaderVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the scope's expand/collapse arrow.
|
||||
*/
|
||||
|
@ -388,6 +546,12 @@ Scope.prototype = {
|
|||
*/
|
||||
get expanded() this._isExpanded,
|
||||
|
||||
/**
|
||||
* Gets the header visibility state.
|
||||
* @return boolean
|
||||
*/
|
||||
get header() this._isHeaderVisible,
|
||||
|
||||
/**
|
||||
* Gets the twisty visibility state.
|
||||
* @return boolean
|
||||
|
@ -406,6 +570,12 @@ Scope.prototype = {
|
|||
*/
|
||||
set expanded(aFlag) aFlag ? this.expand() : this.collapse(),
|
||||
|
||||
/**
|
||||
* Sets the header visibility state.
|
||||
* @param boolean aFlag
|
||||
*/
|
||||
set header(aFlag) aFlag ? this.showHeader() : this.hideHeader(),
|
||||
|
||||
/**
|
||||
* Sets the twisty visibility state.
|
||||
* @param boolean aFlag
|
||||
|
@ -531,6 +701,75 @@ Scope.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs a case insensitive search for variables or properties matching
|
||||
* the query, and hides non-matched items.
|
||||
*
|
||||
* @param string aLowerCaseQuery
|
||||
* The lowercased name of the variable or property to search for.
|
||||
*/
|
||||
_performSearch: function S__performSearch(aLowerCaseQuery) {
|
||||
for (let [_, variable] in this) {
|
||||
let currentObject = variable;
|
||||
let lowerCaseName = variable._nameString.toLowerCase();
|
||||
let lowerCaseValue = variable._valueString.toLowerCase();
|
||||
|
||||
// Non-matched variables or properties require a corresponding attribute.
|
||||
if (!lowerCaseName.contains(aLowerCaseQuery) &&
|
||||
!lowerCaseValue.contains(aLowerCaseQuery)) {
|
||||
variable._match = false;
|
||||
}
|
||||
// Variable or property is matched.
|
||||
else {
|
||||
variable._match = true;
|
||||
|
||||
// If the variable was ever expanded, there's a possibility it may
|
||||
// contain some matched properties, so make sure they're visible
|
||||
// ("expand downwards").
|
||||
|
||||
if (variable._wasToggled) {
|
||||
variable.expand(true);
|
||||
}
|
||||
|
||||
// If the variable is contained in another scope (variable or property),
|
||||
// the parent may not be a match, thus hidden. It should be visible
|
||||
// ("expand upwards").
|
||||
|
||||
while ((variable = variable.ownerView) && /* Parent object exists. */
|
||||
(variable instanceof Scope ||
|
||||
variable instanceof Variable ||
|
||||
variable instanceof Property)) {
|
||||
|
||||
// Show and expand the parent, as it is certainly accessible.
|
||||
variable._match = true;
|
||||
variable.expand(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Proceed with the search recursively inside this variable or property.
|
||||
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", "");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets top level variables view instance.
|
||||
* @return VariablesView
|
||||
|
@ -565,14 +804,18 @@ Scope.prototype = {
|
|||
|
||||
ownerView: null,
|
||||
eval: null,
|
||||
fetched: false,
|
||||
_committed: false,
|
||||
_locked: false,
|
||||
_isShown: true,
|
||||
_isExpanded: false,
|
||||
_wasToggled: false,
|
||||
_isHeaderVisible: true,
|
||||
_isArrowVisible: true,
|
||||
_isMatch: true,
|
||||
_store: null,
|
||||
_idString: null,
|
||||
_nameString: null,
|
||||
_idString: "",
|
||||
_nameString: "",
|
||||
_target: null,
|
||||
_arrow: null,
|
||||
_name: null,
|
||||
|
@ -626,7 +869,7 @@ create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
* @return Property
|
||||
* The newly created Property instance, null if it already exists.
|
||||
*/
|
||||
addProperty: function V_addProperty(aName, aDescriptor = {}) {
|
||||
addProperty: function V_addProperty(aName = "", aDescriptor = {}) {
|
||||
if (this._store.has(aName)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -634,6 +877,7 @@ create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
let property = new Property(this, aName, aDescriptor);
|
||||
this._store.set(aName, property);
|
||||
this._variablesView._currHierarchy.set(property._absoluteName, property);
|
||||
property.header = !!aName;
|
||||
return property;
|
||||
},
|
||||
|
||||
|
@ -663,6 +907,98 @@ create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Populates this variable to contain all the properties of an object.
|
||||
*
|
||||
* @param object aObject
|
||||
* The raw object you want to display.
|
||||
*/
|
||||
populate: function V_populate(aObject) {
|
||||
// Retrieve the properties only once.
|
||||
if (this.fetched) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort all of the properties before adding them.
|
||||
let sortedPropertyNames = Object.getOwnPropertyNames(aObject).sort();
|
||||
let prototype = Object.getPrototypeOf(aObject);
|
||||
|
||||
// Add all the variable properties.
|
||||
for (let name of sortedPropertyNames) {
|
||||
let descriptor = Object.getOwnPropertyDescriptor(aObject, name);
|
||||
if (descriptor.get || descriptor.set) {
|
||||
this._addRawNonValueProperty(name, descriptor);
|
||||
} else {
|
||||
this._addRawValueProperty(name, descriptor, aObject[name]);
|
||||
}
|
||||
}
|
||||
// Add the variable's __proto__.
|
||||
if (prototype) {
|
||||
this._addRawValueProperty("__proto__", {}, prototype);
|
||||
}
|
||||
|
||||
this.fetched = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a property for this variable based on a raw value descriptor.
|
||||
*
|
||||
* @param string aName
|
||||
* The property's name.
|
||||
* @param object aDescriptor
|
||||
* Specifies the exact property descriptor as returned by a call to
|
||||
* Object.getOwnPropertyDescriptor.
|
||||
* @param object aValue
|
||||
* The raw property value you want to display.
|
||||
*/
|
||||
_addRawValueProperty: function V__addRawValueProperty(aName, aDescriptor, aValue) {
|
||||
let descriptor = Object.create(aDescriptor);
|
||||
descriptor.value = VariablesView.getGrip(aValue);
|
||||
|
||||
let propertyItem = this.addProperty(aName, descriptor);
|
||||
|
||||
// Add an 'onexpand' callback for the property, lazily handling
|
||||
// the addition of new child properties.
|
||||
if (!VariablesView.isPrimitive(descriptor)) {
|
||||
propertyItem.onexpand = this.populate.bind(propertyItem, aValue);
|
||||
}
|
||||
|
||||
return propertyItem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a property for this variable based on a getter/setter descriptor.
|
||||
*
|
||||
* @param string aName
|
||||
* The property's name.
|
||||
* @param object aDescriptor
|
||||
* Specifies the exact property descriptor as returned by a call to
|
||||
* Object.getOwnPropertyDescriptor.
|
||||
*/
|
||||
_addRawNonValueProperty: function V__addRawNonValueProperty(aName, aDescriptor) {
|
||||
let descriptor = Object.create(aDescriptor);
|
||||
descriptor.get = VariablesView.getGrip(aDescriptor.get);
|
||||
descriptor.set = VariablesView.getGrip(aDescriptor.set);
|
||||
|
||||
let propertyItem = this.addProperty(aName, descriptor);
|
||||
return propertyItem;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns this variable's value from the descriptor if available,
|
||||
*/
|
||||
get value() this._initialDescriptor.value,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* The grip should contain the value or the type & class, as defined in the
|
||||
|
@ -754,8 +1090,8 @@ create({ constructor: Variable, proto: Scope.prototype }, {
|
|||
this.hideArrow();
|
||||
}
|
||||
if (aDescriptor.get || aDescriptor.set) {
|
||||
this.addProperty("get ", { value: aDescriptor.get });
|
||||
this.addProperty("set ", { value: aDescriptor.set });
|
||||
this.addProperty("get", { value: aDescriptor.get });
|
||||
this.addProperty("set", { value: aDescriptor.set });
|
||||
this.expand(true);
|
||||
separatorLabel.hidden = true;
|
||||
valueLabel.hidden = true;
|
||||
|
@ -1092,6 +1428,31 @@ VariablesView.isPrimitive = function VV_isPrimitive(aDescriptor) {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a standard grip for a value.
|
||||
*
|
||||
* @param any aValue
|
||||
* The raw value to get a grip for.
|
||||
* @return any
|
||||
* The value's grip.
|
||||
*/
|
||||
VariablesView.getGrip = function VV_getGrip(aValue) {
|
||||
if (aValue === undefined) {
|
||||
return { type: "undefined" };
|
||||
}
|
||||
if (aValue === null) {
|
||||
return { type: "null" };
|
||||
}
|
||||
if (typeof aValue == "object" || typeof aValue == "function") {
|
||||
if (aValue.constructor) {
|
||||
return { type: "object", class: aValue.constructor.name };
|
||||
} else {
|
||||
return { type: "object", class: "Object" };
|
||||
}
|
||||
}
|
||||
return aValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a custom formatted property string for a grip.
|
||||
*
|
|
@ -49,6 +49,11 @@
|
|||
<!ENTITY debuggerUI.showPanesOnInit "Show panes on startup">
|
||||
<!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
|
||||
- checkbox that toggles visibility of hidden (non-enumerable) variables and
|
||||
- properties in stack views. -->
|
||||
|
|
|
@ -103,10 +103,15 @@ noMatchingStringsText=No matches found
|
|||
# filter text box when it is empty and the scripts container is selected.
|
||||
emptyFilterText=Filter scripts (%S)
|
||||
|
||||
# LOCALIZATION NOTE (emptyFilterText): This is the text that appears in the
|
||||
# filter text box when it is empty and the chrome globals container is selected.
|
||||
# LOCALIZATION NOTE (emptyChromeGlobalsFilterText): This is the text that
|
||||
# appears in the filter text box when it is empty and the chrome globals
|
||||
# container is selected.
|
||||
emptyChromeGlobalsFilterText=Filter chrome globals (%S)
|
||||
|
||||
# LOCALIZATION NOTE (emptyVariablesFilterText): This is the text that
|
||||
# appears in the filter text box for the variables view container.
|
||||
emptyVariablesFilterText=Filter variables
|
||||
|
||||
# LOCALIZATION NOTE (searchPanelGlobal): This is the text that appears in the
|
||||
# filter panel popup for the global search operation.
|
||||
searchPanelGlobal=Search in all files (%S)
|
||||
|
@ -119,6 +124,10 @@ searchPanelToken=Find in this file (%S)
|
|||
# filter panel popup for the line search operation.
|
||||
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
|
||||
# are displayed in the breakpoints menu item popup.
|
||||
breakpointMenuItem.enableSelf=Enable breakpoint
|
||||
|
|
|
@ -229,7 +229,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.variable > .details {
|
||||
.variable:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.property > .details {
|
||||
.property:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -319,6 +319,20 @@
|
|||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variables and properties searching
|
||||
*/
|
||||
|
||||
#variables .devtools-searchinput {
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable[non-match],
|
||||
.property[non-match] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token value colors
|
||||
*/
|
||||
|
|
|
@ -231,7 +231,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.variable > .details {
|
||||
.variable:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.property > .details {
|
||||
.property:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -321,6 +321,20 @@
|
|||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variables and properties searching
|
||||
*/
|
||||
|
||||
#variables .devtools-searchinput {
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable[non-match],
|
||||
.property[non-match] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token value colors
|
||||
*/
|
||||
|
|
|
@ -237,7 +237,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.variable > .details {
|
||||
.variable:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@
|
|||
-moz-padding-start: 6px;
|
||||
}
|
||||
|
||||
.property > .details {
|
||||
.property:not([non-header]) > .details {
|
||||
-moz-margin-start: 10px;
|
||||
}
|
||||
|
||||
|
@ -327,6 +327,20 @@
|
|||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variables and properties searching
|
||||
*/
|
||||
|
||||
#variables .devtools-searchinput {
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.variable[non-match],
|
||||
.property[non-match] {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token value colors
|
||||
*/
|
||||
|
|
|
@ -451,11 +451,13 @@ nsGenericHTMLElement::GetAccessKeyLabel(nsAString& aLabel)
|
|||
{
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
|
||||
if (presContext &&
|
||||
presContext->EventStateManager()->GetAccessKeyLabelPrefix(aLabel)) {
|
||||
nsAutoString suffix;
|
||||
GetAccessKey(suffix);
|
||||
if (presContext) {
|
||||
nsAutoString suffix;
|
||||
GetAccessKey(suffix);
|
||||
if (!suffix.IsEmpty() &&
|
||||
presContext->EventStateManager()->GetAccessKeyLabelPrefix(aLabel)) {
|
||||
aLabel.Append(suffix);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -72,6 +72,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=583533
|
|||
|
||||
is(label, document.getElementById("e").accessKeyLabel, "JS and C++ agree on accessKeyLabel");
|
||||
|
||||
/** Test for Bug 808964 **/
|
||||
|
||||
var div = document.createElement("div");
|
||||
document.body.appendChild(div);
|
||||
|
||||
is(div.accessKeyLabel, "", "accessKeyLabel should be empty string");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
|
До Ширина: | Высота: | Размер: 370 B После Ширина: | Высота: | Размер: 370 B |
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
|
@ -95,11 +96,11 @@ __wrap_dladdr(void *addr, Dl_info *info)
|
|||
int
|
||||
__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
|
||||
{
|
||||
if (ElfLoader::Singleton.dbg == NULL)
|
||||
if (!ElfLoader::Singleton.dbg)
|
||||
return -1;
|
||||
|
||||
for (ElfLoader::r_debug::iterator it = ElfLoader::Singleton.dbg->begin();
|
||||
it < ElfLoader::Singleton.dbg->end(); ++it) {
|
||||
for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin();
|
||||
it < ElfLoader::Singleton.dbg.end(); ++it) {
|
||||
dl_phdr_info info;
|
||||
info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
|
||||
info.dlpi_name = it->l_name;
|
||||
|
@ -317,7 +318,7 @@ ElfLoader::Register(LibHandle *handle)
|
|||
{
|
||||
handles.push_back(handle);
|
||||
if (dbg && !handle->IsSystemElf())
|
||||
dbg->Add(static_cast<CustomElf *>(handle));
|
||||
dbg.Add(static_cast<CustomElf *>(handle));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -328,7 +329,7 @@ ElfLoader::Forget(LibHandle *handle)
|
|||
debug("ElfLoader::Forget(%p [\"%s\"])", reinterpret_cast<void *>(handle),
|
||||
handle->GetPath());
|
||||
if (dbg && !handle->IsSystemElf())
|
||||
dbg->Remove(static_cast<CustomElf *>(handle));
|
||||
dbg.Remove(static_cast<CustomElf *>(handle));
|
||||
handles.erase(it);
|
||||
} else {
|
||||
debug("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
|
||||
|
@ -433,8 +434,7 @@ ElfLoader::DestructorCaller::Call()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ElfLoader::InitDebugger()
|
||||
ElfLoader::DebuggerHelper::DebuggerHelper(): dbg(NULL)
|
||||
{
|
||||
/* Find ELF auxiliary vectors.
|
||||
*
|
||||
|
@ -577,6 +577,68 @@ ElfLoader::InitDebugger()
|
|||
debug("DT_DEBUG points at %p", dbg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to ensure the given pointer is writable within the scope of
|
||||
* an instance. Permissions to the memory page where the pointer lies are
|
||||
* restored to their original value when the instance is destroyed.
|
||||
*/
|
||||
class EnsureWritable
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
EnsureWritable(T *&ptr)
|
||||
{
|
||||
prot = getProt((uintptr_t) &ptr);
|
||||
if (prot == -1)
|
||||
MOZ_CRASH();
|
||||
/* Pointers are aligned such that their value can't be spanning across
|
||||
* 2 pages. */
|
||||
page = (void*)((uintptr_t) &ptr & PAGE_MASK);
|
||||
if (!(prot & PROT_WRITE))
|
||||
mprotect(page, PAGE_SIZE, prot | PROT_WRITE);
|
||||
}
|
||||
|
||||
~EnsureWritable()
|
||||
{
|
||||
if (!(prot & PROT_WRITE))
|
||||
mprotect(page, PAGE_SIZE, prot);
|
||||
}
|
||||
|
||||
private:
|
||||
int getProt(uintptr_t addr)
|
||||
{
|
||||
/* The interesting part of the /proc/self/maps format looks like:
|
||||
* startAddr-endAddr rwxp */
|
||||
int result = 0;
|
||||
AutoCloseFILE f(fopen("/proc/self/maps", "r"));
|
||||
while (f) {
|
||||
unsigned long long startAddr, endAddr;
|
||||
char perms[5];
|
||||
if (fscanf(f, "%llx-%llx %4s %*1024[^\n] ", &startAddr, &endAddr, perms) != 3)
|
||||
return -1;
|
||||
if (addr < startAddr || addr >= endAddr)
|
||||
continue;
|
||||
if (perms[0] == 'r')
|
||||
result |= PROT_READ;
|
||||
else if (perms[0] != '-')
|
||||
return -1;
|
||||
if (perms[1] == 'w')
|
||||
result |= PROT_WRITE;
|
||||
else if (perms[1] != '-')
|
||||
return -1;
|
||||
if (perms[2] == 'x')
|
||||
result |= PROT_EXEC;
|
||||
else if (perms[2] != '-')
|
||||
return -1;
|
||||
return result;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int prot;
|
||||
void *page;
|
||||
};
|
||||
|
||||
/**
|
||||
* The system linker maintains a doubly linked list of library it loads
|
||||
* for use by the debugger. Unfortunately, it also uses the list pointers
|
||||
|
@ -594,34 +656,48 @@ ElfLoader::InitDebugger()
|
|||
* r_debug::r_map.
|
||||
*/
|
||||
void
|
||||
ElfLoader::r_debug::Add(ElfLoader::link_map *map)
|
||||
ElfLoader::DebuggerHelper::Add(ElfLoader::link_map *map)
|
||||
{
|
||||
if (!r_brk)
|
||||
if (!dbg->r_brk)
|
||||
return;
|
||||
r_state = RT_ADD;
|
||||
r_brk();
|
||||
dbg->r_state = r_debug::RT_ADD;
|
||||
dbg->r_brk();
|
||||
map->l_prev = NULL;
|
||||
map->l_next = r_map;
|
||||
r_map->l_prev = map;
|
||||
r_map = map;
|
||||
r_state = RT_CONSISTENT;
|
||||
r_brk();
|
||||
map->l_next = dbg->r_map;
|
||||
if (!firstAdded) {
|
||||
firstAdded = map;
|
||||
/* When adding a library for the first time, r_map points to data
|
||||
* handled by the system linker, and that data may be read-only */
|
||||
EnsureWritable w(dbg->r_map->l_prev);
|
||||
dbg->r_map->l_prev = map;
|
||||
} else
|
||||
dbg->r_map->l_prev = map;
|
||||
dbg->r_map = map;
|
||||
dbg->r_state = r_debug::RT_CONSISTENT;
|
||||
dbg->r_brk();
|
||||
}
|
||||
|
||||
void
|
||||
ElfLoader::r_debug::Remove(ElfLoader::link_map *map)
|
||||
ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map *map)
|
||||
{
|
||||
if (!r_brk)
|
||||
if (!dbg->r_brk)
|
||||
return;
|
||||
r_state = RT_DELETE;
|
||||
r_brk();
|
||||
if (r_map == map)
|
||||
r_map = map->l_next;
|
||||
dbg->r_state = r_debug::RT_DELETE;
|
||||
dbg->r_brk();
|
||||
if (dbg->r_map == map)
|
||||
dbg->r_map = map->l_next;
|
||||
else
|
||||
map->l_prev->l_next = map->l_next;
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
r_state = RT_CONSISTENT;
|
||||
r_brk();
|
||||
if (map == firstAdded) {
|
||||
firstAdded = map->l_prev;
|
||||
/* When removing the first added library, its l_next is going to be
|
||||
* data handled by the system linker, and that data may be read-only */
|
||||
EnsureWritable w(map->l_next->l_prev);
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
} else
|
||||
map->l_next->l_prev = map->l_prev;
|
||||
dbg->r_state = r_debug::RT_CONSISTENT;
|
||||
dbg->r_brk();
|
||||
}
|
||||
|
||||
SEGVHandler::SEGVHandler()
|
||||
|
|
|
@ -286,7 +286,6 @@ protected:
|
|||
const char *lastError;
|
||||
|
||||
private:
|
||||
ElfLoader() { InitDebugger(); }
|
||||
~ElfLoader();
|
||||
|
||||
/* Bookkeeping */
|
||||
|
@ -368,7 +367,7 @@ private:
|
|||
ZipCollection zips;
|
||||
|
||||
/* Forward declaration, see further below */
|
||||
class r_debug;
|
||||
class DebuggerHelper;
|
||||
public:
|
||||
/* Loaded object descriptor for the debugger interface below*/
|
||||
struct link_map {
|
||||
|
@ -380,7 +379,7 @@ public:
|
|||
const void *l_ld;
|
||||
|
||||
private:
|
||||
friend class ElfLoader::r_debug;
|
||||
friend class ElfLoader::DebuggerHelper;
|
||||
/* Double linked list of loaded objects. */
|
||||
link_map *l_next, *l_prev;
|
||||
};
|
||||
|
@ -388,9 +387,40 @@ public:
|
|||
private:
|
||||
/* Data structure used by the linker to give details about shared objects it
|
||||
* loaded to debuggers. This is normally defined in link.h, but Android
|
||||
* headers lack this file. This also gives the opportunity to make it C++. */
|
||||
class r_debug {
|
||||
* headers lack this file. */
|
||||
struct r_debug {
|
||||
/* Version number of the protocol. */
|
||||
int r_version;
|
||||
|
||||
/* Head of the linked list of loaded objects. */
|
||||
link_map *r_map;
|
||||
|
||||
/* Function to be called when updates to the linked list of loaded objects
|
||||
* are going to occur. The function is to be called before and after
|
||||
* changes. */
|
||||
void (*r_brk)(void);
|
||||
|
||||
/* Indicates to the debugger what state the linked list of loaded objects
|
||||
* is in when the function above is called. */
|
||||
enum {
|
||||
RT_CONSISTENT, /* Changes are complete */
|
||||
RT_ADD, /* Beginning to add a new object */
|
||||
RT_DELETE /* Beginning to remove an object */
|
||||
} r_state;
|
||||
};
|
||||
|
||||
/* Helper class used to integrate libraries loaded by this linker in
|
||||
* r_debug */
|
||||
class DebuggerHelper
|
||||
{
|
||||
public:
|
||||
DebuggerHelper();
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return dbg;
|
||||
}
|
||||
|
||||
/* Make the debugger aware of a new loaded object */
|
||||
void Add(link_map *map);
|
||||
|
||||
|
@ -416,10 +446,10 @@ private:
|
|||
{
|
||||
if (other.item == NULL)
|
||||
return item ? true : false;
|
||||
MOZ_NOT_REACHED("r_debug::iterator::operator< called with something else than r_debug::end()");
|
||||
MOZ_NOT_REACHED("DebuggerHelper::iterator::operator< called with something else than DebuggerHelper::end()");
|
||||
}
|
||||
protected:
|
||||
friend class r_debug;
|
||||
friend class DebuggerHelper;
|
||||
iterator(const link_map *item): item(item) { }
|
||||
|
||||
private:
|
||||
|
@ -428,7 +458,7 @@ private:
|
|||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(r_map);
|
||||
return iterator(dbg ? dbg->r_map : NULL);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
|
@ -437,32 +467,11 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
/* Version number of the protocol. */
|
||||
int r_version;
|
||||
|
||||
/* Head of the linked list of loaded objects. */
|
||||
struct link_map *r_map;
|
||||
|
||||
/* Function to be called when updates to the linked list of loaded objects
|
||||
* are going to occur. The function is to be called before and after
|
||||
* changes. */
|
||||
void (*r_brk)(void);
|
||||
|
||||
/* Indicates to the debugger what state the linked list of loaded objects
|
||||
* is in when the function above is called. */
|
||||
enum {
|
||||
RT_CONSISTENT, /* Changes are complete */
|
||||
RT_ADD, /* Beginning to add a new object */
|
||||
RT_DELETE /* Beginning to remove an object */
|
||||
} r_state;
|
||||
r_debug *dbg;
|
||||
link_map *firstAdded;
|
||||
};
|
||||
friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
|
||||
r_debug *dbg;
|
||||
|
||||
/**
|
||||
* Initializes the pointer to the debugger data structure.
|
||||
*/
|
||||
void InitDebugger();
|
||||
DebuggerHelper dbg;
|
||||
};
|
||||
|
||||
#endif /* ElfLoader_h */
|
||||
|
|
|
@ -90,6 +90,16 @@ struct AutoCloseFDTraits
|
|||
};
|
||||
typedef mozilla::Scoped<AutoCloseFDTraits> AutoCloseFD;
|
||||
|
||||
/**
|
||||
* AutoCloseFILE is a RAII wrapper for POSIX streams
|
||||
*/
|
||||
struct AutoCloseFILETraits
|
||||
{
|
||||
typedef FILE *type;
|
||||
static FILE *empty() { return NULL; }
|
||||
static void release(FILE *f) { fclose(f); }
|
||||
};
|
||||
typedef mozilla::Scoped<AutoCloseFILETraits> AutoCloseFILE;
|
||||
|
||||
/**
|
||||
* MappedPtr is a RAII wrapper for mmap()ed memory. It can be used as
|
||||
|
|
|
@ -19,6 +19,14 @@ import sys
|
|||
import time
|
||||
|
||||
|
||||
def format_seconds(total):
|
||||
"""Format number of seconds to MM:SS.DD form."""
|
||||
|
||||
minutes, seconds = divmod(total, 60)
|
||||
|
||||
return '%2d:%05.2f' % (minutes, seconds)
|
||||
|
||||
|
||||
class ConvertToStructuredFilter(logging.Filter):
|
||||
"""Filter that converts unstructured records into structured ones."""
|
||||
def filter(self, record):
|
||||
|
@ -61,7 +69,8 @@ class StructuredHumanFormatter(logging.Formatter):
|
|||
def format(self, record):
|
||||
elapsed = self._time(record)
|
||||
|
||||
return '%4.2f %s' % (elapsed, record.msg.format(**record.params))
|
||||
return '%s %s' % (format_seconds(elapsed),
|
||||
record.msg.format(**record.params))
|
||||
|
||||
def _time(self, record):
|
||||
t = record.created - self.start_time
|
||||
|
@ -81,7 +90,7 @@ class StructuredTerminalFormatter(StructuredHumanFormatter):
|
|||
self.terminal = terminal
|
||||
|
||||
def format(self, record):
|
||||
t = self.terminal.blue('%4.2f' % self._time(record))
|
||||
t = self.terminal.blue(format_seconds(self._time(record)))
|
||||
f = record.msg.format(**record.params)
|
||||
|
||||
return '%s %s' % (t, self._colorize(f))
|
||||
|
|
|
@ -240,26 +240,14 @@ BrowserRootActor.prototype = {
|
|||
* Prepare to enter a nested event loop by disabling debuggee events.
|
||||
*/
|
||||
preNest: function BRA_preNest() {
|
||||
let top = windowMediator.getMostRecentWindow("navigator:browser");
|
||||
let browser = top.gBrowser.selectedBrowser;
|
||||
let windowUtils = browser.contentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.suppressEventHandling(true);
|
||||
windowUtils.suspendTimeouts();
|
||||
// Nothing to be done here for chrome windows.
|
||||
},
|
||||
|
||||
/**
|
||||
* Prepare to exit a nested event loop by enabling debuggee events.
|
||||
*/
|
||||
postNest: function BRA_postNest(aNestData) {
|
||||
let top = windowMediator.getMostRecentWindow("navigator:browser");
|
||||
let browser = top.gBrowser.selectedBrowser;
|
||||
let windowUtils = browser.contentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.resumeTimeouts();
|
||||
windowUtils.suppressEventHandling(false);
|
||||
// Nothing to be done here for chrome windows.
|
||||
},
|
||||
|
||||
// nsIWindowMediatorListener.
|
||||
|
@ -451,7 +439,7 @@ BrowserTabActor.prototype = {
|
|||
this._contextPool = new ActorPool(this.conn);
|
||||
this.conn.addActorPool(this._contextPool);
|
||||
|
||||
this.threadActor = new ThreadActor(this);
|
||||
this.threadActor = new ThreadActor(this, this.browser.contentWindow.wrappedJSObject);
|
||||
this._contextPool.addActor(this.threadActor);
|
||||
},
|
||||
|
||||
|
|
|
@ -19,22 +19,19 @@
|
|||
* An object with preNest and postNest methods for calling when entering
|
||||
* and exiting a nested event loop, addToParentPool and
|
||||
* removeFromParentPool methods for handling the lifetime of actors that
|
||||
* will outlive the thread, like breakpoints, and also an optional (for
|
||||
* content debugging) browser property for getting a reference to the
|
||||
* content window.
|
||||
* will outlive the thread, like breakpoints.
|
||||
* @param aGlobal object [optional]
|
||||
* An optional (for content debugging only) reference to the content
|
||||
* window.
|
||||
*/
|
||||
function ThreadActor(aHooks)
|
||||
function ThreadActor(aHooks, aGlobal)
|
||||
{
|
||||
this._state = "detached";
|
||||
this._frameActors = [];
|
||||
this._environmentActors = [];
|
||||
this._hooks = {};
|
||||
if (aHooks) {
|
||||
this._hooks = aHooks;
|
||||
if (aHooks.browser) {
|
||||
this.global = aHooks.browser.contentWindow.wrappedJSObject;
|
||||
}
|
||||
}
|
||||
this._hooks = aHooks;
|
||||
this.global = aGlobal;
|
||||
this._scripts = {};
|
||||
this.findGlobals = this.globalManager.findGlobals.bind(this);
|
||||
this.onNewGlobal = this.globalManager.onNewGlobal.bind(this);
|
||||
|
|
Загрузка…
Ссылка в новой задаче