diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index e9aee41b74a..c81081a81a9 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1035,6 +1035,7 @@ pref("devtools.debugger.ui.stackframes-width", 200); pref("devtools.debugger.ui.stackframes-pane-visible", true); pref("devtools.debugger.ui.variables-width", 300); pref("devtools.debugger.ui.variables-pane-visible", true); +pref("devtools.debugger.ui.non-enum-visible", true); // Enable the style inspector pref("devtools.styleinspector.enabled", true); diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index 5dd57ec2ea8..ba0cd874c20 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -1733,6 +1733,7 @@ const REMOTE_HOST = "devtools.debugger.remote-host"; const REMOTE_PORT = "devtools.debugger.remote-port"; const REMOTE_CONNECTION_RETRIES = "devtools.debugger.remote-connection-retries"; const REMOTE_TIMEOUT = "devtools.debugger.remote-timeout"; +const NON_ENUM_VISIBLE = "devtools.debugger.ui.non-enum-visible"; /** * Shortcuts for accessing various debugger preferences. @@ -1820,7 +1821,7 @@ let Prefs = { }, /** - * Gets a flag specifying if the the debugger should automatically connect to + * Gets a flag specifying if the debugger should automatically connect to * the default host and port number. * @return boolean */ @@ -1832,13 +1833,35 @@ let Prefs = { }, /** - * Sets a flag specifying if the the debugger should automatically connect to + * Sets a flag specifying if the debugger should automatically connect to * the default host and port number. * @param boolean value */ set remoteAutoConnect(value) { Services.prefs.setBoolPref(REMOTE_AUTO_CONNECT, value); this._autoConnect = value; + }, + + /** + * Gets a flag specifying if the debugger should show non-enumerable + * properties and variables in the scope view. + * @return boolean + */ + get nonEnumVisible() { + if (this._nonEnumVisible === undefined) { + this._nonEnumVisible = Services.prefs.getBoolPref(NON_ENUM_VISIBLE); + } + return this._nonEnumVisible; + }, + + /** + * Sets a flag specifying if the debugger should show non-enumerable + * properties and variables in the scope view. + * @param boolean value + */ + set nonEnumVisible(value) { + Services.prefs.setBoolPref(NON_ENUM_VISIBLE, value); + this._nonEnumVisible = value; } }; diff --git a/browser/devtools/debugger/debugger-view.js b/browser/devtools/debugger/debugger-view.js index bbcd116d034..f9d4118c47e 100644 --- a/browser/devtools/debugger/debugger-view.js +++ b/browser/devtools/debugger/debugger-view.js @@ -2585,9 +2585,16 @@ PropertiesView.prototype = { // Compute the id of the element if not specified. aId = aId || (aScope.id + "->" + aName + "-variable"); + let parent; + if (aFlags && !aFlags.enumerable) { + parent = aScope.childNodes[2]; + } + else { + parent = aScope.childNodes[1]; + } + // Contains generic nodes and functionality. - let element = this._createPropertyElement(aName, aId, "variable", - aScope.getElementsByClassName("details")[0]); + let element = this._createPropertyElement(aName, aId, "variable", parent); // Make sure the element was created successfully. if (!element) { @@ -2789,6 +2796,7 @@ PropertiesView.prototype = { if (value !== undefined) { this._addProperty(aVar, [i, value], desc); } + if (getter !== undefined || setter !== undefined) { let prop = this._addProperty(aVar, [i]).expand(); prop.getter = this._addProperty(prop, ["get", getter], desc); @@ -2834,9 +2842,16 @@ PropertiesView.prototype = { // Compute the id of the element if not specified. aId = aId || (aVar.id + "->" + aProperty[0] + "-property"); + let parent; + if (aFlags && !aFlags.enumerable) { + parent = aVar.childNodes[2]; + } + else { + parent = aVar.childNodes[1]; + } + // Contains generic nodes and functionality. - let element = this._createPropertyElement(aName, aId, "property", - aVar.getElementsByClassName("details")[0]); + let element = this._createPropertyElement(aName, aId, "property", parent); // Make sure the element was created successfully. if (!element) { @@ -3112,6 +3127,7 @@ PropertiesView.prototype = { let title = document.createElement("box"); let details = document.createElement("vbox"); + let nonEnum = document.createElement("vbox"); // Create a scope node to contain all the elements. element.id = aId; @@ -3131,6 +3147,7 @@ PropertiesView.prototype = { // The node element which will contain any added scope variables. details.className = "details"; + nonEnum.className = "details nonenum"; // Add the click event handler for the title, or arrow and name. if (aClass === "scope") { @@ -3146,6 +3163,7 @@ PropertiesView.prototype = { element.appendChild(title); element.appendChild(details); + element.appendChild(nonEnum); aParent.appendChild(element); @@ -3192,12 +3210,19 @@ PropertiesView.prototype = { arrow.setAttribute("open", ""); details.setAttribute("open", ""); + if (Prefs.nonEnumVisible) { + nonEnum.setAttribute("open", ""); + } + if (!aSkipAnimationFlag) { details.setAttribute("animated", ""); + nonEnum.setAttribute("animated", ""); } + if ("function" === typeof element.onexpand) { element.onexpand(element); } + return element; }; @@ -3210,9 +3235,12 @@ PropertiesView.prototype = { if (element._preventCollapse) { return; } + arrow.removeAttribute("open"); details.removeAttribute("open"); details.removeAttribute("animated"); + nonEnum.removeAttribute("open"); + nonEnum.removeAttribute("animated"); if ("function" === typeof element.oncollapse) { element.oncollapse(element); @@ -3240,9 +3268,12 @@ PropertiesView.prototype = { * The same element. */ element.showArrow = function DVP_element_showArrow() { - if (element._forceShowArrow || details.childNodes.length) { + let len = details.childNodes.length + nonEnum.childNodes.length; + + if (element._forceShowArrow || len) { arrow.style.visibility = "visible"; } + return element; }; @@ -3327,13 +3358,19 @@ PropertiesView.prototype = { element.empty = function DVP_element_empty() { // This details node won't have any elements, so hide the arrow. arrow.style.visibility = "hidden"; + while (details.firstChild) { details.removeChild(details.firstChild); } + while (nonEnum.firstChild) { + nonEnum.removeChild(nonEnum.firstChild); + } + if ("function" === typeof element.onempty) { element.onempty(element); } + return element; }; @@ -3431,7 +3468,7 @@ PropertiesView.prototype = { let node = aParent.parentNode; let arrow = node.getElementsByClassName("arrow")[0]; - let children = node.getElementsByClassName("details")[0].childNodes.length; + let children = node.querySelectorAll(".details > vbox").length; // If the parent details node has at least one element, set the // expand/collapse arrow visible. @@ -3549,10 +3586,31 @@ PropertiesView.prototype = { */ _vars: null, + _onShowNonEnums: function DVP__onShowNonEnums() { + let option = document.getElementById("show-nonenum"); + Prefs.nonEnumVisible = option.checked; + + let els = document.getElementsByClassName("nonenum").iterator(); + for (let el of els) { + if (el.parentNode.expanded) { + if (Prefs.nonEnumVisible) { + el.setAttribute("open", ""); + } else { + el.removeAttribute("open"); + el.removeAttribute("animated"); + } + } + } + }, + /** * Initialization function, called when the debugger is initialized. */ initialize: function DVP_initialize() { + let showNonEnums = document.getElementById("show-nonenum"); + showNonEnums.addEventListener("click", this._onShowNonEnums, false); + showNonEnums.checked = Prefs.nonEnumVisible; + this._vars = DebuggerView._variables; this.emptyText(); diff --git a/browser/devtools/debugger/debugger.xul b/browser/devtools/debugger/debugger.xul index 87e32955354..cbea5982362 100644 --- a/browser/devtools/debugger/debugger.xul +++ b/browser/devtools/debugger/debugger.xul @@ -90,6 +90,10 @@ type="checkbox" tabindex="0" label="&debuggerUI.pauseExceptions;"/> + #ifndef XP_MACOSX