Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (180712 => 180713)
--- trunk/Source/WebInspectorUI/ChangeLog 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/ChangeLog 2015-02-27 01:15:15 UTC (rev 180713)
@@ -1,3 +1,152 @@
+2015-02-26 Joseph Pecoraro <pecor...@apple.com>
+
+ Web Inspector: New ObjectTree UI for Arrays / Maps / Sets
+ https://bugs.webkit.org/show_bug.cgi?id=142037
+
+ Reviewed by Timothy Hatcher.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Main.html:
+ Miscellaneous changes.
+
+ * UserInterface/Models/PropertyDescriptor.js:
+ (WebInspector.PropertyDescriptor.prototype.isIndexProperty):
+ Useful for quickly checking if this property is numeric and possibly
+ an array index.
+
+ * UserInterface/Models/PropertyPath.js:
+ (WebInspector.PropertyPath.prototype.appendMapKey):
+ (WebInspector.PropertyPath.prototype.appendMapValue):
+ (WebInspector.PropertyPath.prototype.appendSetIndex):
+ Be specific about property paths into maps / sets. Note that a map
+ value may be displayable if the key is simple.
+
+ * UserInterface/Protocol/RemoteObject.js:
+ (WebInspector.RemoteObject.prototype.hasValue):
+ A simple value RemoteObject may have the value "undefined". So provide
+ a falsey proof helper that actually checks if we have a value.
+
+ (WebInspector.RemoteObject.prototype.isArray):
+ (WebInspector.RemoteObject.prototype.backendGetOwnPropertyDescriptor):
+ (WebInspector.RemoteObject.prototype.wrappedCallback):
+ (WebInspector.RemoteObject.prototype.getOwnPropertyDescriptor):
+ Currently backend APIs exist only to get all properties. In the case
+ of collections, we often want to get only one property (__proto__).
+ This is a simple implementation on top of callFunctionOn.
+
+ * UserInterface/Views/ConsoleMessageImpl.js:
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsObject):
+ (WebInspector.ConsoleMessageImpl.prototype._formatParameterAsArray):
+ (WebInspector.ConsoleMessageImpl.prototype.appendUndefined): Deleted.
+ (WebInspector.ConsoleMessageImpl.prototype._printArray): Deleted.
+ (WebInspector.ConsoleMessageImpl.prototype._formatAsArrayEntry): Deleted.
+ Simplify array formatted to just use an ObjectTreeView. Add fixmes
+ that we should seed the ObjectTreeView with a starting property path.
+
+ * UserInterface/Views/FormattedValue.css:
+ (.formatted-node > ol):
+ Sometimes, a node's display was getting overridden by various console styles.
+ Force a node to always display block. We may be able to remove this later.
+
+ * UserInterface/Views/FormattedValue.js:
+ (WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject):
+ Helper for formatting a node / object / value more easily. This
+ is used by all collection types.
+
+ * UserInterface/Views/ObjectPreviewView.js:
+ (WebInspector.ObjectPreviewView.prototype._appendPropertyPreviews):
+ We lost the nice sparse array support when switching to the new preview path,
+ we should add it back.
+
+ * UserInterface/Views/ObjectTreeArrayIndexTreeElement.css:
+ (.object-tree-array-index):
+ (.object-tree-array-index > .titles):
+ (.object-tree-array-index > .icon):
+ (.object-tree-array-index .index-name):
+ (.object-tree-array-index .index-value .object-tree):
+ (.object-tree-array-index .index-value .object-tree .object-tree-outline):
+ (.object-tree-property + ol .object-tree-array-index):
+ New styles specific to array index tree elements.
+
+ * UserInterface/Views/ObjectTreeMapEntryTreeElement.css:
+ (.object-tree-array-index.object-tree-map-entry > .titles > .title > .index-name):
+ (.object-tree-map-entry.key):
+ (.object-tree-map-entry.key:first-of-type):
+ (.object-tree-map-entry):
+ New styles specific to map key/value tree elements.
+
+ * UserInterface/Views/ObjectTreeCollectionTreeElement.js: Removed.
+ Remove old collection implementation.
+
+ * UserInterface/Views/ObjectTreeArrayIndexTreeElement.js: Added.
+ (WebInspector.ObjectTreeArrayIndexTreeElement):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype.get property):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._resolvedValue):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._propertyPathType):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._resolvedValuePropertyPath):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._thisPropertyPath):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._propertyPathString):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._updateTitle):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._titleFragment):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._createInteractiveGetterElement.):
+ (WebInspector.ObjectTreeArrayIndexTreeElement.prototype._createReadOnlyIconElement):
+ Index followed by formatted value. Unfortunately a page can hack up an array
+ with getter properties, so also support getter values in an array. This ends
+ up copying a lot of ObjectTreePropertyTreeElement as a result.
+
+ * UserInterface/Views/ObjectTreeMapEntryTreeElement.js: Added.
+ (WebInspector.ObjectTreeMapEntryTreeElement):
+ (WebInspector.ObjectTreeMapEntryTreeElement.prototype.get object):
+ (WebInspector.ObjectTreeMapEntryTreeElement.prototype._propertyPathString):
+ (WebInspector.ObjectTreeMapEntryTreeElement.prototype._titleFragment):
+ (WebInspector.ObjectTreeMapKeyTreeElement):
+ (WebInspector.ObjectTreeMapKeyTreeElement.prototype.displayPropertyName):
+ (WebInspector.ObjectTreeMapKeyTreeElement.prototype.resolvedValuePropertyPath):
+ (WebInspector.ObjectTreeMapValueTreeElement):
+ (WebInspector.ObjectTreeMapValueTreeElement.prototype.displayPropertyName):
+ (WebInspector.ObjectTreeMapValueTreeElement.prototype.resolvedValuePropertyPath):
+ Key/value followed by formatted value.
+
+ * UserInterface/Views/ObjectTreeSetIndexTreeElement.js: Added.
+ (WebInspector.ObjectTreeSetIndexTreeElement):
+ (WebInspector.ObjectTreeSetIndexTreeElement.prototype.get object):
+ (WebInspector.ObjectTreeSetIndexTreeElement.prototype._resolvedValuePropertyPath):
+ (WebInspector.ObjectTreeSetIndexTreeElement.prototype._titleFragment):
+ Dot followed by formatted value.
+
+ * UserInterface/Views/ObjectTreePropertyTreeElement.css:
+ (.object-tree-property > .titles):
+ Reformat.
+
+ * UserInterface/Views/ObjectTreeView.css:
+ (.object-tree-property :matches(.formatted-string, .formatted-regexp)):
+ Upgrade generic styles.
+
+ * UserInterface/Views/ObjectTreePropertyTreeElement.js:
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._resolvedValue):
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._resolvedValuePropertyPath):
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._updateChildren):
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._updateChildrenInternal):
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._updateEntries):
+ (WebInspector.ObjectTreePropertyTreeElement.prototype._updateProperties):
+ * UserInterface/Views/ObjectTreeView.js:
+ (WebInspector.ObjectTreeView):
+ (WebInspector.ObjectTreeView.emptyMessageElement):
+ (WebInspector.ObjectTreeView.prototype.expand):
+ (WebInspector.ObjectTreeView.prototype.collapse):
+ (WebInspector.ObjectTreeView.prototype.update):
+ (WebInspector.ObjectTreeView.prototype._updateChildren):
+ (WebInspector.ObjectTreeView.prototype._updateEntries):
+ (WebInspector.ObjectTreeView.prototype._updateProperties):
+ (WebInspector.ObjectTreeView.prototype._handlePreviewOrTitleElementClick):
+ Both ObjectTreeView and ObjectTreePropertyTreeElement will fetch only collection
+ entries or properties depending on the type of the object being expanded.
+
+ (WebInspector.ObjectTreeView.prototype._trackWeakEntries):
+ (WebInspector.ObjectTreeView.prototype._untrackWeakEntries):
+ Allow WeakMap entries to be Garbage Collected when the ObjectTreeView
+ collapses or the console is cleared. FIXME for handling sub-tree WeakMaps.
+
2015-02-26 Brent Fulgham <bfulg...@apple.com>
[Win] Make build logs more legible by reducing noise
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -307,12 +307,14 @@
localizedStrings["No Box Model Information"] = "No Box Model Information";
localizedStrings["No Call Frames"] = "No Call Frames";
localizedStrings["No Child Layers"] = "No Child Layers";
+localizedStrings["No Entries."] = "No Entries.";
localizedStrings["No Event Listeners"] = "No Event Listeners";
localizedStrings["No Filter Results"] = "No Filter Results";
localizedStrings["No Layer Available"] = "No Layer Available";
localizedStrings["No Parameters"] = "No Parameters";
localizedStrings["No Properties"] = "No Properties";
localizedStrings["No Properties \u2014 Click to Edit"] = "No Properties \u2014 Click to Edit";
+localizedStrings["No Properties."] = "No Properties.";
localizedStrings["No Query Parameters"] = "No Query Parameters";
localizedStrings["No Request Headers"] = "No Request Headers";
localizedStrings["No Response Headers"] = "No Response Headers";
@@ -481,7 +483,8 @@
localizedStrings["XHR"] = "XHR";
localizedStrings["XHRs"] = "XHRs";
localizedStrings["Yes"] = "Yes";
+localizedStrings["key"] = "key";
localizedStrings["line "] = "line ";
localizedStrings["originally %s"] = "originally %s";
-localizedStrings["undefined \xD7 %d"] = "undefined \xD7 %d";
+localizedStrings["value"] = "value";
localizedStrings[" %s Profile Recorded"] = " %s Profile Recorded";
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2015-02-27 01:15:15 UTC (rev 180713)
@@ -99,6 +99,8 @@
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
@@ -420,8 +422,10 @@
<script src=""
<script src=""
<script src=""
- <script src=""
+ <script src=""
+ <script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/PropertyDescriptor.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Models/PropertyDescriptor.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/PropertyDescriptor.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -142,5 +142,10 @@
hasSetter: function()
{
return this._set && this._set.type === "function";
- }
+ },
+
+ isIndexProperty: function()
+ {
+ return !isNaN(Number(this._name));
+ },
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/PropertyPath.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Models/PropertyPath.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/PropertyPath.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -44,10 +44,11 @@
};
WebInspector.PropertyPath.SpecialPathComponent = {
- CollectionIndex: "@collection[?]",
InternalPropertyName: "@internal",
SymbolPropertyName: "@symbol",
- GetterPropertyName: "@getter",
+ MapKey: "@mapkey",
+ MapValue: "@mapvalue",
+ SetIndex: "@setindex",
};
WebInspector.PropertyPath.Type = {
@@ -200,12 +201,36 @@
return new WebInspector.PropertyPath(object, component, this);
},
- appendCollectionIndex: function(object)
+ appendMapKey: function(object)
{
- var component = WebInspector.PropertyPath.SpecialPathComponent.CollectionIndex;
+ var component = WebInspector.PropertyPath.SpecialPathComponent.MapKey;
return new WebInspector.PropertyPath(object, component, this);
},
+ appendMapValue: function(object, keyObject)
+ {
+ console.assert(!keyObject || keyObject instanceof WebInspector.RemoteObject);
+
+ if (keyObject && keyObject.hasValue()) {
+ if (keyObject.type === "string") {
+ var component = ".get(" + doubleQuotedString(keyObject.description) + ")";
+ return new WebInspector.PropertyPath(object, component, this);
+ }
+
+ var component = ".get(" + keyObject.description + ")";
+ return new WebInspector.PropertyPath(object, component, this);
+ }
+
+ var component = WebInspector.PropertyPath.SpecialPathComponent.MapValue;
+ return new WebInspector.PropertyPath(object, component, this);
+ },
+
+ appendSetIndex: function(object)
+ {
+ var component = WebInspector.PropertyPath.SpecialPathComponent.SetIndex;
+ return new WebInspector.PropertyPath(object, component, this);
+ },
+
appendPropertyDescriptor: function(object, descriptor, type)
{
if (descriptor.isInternalProperty)
Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -145,6 +145,11 @@
return this._preview;
},
+ hasValue: function()
+ {
+ return "_value" in this;
+ },
+
getOwnPropertyDescriptors: function(callback)
{
this._getPropertyDescriptors(true, callback);
@@ -350,6 +355,11 @@
return this._type === "symbol";
},
+ isArray: function()
+ {
+ return this._subtype === "array";
+ },
+
isCollectionType: function()
{
return this._subtype === "map" || this._subtype === "set" || this._subtype === "weakmap";
@@ -439,6 +449,32 @@
this.callFunction(backendInvokeGetter, [getterRemoteObject], true, callback);
},
+ getOwnPropertyDescriptor: function(propertyName, callback)
+ {
+ if (!RuntimeAgent.getOwnPropertyDescriptor) {
+ function backendGetOwnPropertyDescriptor(propertyName)
+ {
+ return this[propertyName];
+ }
+
+ function wrappedCallback(error, result, wasThrown)
+ {
+ if (error || wasThrown || !(result instanceof WebInspector.RemoteObject)) {
+ callback(null);
+ return;
+ }
+
+ var fakeDescriptor = {name: propertyName, value: result, writable: true, configurable: true, enumerable: false};
+ var fakePropertyDescriptor = new WebInspector.PropertyDescriptor(fakeDescriptor, true, false, false, false);
+ callback(fakePropertyDescriptor);
+ }
+
+ this.callFunction(backendGetOwnPropertyDescriptor, [propertyName], false, wrappedCallback);
+ }
+
+ // FIXME: Implement a real getOwnPropertyDescriptor?
+ },
+
release: function()
{
RuntimeAgent.releaseObject(this._objectId);
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageImpl.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -296,7 +296,8 @@
_formatParameterAsObject: function(obj, elem, forceExpansion)
{
- var objectTree = new WebInspector.ObjectTreeView(obj, WebInspector.ObjectTreeView.Mode.Properties, forceExpansion);
+ // FIXME: Intialize component with "$n" instead of "obj". Or, an existing property path.
+ var objectTree = new WebInspector.ObjectTreeView(obj, WebInspector.ObjectTreeView.Mode.Properties, null, forceExpansion);
elem.appendChild(objectTree.element);
},
@@ -314,8 +315,9 @@
_formatParameterAsArray: function(arr, elem)
{
- // FIXME: Array previews look poor. Keep doing what we currently do for arrays.
- arr.deprecatedGetOwnProperties(this._printArray.bind(this, arr, elem));
+ // FIXME: Intialize component with "$n" instead of "obj". Or, an existing property path.
+ var objectTree = new WebInspector.ObjectTreeView(arr, WebInspector.ObjectTreeView.Mode.Properties);
+ elem.appendChild(objectTree.element);
},
_userProvidedColumnNames: function(columnNamesArgument)
@@ -439,57 +441,6 @@
return element;
},
- _printArray: function(array, elem, properties)
- {
- if (!properties)
- return;
-
- var elements = [];
- for (var i = 0; i < properties.length; ++i) {
- var property = properties[i];
- var name = property.name;
- if (!isNaN(name))
- elements[name] = this._formatAsArrayEntry(property.value);
- }
-
- elem.appendChild(document.createTextNode("["));
- var lastNonEmptyIndex = -1;
-
- function appendUndefined(elem, index)
- {
- if (index - lastNonEmptyIndex <= 1)
- return;
- var span = elem.createChild("span", "formatted-undefined");
- span.textContent = WebInspector.UIString("undefined × %d").format(index - lastNonEmptyIndex - 1);
- }
-
- var length = array.arrayLength();
- for (var i = 0; i < length; ++i) {
- var element = elements[i];
- if (!element)
- continue;
-
- if (i - lastNonEmptyIndex > 1) {
- appendUndefined(elem, i);
- elem.appendChild(document.createTextNode(", "));
- }
-
- elem.appendChild(element);
- lastNonEmptyIndex = i;
- if (i < length - 1)
- elem.appendChild(document.createTextNode(", "));
- }
- appendUndefined(elem, length);
-
- elem.appendChild(document.createTextNode("]"));
- },
-
- _formatAsArrayEntry: function(output)
- {
- // Prevent infinite expansion of cross-referencing arrays.
- return this._formatParameter(output, output.subtype && output.subtype === "array");
- },
-
_formatWithSubstitutionString: function(parameters, formattedResult)
{
var formatters = {};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css 2015-02-27 01:15:15 UTC (rev 180713)
@@ -30,6 +30,10 @@
color: black;
}
+.formatted-node > ol {
+ display: block !important;
+}
+
.formatted-number {
color: rgb(28, 0, 207);
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -111,3 +111,16 @@
{
return WebInspector.FormattedValue.createElementForTypesAndValue(propertyPreview.type, propertyPreview.subtype, propertyPreview.value, true, false);
};
+
+WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject = function(object, propertyPath)
+{
+ if (object.subtype === "node")
+ return WebInspector.FormattedValue.createElementForNode(object);
+
+ if (object.type === "object") {
+ var objectTree = new WebInspector.ObjectTreeView(object, WebInspector.ObjectTreeView.Mode.Properties, propertyPath);
+ return objectTree.element;
+ }
+
+ return WebInspector.FormattedValue.createElementForRemoteObject(object);
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectPreviewView.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectPreviewView.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectPreviewView.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -171,6 +171,7 @@
if (preview.subtype === "date")
return !preview.propertyPreviews.length;
+ // FIXME: Array previews should have better sparse support: (undefined × 10).
var isArray = preview.subtype === "array";
element.appendChild(document.createTextNode(isArray ? "[" : "{"));
Copied: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.css (from rev 180712, trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css) (0 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.css 2015-02-27 01:15:15 UTC (rev 180713)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.object-tree-array-index {
+ position: relative;
+ left: -12px;
+ margin-top: 2px;
+ margin-bottom: 1px;
+}
+
+.object-tree-array-index > .disclosure-button,
+.object-tree-array-index > .icon {
+ display: none;
+}
+
+.object-tree-array-index .index-name {
+ font-family: -webkit-system-font, sans-serif;
+ font-size: 11px;
+ vertical-align: top;
+ color: hsla(0, 0%, 0%, 0.33);
+
+ position:relative;
+ top: -1px;
+
+ display: inline-block;
+ width: 22px;
+ text-align: center;
+}
+
+/* FIXME: Should this be all the time? */
+.object-tree-array-index .index-value .object-tree {
+ display: inline-block;
+}
+
+/* An array inside an array we should reduce the padding-start. */
+.object-tree-array-index .index-value .object-tree .object-tree-outline {
+ -webkit-padding-start: 6px;
+}
+
+/* An array inside an ObjectTreePropertyTreeElement needs more left shift */
+.object-tree-property + ol .object-tree-array-index {
+ left: -18px;
+}
Added: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.js (0 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeArrayIndexTreeElement.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// FIXME: This should share more code with ObjectTreePropertyTreeElement.
+
+WebInspector.ObjectTreeArrayIndexTreeElement = function(property, propertyPath)
+{
+ console.assert(property instanceof WebInspector.PropertyDescriptor);
+ console.assert(propertyPath instanceof WebInspector.PropertyPath);
+ console.assert(property.isIndexProperty(), "ArrayIndexTreeElement expects numeric property names");
+
+ this._property = property;
+ this._propertyPath = propertyPath;
+
+ var classNames = ["object-tree-property", "object-tree-array-index"];
+ if (!this._property.hasValue())
+ classNames.push("accessor");
+
+ WebInspector.GeneralTreeElement.call(this, classNames, this._titleFragment(), null, this._property, false);
+
+ this.small = true;
+ this.toggleOnClick = false;
+ this.selectable = false;
+ this.tooltipHandledSeparately = true;
+ this.hasChildren = false;
+};
+
+WebInspector.ObjectTreeArrayIndexTreeElement.prototype = {
+ constructor: WebInspector.ObjectTreeArrayIndexTreeElement,
+ __proto__: WebInspector.GeneralTreeElement.prototype,
+
+ // Public
+
+ get property()
+ {
+ return this._property;
+ },
+
+ // Private
+
+ _resolvedValue: function()
+ {
+ if (this._getterValue)
+ return this._getterValue;
+ if (this._property.hasValue())
+ return this._property.value;
+ return null;
+ },
+
+ _propertyPathType: function()
+ {
+ if (this._getterValue || this._property.hasValue())
+ return WebInspector.PropertyPath.Type.Value;
+ if (this._property.hasGetter())
+ return WebInspector.PropertyPath.Type.Getter;
+ if (this._property.hasSetter())
+ return WebInspector.PropertyPath.Type.Setter;
+ return WebInspector.PropertyPath.Type.Value;
+ },
+
+ _resolvedValuePropertyPath: function()
+ {
+ if (this._getterValue)
+ return this._propertyPath.appendPropertyDescriptor(this._getterValue, this._property, WebInspector.PropertyPath.Type.Value);
+ if (this._property.hasValue())
+ return this._propertyPath.appendPropertyDescriptor(this._property.value, this._property, WebInspector.PropertyPath.Type.Value);
+ return null;
+ },
+
+ _thisPropertyPath: function()
+ {
+ return this._propertyPath.appendPropertyDescriptor(null, this._property, this._propertyPathType());
+ },
+
+ _propertyPathString: function(propertyPath)
+ {
+ if (propertyPath.isFullPathImpossible())
+ return WebInspector.UIString("Unable to determine path to property from root");
+
+ return propertyPath.displayPath(this._propertyPathType());
+ },
+
+ _updateTitle: function()
+ {
+ this.mainTitle = this._titleFragment();
+
+ if (this._getterValue)
+ this.removeClassName("accessor");
+
+ this._updateHasChildren();
+ },
+
+ _titleFragment: function()
+ {
+ var container = document.createDocumentFragment();
+
+ // Array index name.
+ var nameElement = container.appendChild(document.createElement("span"));
+ nameElement.className = "index-name";
+ nameElement.textContent = this._property.name;
+ nameElement.title = this._propertyPathString(this._thisPropertyPath());
+
+ // Value.
+ var valueElement = container.appendChild(document.createElement("span"));
+ valueElement.className = "index-value";
+
+ var resolvedValue = this._resolvedValue();
+ if (resolvedValue)
+ valueElement.appendChild(WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject(resolvedValue, this._resolvedValuePropertyPath()));
+ else {
+ if (this._property.hasGetter())
+ container.appendChild(this._createInteractiveGetterElement());
+ if (!this._property.hasSetter())
+ container.appendChild(this._createReadOnlyIconElement());
+ // FIXME: What if just a setter?
+ }
+
+ valueElement.classList.add("value");
+ if (this._property.wasThrown || this._getterHadError)
+ valueElement.classList.add("error");
+
+ return container;
+ },
+
+ _createInteractiveGetterElement: function()
+ {
+ var getterElement = document.createElement("img");
+ getterElement.className = "getter";
+ getterElement.title = WebInspector.UIString("Invoke getter");
+
+ getterElement.addEventListener("click", function(event) {
+ event.stopPropagation();
+ var lastNonPrototypeObject = this._propertyPath.lastNonPrototypeObject;
+ var getterObject = this._property.get;
+ lastNonPrototypeObject.invokeGetter(getterObject, function(error, result, wasThrown) {
+ this._getterHadError = !!(error || wasThrown);
+ this._getterValue = result;
+ this._updateTitle();
+ }.bind(this));
+ }.bind(this));
+
+ return getterElement;
+ },
+
+ _createReadOnlyIconElement: function()
+ {
+ var readOnlyElement = document.createElement("img");
+ readOnlyElement.className = "read-only";
+ readOnlyElement.title = WebInspector.UIString("Read only");
+ return readOnlyElement;
+ },
+};
Deleted: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeCollectionTreeElement.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeCollectionTreeElement.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeCollectionTreeElement.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WebInspector.ObjectTreeCollectionTreeElement = function(remoteObject)
-{
- console.assert(remoteObject instanceof WebInspector.RemoteObject);
-
- this._remoteObject = remoteObject;
- this._requestingEntries = false;
- this._trackingEntries = false;
-
- TreeElement.call(this, "<entries>", null, false);
- this.toggleOnClick = true;
- this.selectable = false;
- this.hasChildren = true;
- this.expand();
-
- // FIXME: When a parent TreeElement is collapsed, we do not get a chance
- // to releaseWeakCollectionEntries. We should.
-};
-
-WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry = function(name, value)
-{
- var descriptor = {name: name, value: value, enumerable: true, writable: false};
- return new WebInspector.PropertyDescriptor(descriptor, true, false, false);
-}
-
-WebInspector.ObjectTreeCollectionTreeElement.prototype = {
- constructor: WebInspector.ObjectTreeCollectionTreeElement,
- __proto__: TreeElement.prototype,
-
- // Public
-
- get remoteObject()
- {
- return this._remoteObject;
- },
-
- // Protected
-
- onexpand: function()
- {
- if (this.children.length && !this.shouldRefreshChildren)
- return;
-
- if (this._requestingEntries)
- return;
-
- this._requestingEntries = true;
-
- function callback(entries) {
- this._requestingEntries = false;
-
- this.removeChildren();
-
- if (!entries || !entries.length) {
- this.appendChild(new WebInspector.ObjectTreeEmptyCollectionTreeElement);
- return;
- }
-
- this._trackWeakEntries();
-
- for (var i = 0; i < entries.length; ++i) {
- var entry = entries[i];
- if (entry.key)
- this.appendChild(new WebInspector.ObjectTreeCollectionEntryTreeElement(entry, i));
- else {
- var propertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("" + i, entry.value);
- this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor));
- }
- }
- }
-
- this._remoteObject.getCollectionEntries(0, 100, callback.bind(this));
- },
-
- oncollapse: function()
- {
- this._untrackWeakEntries();
- },
-
- ondetach: function()
- {
- this._untrackWeakEntries();
- },
-
- // Private.
-
- _trackWeakEntries: function()
- {
- if (!this._remoteObject.isWeakCollection())
- return;
-
- if (this._trackingEntries)
- return;
-
- this._trackingEntries = true;
-
- WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
- WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
- WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
- },
-
- _untrackWeakEntries: function()
- {
- if (!this._remoteObject.isWeakCollection())
- return;
-
- if (!this._trackingEntries)
- return;
-
- this._trackingEntries = false;
-
- this._remoteObject.releaseWeakCollectionEntries();
-
- WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
- WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
- WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
-
- this.removeChildren();
-
- if (this.expanded)
- this.collapse();
- },
-};
-
-WebInspector.ObjectTreeCollectionEntryTreeElement = function(entry, index)
-{
- console.assert(entry instanceof WebInspector.CollectionEntry);
- console.assert(entry.key instanceof WebInspector.RemoteObject);
- console.assert(entry.value instanceof WebInspector.RemoteObject);
-
- this._name = "" + index;
- this._key = entry.key;
- this._value = entry.value;
-
- TreeElement.call(this, "", null, false);
- this.toggleOnClick = true;
- this.selectable = false;
- this.hasChildren = true;
-}
-
-WebInspector.ObjectTreeCollectionEntryTreeElement.prototype = {
- constructor: WebInspector.ObjectTreeCollectionEntryTreeElement,
- __proto__: TreeElement.prototype,
-
- // Protected
-
- onpopulate: function()
- {
- if (this.children.length && !this.shouldRefreshChildren)
- return;
-
- var keyPropertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("key", this._key);
- this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(keyPropertyDescriptor));
-
- var valuePropertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("value", this._value);
- this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(valuePropertyDescriptor));
- },
-
- onattach: function()
- {
- var nameElement = document.createElement("span");
- nameElement.className = "name";
- nameElement.textContent = "" + this._name;
-
- var separatorElement = document.createElement("span");
- separatorElement.className = "separator";
- separatorElement.textContent = ": ";
-
- var valueElement = document.createElement("span");
- valueElement.className = "value";
- valueElement.textContent = "{" + this._key.description + " => " + this._value.description + "}";
-
- this.listItemElement.classList.add("object-tree-property");
-
- this.listItemElement.removeChildren();
- this.listItemElement.appendChild(nameElement);
- this.listItemElement.appendChild(separatorElement);
- this.listItemElement.appendChild(valueElement);
- }
-};
-
-WebInspector.ObjectTreeEmptyCollectionTreeElement = function()
-{
- TreeElement.call(this, WebInspector.UIString("Empty Collection"), null, false);
- this.selectable = false;
-}
-
-WebInspector.ObjectTreeEmptyCollectionTreeElement.prototype = {
- constructor: WebInspector.ObjectTreeEmptyCollectionTreeElement,
- __proto__: TreeElement.prototype
-};
Copied: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.css (from rev 180712, trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css) (0 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.css 2015-02-27 01:15:15 UTC (rev 180713)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.object-tree-array-index.object-tree-map-entry > .titles > .title > .index-name {
+ width: 37px;
+ text-align: right;
+ margin-right: 5px;
+}
+
+.object-tree-map-entry.key {
+ border-top: 1px solid hsl(0, 0%, 96%);
+}
+
+.object-tree-map-entry.key:first-of-type {
+ border-top: none;
+}
+
+.object-tree-map-entry {
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
Added: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.js (0 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeMapEntryTreeElement.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectTreeMapEntryTreeElement = function(object, propertyPath)
+{
+ console.assert(object instanceof WebInspector.RemoteObject);
+ console.assert(propertyPath instanceof WebInspector.PropertyPath);
+
+ this._object = object;
+ this._propertyPath = propertyPath;
+
+ // Treat the same as an array-index just with different strings and widths.
+ WebInspector.GeneralTreeElement.call(this, ["object-tree-array-index", "object-tree-map-entry"], this._titleFragment(), null, this._object, false);
+
+ this.small = true;
+ this.toggleOnClick = false;
+ this.selectable = false;
+ this.tooltipHandledSeparately = true;
+ this.hasChildren = false;
+};
+
+WebInspector.ObjectTreeMapEntryTreeElement.prototype = {
+ constructor: WebInspector.ObjectTreeMapEntryTreeElement,
+ __proto__: WebInspector.GeneralTreeElement.prototype,
+
+ // Public
+
+ get object()
+ {
+ return this._object;
+ },
+
+ // Private
+
+ _propertyPathString: function(propertyPath)
+ {
+ if (propertyPath.isFullPathImpossible())
+ return WebInspector.UIString("Unable to determine path to property from root");
+
+ return propertyPath.displayPath(WebInspector.PropertyPath.Type.Value);
+ },
+
+ _titleFragment: function()
+ {
+ var container = document.createDocumentFragment();
+
+ var propertyPath = this.resolvedValuePropertyPath();
+
+ // Index name.
+ var nameElement = container.appendChild(document.createElement("span"));
+ nameElement.className = "index-name";
+ nameElement.textContent = this.displayPropertyName();
+ nameElement.title = this._propertyPathString(propertyPath);
+
+ // Value.
+ var valueElement = container.appendChild(document.createElement("span"));
+ valueElement.className = "index-value";
+ valueElement.appendChild(WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject(this._object, propertyPath));
+
+ return container;
+ }
+};
+
+
+WebInspector.ObjectTreeMapKeyTreeElement = function(object, propertyPath)
+{
+ WebInspector.ObjectTreeMapEntryTreeElement.call(this, object, propertyPath);
+ this.addClassName("key");
+}
+
+WebInspector.ObjectTreeMapKeyTreeElement.prototype = {
+ constructor: WebInspector.ObjectTreeMapKeyTreeElement,
+ __proto__: WebInspector.ObjectTreeMapEntryTreeElement.prototype,
+
+ // Protected
+
+ displayPropertyName: function()
+ {
+ return WebInspector.UIString("key");
+ },
+
+ resolvedValuePropertyPath: function()
+ {
+ return this._propertyPath.appendMapKey(this._object);
+ }
+};
+
+
+WebInspector.ObjectTreeMapValueTreeElement = function(object, propertyPath, key)
+{
+ this._key = key;
+ WebInspector.ObjectTreeMapEntryTreeElement.call(this, object, propertyPath);
+ this.addClassName("value");
+}
+
+WebInspector.ObjectTreeMapValueTreeElement.prototype = {
+ constructor: WebInspector.ObjectTreeMapValueTreeElement,
+ __proto__: WebInspector.ObjectTreeMapEntryTreeElement.prototype,
+
+ // Protected
+
+ displayPropertyName: function()
+ {
+ return WebInspector.UIString("value");
+ },
+
+ resolvedValuePropertyPath: function()
+ {
+ return this._propertyPath.appendMapValue(this._object, this._key);
+ }
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.css (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.css 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.css 2015-02-27 01:15:15 UTC (rev 180713)
@@ -27,6 +27,16 @@
margin-top: 1px;
}
+.object-tree-property > .titles {
+ position: relative;
+ top: 2px;
+ line-height: normal;
+ padding-bottom: 1px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
.object-tree-property > .disclosure-button {
float: left;
@@ -160,20 +170,6 @@
margin-left: 3px;
}
-.object-tree-property :matches(.formatted-string, .formatted-regexp) {
- white-space: nowrap;
-}
-
.object-tree-property .value.error {
color: red;
}
-
-.object-tree-property > .titles {
- position: relative;
- top: 2px;
- line-height: normal;
- padding-bottom: 1px;
- text-overflow: ellipsis;
- overflow: hidden;
- white-space: nowrap;
-}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreePropertyTreeElement.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -94,10 +94,8 @@
{
if (this._getterValue)
return this._getterValue;
-
if (this._property.hasValue())
return this._property.value;
-
return null;
},
@@ -116,10 +114,8 @@
{
if (this._getterValue)
return this._propertyPath.appendPropertyDescriptor(this._getterValue, this._property, WebInspector.PropertyPath.Type.Value);
-
if (this._property.hasValue())
return this._propertyPath.appendPropertyDescriptor(this._property.value, this._property, WebInspector.PropertyPath.Type.Value);
-
return null;
},
@@ -391,48 +387,84 @@
return;
var resolvedValue = this._resolvedValue();
- var resolvedValuePropertyPath = this._resolvedValuePropertyPath();
+ if (resolvedValue.isCollectionType() && this._mode === WebInspector.ObjectTreeView.Mode.Properties)
+ resolvedValue.getCollectionEntries(0, 100, this._updateChildrenInternal.bind(this, this._updateEntries, this._mode));
+ else if (this._property.name === "__proto__")
+ resolvedValue.getOwnPropertyDescriptors(this._updateChildrenInternal.bind(this, this._updateProperties, WebInspector.ObjectTreeView.Mode.API));
+ else
+ resolvedValue.getDisplayablePropertyDescriptors(this._updateChildrenInternal.bind(this, this._updateProperties, this._mode));
+ },
- function callback(mode, properties)
- {
- this.removeChildren();
+ _updateChildrenInternal: function(handler, mode, list)
+ {
+ this.removeChildren();
- if (!properties) {
- var errorMessageElement = document.createElement("div");
- errorMessageElement.className = "empty-message";
- errorMessageElement.textContent = WebInspector.UIString("Could not fetch properties. Object may no longer exist.");;
- this.appendChild(new TreeElement(errorMessageElement, null, false));
- return;
- }
+ if (!list) {
+ var errorMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("Could not fetch properties. Object may no longer exist."));
+ this.appendChild(new TreeElement(errorMessageElement, null, false));
+ return;
+ }
- var prototypeName = undefined;
- if (this._property.name === "__proto__") {
- if (resolvedValue.description)
- prototypeName = this._sanitizedPrototypeString(resolvedValue);
- }
+ handler.call(this, list, this._resolvedValuePropertyPath(), mode);
+ },
- var isAPI = mode === WebInspector.ObjectTreeView.Mode.API;
+ _updateEntries: function(entries, propertyPath, mode)
+ {
+ for (var entry of entries) {
+ if (entry.key) {
+ this.appendChild(new WebInspector.ObjectTreeMapKeyTreeElement(entry.key, propertyPath));
+ this.appendChild(new WebInspector.ObjectTreeMapValueTreeElement(entry.value, propertyPath, entry.key));
+ } else
+ this.appendChild(new WebInspector.ObjectTreeSetIndexTreeElement(entry.value, propertyPath));
+ }
- properties.sort(WebInspector.ObjectTreeView.ComparePropertyDescriptors);
- for (var propertyDescriptor of properties) {
- // FIXME: If this is a pure API ObjectTree, we should show the native getters.
- // For now, just skip native binding getters in API mode, since we likely
- // already showed them in the Properties section.
- if (isAPI && propertyDescriptor.nativeGetter)
- continue;
- this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, resolvedValuePropertyPath, mode, prototypeName));
- }
+ if (!this.children.length) {
+ var emptyMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("No Entries."));
+ this.appendChild(new TreeElement(emptyMessageElement, null, false));
+ }
- // FIXME: Re-enable Collection Entries with new UI.
- // if (mode === WebInspector.ObjectTreeView.Mode.Properties) {
- // if (resolvedValue.isCollectionType())
- // this.appendChild(new WebInspector.ObjectTreeCollectionTreeElement(resolvedValue));
- // }
- };
+ // Show the prototype so users can see the API.
+ var resolvedValue = this._resolvedValue();
+ resolvedValue.getOwnPropertyDescriptor("__proto__", function(propertyDescriptor) {
+ if (propertyDescriptor)
+ this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, mode));
+ }.bind(this));
+ },
- if (this._property.name === "__proto__")
- resolvedValue.getOwnPropertyDescriptors(callback.bind(this, WebInspector.ObjectTreeView.Mode.API));
- else
- resolvedValue.getDisplayablePropertyDescriptors(callback.bind(this, this._mode));
- },
+ _updateProperties: function(properties, propertyPath, mode)
+ {
+ properties.sort(WebInspector.ObjectTreeView.ComparePropertyDescriptors);
+
+ var resolvedValue = this._resolvedValue();
+ var isArray = resolvedValue.isArray();
+ var isPropertyMode = mode === WebInspector.ObjectTreeView.Mode.Properties || this._getterValue;
+ var isAPI = mode === WebInspector.ObjectTreeView.Mode.API;
+
+ var prototypeName = undefined;
+ if (this._property.name === "__proto__") {
+ if (resolvedValue.description)
+ prototypeName = this._sanitizedPrototypeString(resolvedValue);
+ }
+
+ for (var propertyDescriptor of properties) {
+ // FIXME: If this is a pure API ObjectTree, we should show the native getters.
+ // For now, just skip native binding getters in API mode, since we likely
+ // already showed them in the Properties section.
+ if (isAPI && propertyDescriptor.nativeGetter)
+ continue;
+
+ if (isArray && isPropertyMode) {
+ if (propertyDescriptor.isIndexProperty())
+ this.appendChild(new WebInspector.ObjectTreeArrayIndexTreeElement(propertyDescriptor, propertyPath));
+ else if (propertyDescriptor.name === "__proto__")
+ this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, mode, prototypeName));
+ } else
+ this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, mode, prototypeName));
+ }
+
+ if (!this.children.length) {
+ var emptyMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("No Properties."));
+ this.appendChild(new TreeElement(emptyMessageElement, null, false));
+ }
+ }
};
Added: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeSetIndexTreeElement.js (0 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeSetIndexTreeElement.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeSetIndexTreeElement.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.ObjectTreeSetIndexTreeElement = function(object, propertyPath)
+{
+ console.assert(object instanceof WebInspector.RemoteObject);
+
+ this._object = object;
+ this._propertyPath = propertyPath;
+
+ // Treat the same as an array-index just with a different character.
+ WebInspector.GeneralTreeElement.call(this, ["object-tree-array-index"], this._titleFragment(), null, this._object, false);
+
+ this.small = true;
+ this.toggleOnClick = false;
+ this.selectable = false;
+ this.tooltipHandledSeparately = true;
+ this.hasChildren = false;
+};
+
+WebInspector.ObjectTreeSetIndexTreeElement.prototype = {
+ constructor: WebInspector.ObjectTreeSetIndexTreeElement,
+ __proto__: WebInspector.GeneralTreeElement.prototype,
+
+ // Public
+
+ get object()
+ {
+ return this._object;
+ },
+
+ // Private
+
+ _resolvedValuePropertyPath: function()
+ {
+ return this._propertyPath.appendSetIndex(this._object);
+ },
+
+ _titleFragment: function()
+ {
+ var container = document.createDocumentFragment();
+
+ // Set bullet.
+ var nameElement = container.appendChild(document.createElement("span"));
+ nameElement.className = "index-name";
+ nameElement.textContent = "\u2022";
+ nameElement.title = WebInspector.UIString("Unable to determine path to property from root");
+
+ // Value.
+ var valueElement = container.appendChild(document.createElement("span"));
+ valueElement.className = "index-value";
+ valueElement.appendChild(WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject(this._object, this._resolvedValuePropertyPath()));
+
+ return container;
+ }
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.css (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.css 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.css 2015-02-27 01:15:15 UTC (rev 180713)
@@ -105,3 +105,7 @@
font-family: sans-serif;
font-size: 12px;
}
+
+.object-tree-property :matches(.formatted-string, .formatted-regexp) {
+ white-space: nowrap;
+}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.js (180712 => 180713)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.js 2015-02-27 01:04:19 UTC (rev 180712)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ObjectTreeView.js 2015-02-27 01:15:15 UTC (rev 180713)
@@ -23,17 +23,24 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.ObjectTreeView = function(object, mode, forceExpanding)
+WebInspector.ObjectTreeView = function(object, mode, propertyPath, forceExpanding)
{
WebInspector.Object.call(this);
console.assert(object instanceof WebInspector.RemoteObject);
+ console.assert(!propertyPath || propertyPath instanceof WebInspector.PropertyPath);
this._object = object;
this._mode = mode || WebInspector.ObjectTreeView.Mode.Properties;
+ this._propertyPath = propertyPath || new WebInspector.PropertyPath(this._object, "obj");
this._expanded = false;
this._hasLosslessPreview = false;
+ // If ObjectTree is used outside of the console, we do not know when to release
+ // WeakMap entries. Currently collapse would work. For the console, we can just
+ // listen for console clear events. Currently all ObjectTrees are in the console.
+ this._inConsole = true;
+
this._element = document.createElement("div");
this._element.className = "object-tree";
@@ -62,6 +69,14 @@
// FIXME: Support editable ObjectTrees.
};
+WebInspector.ObjectTreeView.emptyMessageElement = function(message)
+{
+ var emptyMessageElement = document.createElement("div");
+ emptyMessageElement.className = "empty-message";
+ emptyMessageElement.textContent = message;
+ return emptyMessageElement;
+};
+
WebInspector.ObjectTreeView.Mode = {
Properties: Symbol("object-tree-properties"),
API: Symbol("object-tree-api"),
@@ -152,6 +167,8 @@
if (this._previewView)
this._previewView.showTitle();
+ this._trackWeakEntries();
+
this.update();
},
@@ -165,47 +182,76 @@
if (this._previewView)
this._previewView.showPreview();
+
+ this._untrackWeakEntries();
},
// Protected
update: function()
{
- this._object.getDisplayablePropertyDescriptors(this._updateProperties.bind(this));
+ if (this._object.isCollectionType() && this._mode === WebInspector.ObjectTreeView.Mode.Properties)
+ this._object.getCollectionEntries(0, 100, this._updateChildren.bind(this, this._updateEntries));
+ else
+ this._object.getDisplayablePropertyDescriptors(this._updateChildren.bind(this, this._updateProperties));
},
// Private
- _updateProperties: function(properties)
+ _updateChildren: function(handler, list)
{
this._outline.removeChildren();
- if (!properties) {
- var errorMessageElement = document.createElement("div");
- errorMessageElement.className = "empty-message";
- errorMessageElement.textContent = WebInspector.UIString("Could not fetch properties. Object may no longer exist.");;
+ if (!list) {
+ var errorMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("Could not fetch properties. Object may no longer exist."));
this._outline.appendChild(new TreeElement(errorMessageElement, null, false));
return;
}
+ handler.call(this, list, this._propertyPath);
+ },
+
+ _updateEntries: function(entries, propertyPath)
+ {
+ for (var entry of entries) {
+ if (entry.key) {
+ this._outline.appendChild(new WebInspector.ObjectTreeMapKeyTreeElement(entry.key, propertyPath));
+ this._outline.appendChild(new WebInspector.ObjectTreeMapValueTreeElement(entry.value, propertyPath, entry.key));
+ } else
+ this._outline.appendChild(new WebInspector.ObjectTreeSetIndexTreeElement(entry.value, propertyPath));
+ }
+
+ if (!this._outline.children.length) {
+ var emptyMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("No Entries."));
+ this._outline.appendChild(new TreeElement(emptyMessageElement, null, false));
+ }
+
+ // Show the prototype so users can see the API.
+ this._object.getOwnPropertyDescriptor("__proto__", function(propertyDescriptor) {
+ if (propertyDescriptor)
+ this._outline.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode));
+ }.bind(this));
+ },
+
+ _updateProperties: function(properties, propertyPath)
+ {
properties.sort(WebInspector.ObjectTreeView.ComparePropertyDescriptors);
- // FIXME: Intialize component with "$n" instead of "obj".
- var rootPropertyPath = new WebInspector.PropertyPath(this._object, "obj");
+ var isArray = this._object.isArray();
+ var isPropertyMode = this._mode === WebInspector.ObjectTreeView.Mode.Properties;
- for (var propertyDescriptor of properties)
- this._outline.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, rootPropertyPath, this._mode));
+ for (var propertyDescriptor of properties) {
+ if (isArray && isPropertyMode) {
+ if (propertyDescriptor.isIndexProperty())
+ this._outline.appendChild(new WebInspector.ObjectTreeArrayIndexTreeElement(propertyDescriptor, propertyPath));
+ else if (propertyDescriptor.name === "__proto__")
+ this._outline.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode));
+ } else
+ this._outline.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor, propertyPath, this._mode));
+ }
- // FIXME: Re-enable Collection Entries with new UI.
- // if (this._mode === WebInspector.ObjectTreeView.Mode.Properties) {
- // if (this._object.isCollectionType())
- // this._outline.appendChild(new WebInspector.ObjectTreeCollectionTreeElement(this._object));
- // }
-
if (!this._outline.children.length) {
- var emptyMessageElement = document.createElement("div");
- emptyMessageElement.className = "empty-message";
- emptyMessageElement.textContent = WebInspector.UIString("No Properties");;
+ var emptyMessageElement = WebInspector.ObjectTreeView.emptyMessageElement(WebInspector.UIString("No Properties."));
this._outline.appendChild(new TreeElement(emptyMessageElement, null, false));
}
},
@@ -221,5 +267,45 @@
this.collapse();
event.stopPropagation();
- }
+ },
+
+ _trackWeakEntries: function()
+ {
+ if (this._trackingEntries)
+ return;
+
+ if (!this._object.isWeakCollection())
+ return;
+
+ this._trackingEntries = true;
+
+ if (this._inConsole) {
+ WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
+ WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
+ WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
+ }
+ },
+
+ _untrackWeakEntries: function()
+ {
+ if (!this._trackingEntries)
+ return;
+
+ if (!this._object.isWeakCollection())
+ return;
+
+ this._trackingEntries = false;
+
+ this._object.releaseWeakCollectionEntries();
+
+ if (this._inConsole) {
+ WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
+ WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
+ WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
+ }
+
+ // FIXME: This only tries to release weak entries if this object was a WeakMap.
+ // If there was a WeakMap expanded in a sub-object, we will never release those values.
+ // Should we attempt walking the entire tree and release weak collections?
+ },
};