Modified: trunk/Source/WebCore/ChangeLog (124875 => 124876)
--- trunk/Source/WebCore/ChangeLog 2012-08-07 10:46:14 UTC (rev 124875)
+++ trunk/Source/WebCore/ChangeLog 2012-08-07 11:28:24 UTC (rev 124876)
@@ -1,3 +1,33 @@
+2012-08-07 Peter Rybin <[email protected]>
+
+ Web Inspector: display function scope in UI
+ https://bugs.webkit.org/show_bug.cgi?id=90631
+
+ Reviewed by Yury Semikhatsky.
+
+ Two new tree element types added: function scope group node and scope node.
+ Scope node is only used to represent closure and catch scopes. Scopes that
+ have a real object beneath are represented as a property node.
+ A method that reads properties from RemoteObject and populate tree element
+ is factored out from RemoteObjectTreeElement for reuse.
+
+ * inspector/front-end/ObjectPropertiesSection.js:
+ (WebInspector.ObjectPropertyTreeElement.prototype.onpopulate):
+ (WebInspector.ObjectPropertyTreeElement.Populate.callback):
+ (WebInspector.ObjectPropertyTreeElement.Populate):
+ (WebInspector.FunctionScopeMainTreeElement):
+ (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate.didGetDetails):
+ (WebInspector.FunctionScopeMainTreeElement.prototype.onpopulate):
+ (WebInspector.FunctionScopeMainTreeElement.prototype.onattach):
+ (WebInspector.FunctionScopeMainTreeElement.prototype.update):
+ (WebInspector.ScopeTreeElement):
+ (WebInspector.ScopeTreeElement.prototype.onpopulate):
+ (WebInspector.ScopeTreeElement.prototype.onattach):
+ (WebInspector.ScopeTreeElement.prototype.update):
+ * inspector/front-end/RemoteObject.js:
+ (WebInspector.RemoteObjectProperty.fromScopeValue):
+
+
2012-08-07 Vineet Chaudhary <[email protected]>
[V8] Remove custom toV8() calls for TypedArray.
Modified: trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js (124875 => 124876)
--- trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js 2012-08-07 10:46:14 UTC (rev 124875)
+++ trunk/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js 2012-08-07 11:28:24 UTC (rev 124876)
@@ -226,31 +226,7 @@
WebInspector.ObjectPropertyTreeElement.prototype = {
onpopulate: function()
{
- if (this.children.length && !this.shouldRefreshChildren)
- return;
-
- if (this.property.value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) {
- this.removeChildren();
- WebInspector.ArrayGroupingTreeElement._populateArray(this, this.property.value, 0, this.property.value.arrayLength() - 1);
- return;
- }
-
- function callback(properties)
- {
- this.removeChildren();
- if (!properties)
- return;
-
- properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
- for (var i = 0; i < properties.length; ++i) {
- if (this.treeOutline.section.skipProto && properties[i].name === "__proto__")
- continue;
- properties[i].parentObject = this.property.value;
- this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
- }
- }
-
- this.property.value.getOwnProperties(callback.bind(this));
+ return WebInspector.ObjectPropertyTreeElement.populate(this, this.property.value);
},
ondblclick: function(event)
@@ -305,7 +281,7 @@
this.valueElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false);
this.valueElement.title = description || "";
-
+
this.listItemElement.removeChildren();
this.listItemElement.appendChild(this.nameElement);
@@ -468,11 +444,146 @@
}
}
+/**
+ * @param {TreeElement} treeElement
+ * @param {WebInspector.RemoteObject} value
+ */
+WebInspector.ObjectPropertyTreeElement.populate = function(treeElement, value) {
+ if (treeElement.children.length && !treeElement.shouldRefreshChildren)
+ return;
+
+ if (value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) {
+ treeElement.removeChildren();
+ WebInspector.ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1);
+ return;
+ }
+
+ function callback(properties)
+ {
+ treeElement.removeChildren();
+ if (!properties)
+ return;
+
+ properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
+ for (var i = 0; i < properties.length; ++i) {
+ if (treeElement.treeOutline.section.skipProto && properties[i].name === "__proto__")
+ continue;
+ properties[i].parentObject = value;
+ treeElement.appendChild(new treeElement.treeOutline.section.treeElementConstructor(properties[i]));
+ }
+ if (value.type === "function")
+ treeElement.appendChild(new WebInspector.FunctionScopeMainTreeElement(value));
+ }
+
+ value.getOwnProperties(callback);
+}
+
WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;
/**
* @constructor
* @extends {TreeElement}
+ * @param {WebInspector.RemoteObject} remoteObject
+ */
+WebInspector.FunctionScopeMainTreeElement = function(remoteObject)
+{
+ TreeElement.call(this, "<function scope>", null, false);
+ this.toggleOnClick = true;
+ this.selectable = false;
+ this._remoteObject = remoteObject;
+ this.hasChildren = true;
+}
+
+WebInspector.FunctionScopeMainTreeElement.prototype = {
+ onpopulate: function()
+ {
+ if (this.children.length && !this.shouldRefreshChildren)
+ return;
+
+ function didGetDetails(error, response)
+ {
+ if (error) {
+ console.error(error);
+ return;
+ }
+ this.removeChildren();
+
+ var scopeChain = response.scopeChain;
+ for (var i = 0; i < scopeChain.length; ++i) {
+ var scope = scopeChain[i];
+ var title = null;
+ var isTrueObject;
+
+ switch (scope.type) {
+ case "local":
+ // Not really expecting this scope type here.
+ title = WebInspector.UIString("Local");
+ isTrueObject = false;
+ break;
+ case "closure":
+ title = WebInspector.UIString("Closure");
+ isTrueObject = false;
+ break;
+ case "catch":
+ title = WebInspector.UIString("Catch");
+ isTrueObject = false;
+ break;
+ case "with":
+ title = WebInspector.UIString("With Block");
+ isTrueObject = true;
+ break;
+ case "global":
+ title = WebInspector.UIString("Global");
+ isTrueObject = true;
+ break;
+ }
+
+ var remoteObject = WebInspector.RemoteObject.fromPayload(scope.object);
+ if (isTrueObject) {
+ var property = WebInspector.RemoteObjectProperty.fromScopeValue(title, remoteObject);
+ property.parentObject = null;
+ this.appendChild(new this.treeOutline.section.treeElementConstructor(property));
+ } else {
+ var scopeTreeElement = new WebInspector.ScopeTreeElement(title, null, remoteObject);
+ this.appendChild(scopeTreeElement);
+ }
+ }
+
+ }
+ DebuggerAgent.getFunctionDetails(this._remoteObject.objectId, didGetDetails.bind(this));
+
+ }
+};
+
+WebInspector.FunctionScopeMainTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {WebInspector.RemoteObject} remoteObject
+ */
+WebInspector.ScopeTreeElement = function(title, subtitle, remoteObject)
+{
+ // TODO: use subtitle parameter.
+ TreeElement.call(this, title, null, false);
+ this.toggleOnClick = true;
+ this.selectable = false;
+ this._remoteObject = remoteObject;
+ this.hasChildren = true;
+}
+
+WebInspector.ScopeTreeElement.prototype = {
+ onpopulate: function()
+ {
+ return WebInspector.ObjectPropertyTreeElement.populate(this, this._remoteObject);
+ }
+};
+
+WebInspector.ScopeTreeElement.prototype.__proto__ = TreeElement.prototype;
+
+/**
+ * @constructor
+ * @extends {TreeElement}
* @param {WebInspector.RemoteObject} object
* @param {number} fromIndex
* @param {number} toIndex
@@ -679,7 +790,7 @@
{
if (this._populated)
return;
-
+
this._populated = true;
if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) {
Modified: trunk/Source/WebCore/inspector/front-end/RemoteObject.js (124875 => 124876)
--- trunk/Source/WebCore/inspector/front-end/RemoteObject.js 2012-08-07 10:46:14 UTC (rev 124875)
+++ trunk/Source/WebCore/inspector/front-end/RemoteObject.js 2012-08-07 11:28:24 UTC (rev 124876)
@@ -336,7 +336,7 @@
/**
* @constructor
* @param {string} name
- * @param {WebInspector.RemoteObject} value
+ * @param {WebInspector.RemoteObject} value
* @param {Object=} descriptor
*/
WebInspector.RemoteObjectProperty = function(name, value, descriptor)
@@ -359,6 +359,18 @@
return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value));
}
+/**
+ * @param {string} name
+ * @param {WebInspector.RemoteObject} value
+ * @return {WebInspector.RemoteObjectProperty}
+ */
+WebInspector.RemoteObjectProperty.fromScopeValue = function(name, value)
+{
+ var result = new WebInspector.RemoteObjectProperty(name, value);
+ result.writable = false;
+ return result;
+}
+
// The below is a wrapper around a local object that provides an interface comaptible
// with RemoteObject, to be used by the UI code (primarily ObjectPropertiesSection).
// Note that only JSON-compliant objects are currently supported, as there's no provision