From 1287792e09363c544bc248aa6f7dcb432c29d873 Mon Sep 17 00:00:00 2001 From: Victor Porof Date: Wed, 30 May 2012 16:13:05 +0300 Subject: [PATCH] Bug 753677 - Visually distinguish between configurable, enumerable and writable properties; r=past --- .../devtools/debugger/debugger-controller.js | 4 +- browser/devtools/debugger/debugger-view.js | 46 ++++++++++++++----- .../themes/gnomestripe/devtools/debugger.css | 33 +++++++++++-- .../themes/pinstripe/devtools/debugger.css | 33 +++++++++++-- .../themes/winstripe/devtools/debugger.css | 33 +++++++++++-- 5 files changed, 124 insertions(+), 25 deletions(-) diff --git a/browser/devtools/debugger/debugger-controller.js b/browser/devtools/debugger/debugger-controller.js index 0b2647b1f337..864943da7752 100644 --- a/browser/devtools/debugger/debugger-controller.js +++ b/browser/devtools/debugger/debugger-controller.js @@ -584,7 +584,7 @@ StackFrames.prototype = { let variables = env.bindings.arguments; for each (let variable in variables) { let name = Object.getOwnPropertyNames(variable)[0]; - let paramVar = scope.addVar(name); + let paramVar = scope.addVar(name, variable[name]); let paramVal = variable[name].value; paramVar.setGrip(paramVal); this._addExpander(paramVar, paramVal); @@ -628,7 +628,7 @@ StackFrames.prototype = { // Add the sorted variables to the specified scope. for (let variable in variables) { - let paramVar = aScope.addVar(variable); + let paramVar = aScope.addVar(variable, variables[variable]); let paramVal = variables[variable].value; paramVar.setGrip(paramVal); this._addExpander(paramVar, paramVal); diff --git a/browser/devtools/debugger/debugger-view.js b/browser/devtools/debugger/debugger-view.js index 8e0570e0d97e..31b49ba5e409 100644 --- a/browser/devtools/debugger/debugger-view.js +++ b/browser/devtools/debugger/debugger-view.js @@ -880,12 +880,14 @@ PropertiesView.prototype = { * The parent scope element. * @param string aName * The variable name. + * @param object aFlags + * Optional, contains configurable, enumerable or writable flags. * @param string aId * Optional, an id for the variable html node. * @return object * The newly created html node representing the added var. */ - _addVar: function DVP__addVar(aScope, aName, aId) { + _addVar: function DVP__addVar(aScope, aName, aFlags, aId) { // Make sure the scope container exists. if (!aScope) { return null; @@ -927,6 +929,21 @@ PropertiesView.prototype = { // The variable information (type, class and/or value). valueLabel.className = "value plain"; + if (aFlags) { + // Use attribute flags to specify the element type and tooltip text. + let tooltip = []; + + !aFlags.configurable ? element.setAttribute("non-configurable", "") + : tooltip.push("configurable"); + !aFlags.enumerable ? element.setAttribute("non-enumerable", "") + : tooltip.push("enumerable"); + !aFlags.writable ? element.setAttribute("non-writable", "") + : tooltip.push("writable"); + + element.setAttribute("tooltiptext", tooltip.join(", ")); + } + if (aName === "this") { element.setAttribute("self", ""); } + // Handle the click event when pressing the element value label. valueLabel.addEventListener("click", this._activateElementInputMode.bind({ scope: this, @@ -1093,7 +1110,7 @@ PropertiesView.prototype = { * ["someProp4", { type: "null" }] * ["someProp5", { type: "object", class: "Object" }] * @param object aFlags - * Contans configurable, enumberable or writable flags. + * Contains configurable, enumerable or writable flags. * @param string aName * Optional, the property name. * @paarm string aId @@ -1139,15 +1156,7 @@ PropertiesView.prototype = { if ("undefined" !== typeof pKey) { // Use a key element to specify the property name. - let className = ""; - if (aFlags) { - if (aFlags.configurable === false) { className += "non-configurable "; } - if (aFlags.enumerable === false) { className += "non-enumerable "; } - if (aFlags.writable === false) { className += "non-writable "; } - } - if (pKey === "__proto__ ") { className += "proto "; } - - nameLabel.className = className + "key plain"; + nameLabel.className = "key plain"; nameLabel.setAttribute("value", pKey.trim()); title.appendChild(nameLabel); } @@ -1164,6 +1173,21 @@ PropertiesView.prototype = { title.appendChild(valueLabel); } + if (aFlags) { + // Use attribute flags to specify the element type and tooltip text. + let tooltip = []; + + !aFlags.configurable ? element.setAttribute("non-configurable", "") + : tooltip.push("configurable"); + !aFlags.enumerable ? element.setAttribute("non-enumerable", "") + : tooltip.push("enumerable"); + !aFlags.writable ? element.setAttribute("non-writable", "") + : tooltip.push("writable"); + + element.setAttribute("tooltiptext", tooltip.join(", ")); + } + if (pKey === "__proto__ ") { element.setAttribute("proto", ""); } + // Handle the click event when pressing the element value label. valueLabel.addEventListener("click", this._activateElementInputMode.bind({ scope: this, diff --git a/browser/themes/gnomestripe/devtools/debugger.css b/browser/themes/gnomestripe/devtools/debugger.css index 857910517c33..158cf3f6ad97 100644 --- a/browser/themes/gnomestripe/devtools/debugger.css +++ b/browser/themes/gnomestripe/devtools/debugger.css @@ -99,7 +99,7 @@ -moz-margin-start: 1px; -moz-margin-end: 1px; margin-top: 2px; - border-bottom: 1px dotted #ccc; + border-bottom: 1px dotted #ddd; border-radius: 8px; -moz-transition: background 1s ease-in-out; background: #fff; @@ -136,9 +136,34 @@ color: #881090; } -.property > .title > .non-enumerable.key, -.property > .title > .proto.key { - color: #c48bc8; +/** + * Non enumerable, configurable and writable variables and properties. + */ + +.property[proto] > .title > .key, +.variable[non-enumerable] > .title > .name, +.property[non-enumerable] > .title > .key { + opacity: 0.5; +} + +.variable[non-configurable] > .title > .name, +.property[non-configurable] > .title > .key { + border-bottom: 1px dashed #99f; +} + +.variable[non-writable] > .title > .name, +.property[non-writable] > .title > .key { + border-bottom: 1px dashed #f99; +} + +.variable[non-writable] > .title:after, +.property[non-writable] > .title:after { + content: " "; + display: inline-block; + width: 16px; + height: 16px; + background: url("chrome://browser/skin/identity-icons-https.png") no-repeat; + opacity: 0.5; } /** diff --git a/browser/themes/pinstripe/devtools/debugger.css b/browser/themes/pinstripe/devtools/debugger.css index 3746363512c9..0ecd1ed0ca2e 100644 --- a/browser/themes/pinstripe/devtools/debugger.css +++ b/browser/themes/pinstripe/devtools/debugger.css @@ -101,7 +101,7 @@ -moz-margin-start: 1px; -moz-margin-end: 1px; margin-top: 2px; - border-bottom: 1px dotted #ccc; + border-bottom: 1px dotted #ddd; border-radius: 8px; -moz-transition: background 1s ease-in-out; background: #fff; @@ -138,9 +138,34 @@ color: #881090; } -.property > .title > .non-enumerable.key, -.property > .title > .proto.key { - color: #c48bc8; +/** + * Non enumerable, configurable and writable variables and properties. + */ + +.property[proto] > .title > .key, +.variable[non-enumerable] > .title > .name, +.property[non-enumerable] > .title > .key { + opacity: 0.5; +} + +.variable[non-configurable] > .title > .name, +.property[non-configurable] > .title > .key { + border-bottom: 1px dashed #99f; +} + +.variable[non-writable] > .title > .name, +.property[non-writable] > .title > .key { + border-bottom: 1px dashed #f99; +} + +.variable[non-writable] > .title:after, +.property[non-writable] > .title:after { + content: " "; + display: inline-block; + width: 16px; + height: 16px; + background: url("chrome://browser/skin/identity-icons-https.png") no-repeat; + opacity: 0.5; } /** diff --git a/browser/themes/winstripe/devtools/debugger.css b/browser/themes/winstripe/devtools/debugger.css index 5dadacff56c7..f127274ddde2 100644 --- a/browser/themes/winstripe/devtools/debugger.css +++ b/browser/themes/winstripe/devtools/debugger.css @@ -99,7 +99,7 @@ -moz-margin-start: 1px; -moz-margin-end: 1px; margin-top: 2px; - border-bottom: 1px dotted #ccc; + border-bottom: 1px dotted #ddd; border-radius: 8px; -moz-transition: background 1s ease-in-out; background: #fff; @@ -136,9 +136,34 @@ color: #881090; } -.property > .title > .non-enumerable.key, -.property > .title > .proto.key { - color: #c48bc8; +/** + * Non enumerable, configurable and writable variables and properties. + */ + +.property[proto] > .title > .key, +.variable[non-enumerable] > .title > .name, +.property[non-enumerable] > .title > .key { + opacity: 0.5; +} + +.variable[non-configurable] > .title > .name, +.property[non-configurable] > .title > .key { + border-bottom: 1px dashed #99f; +} + +.variable[non-writable] > .title > .name, +.property[non-writable] > .title > .key { + border-bottom: 1px dashed #f99; +} + +.variable[non-writable] > .title:after, +.property[non-writable] > .title:after { + content: " "; + display: inline-block; + width: 16px; + height: 16px; + background: url("chrome://browser/skin/identity-icons-https.png") no-repeat; + opacity: 0.5; } /**