082b23b027240f71a1896b375fbfce785c03f40a
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ObjectTreeArrayIndexTreeElement.js
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 // FIXME: This should share more code with ObjectTreePropertyTreeElement.
27
28 WebInspector.ObjectTreeArrayIndexTreeElement = function(property, propertyPath)
29 {
30     console.assert(property instanceof WebInspector.PropertyDescriptor);
31     console.assert(propertyPath instanceof WebInspector.PropertyPath);
32     console.assert(property.isIndexProperty(), "ArrayIndexTreeElement expects numeric property names");
33
34     this._property = property;
35     this._propertyPath = propertyPath;
36
37     var classNames = ["object-tree-property", "object-tree-array-index"];
38     if (!this._property.hasValue())
39         classNames.push("accessor");
40
41     WebInspector.GeneralTreeElement.call(this, classNames, this._titleFragment(), null, this._property, false);
42
43     this.small = true;
44     this.toggleOnClick = false;
45     this.selectable = false;
46     this.tooltipHandledSeparately = true;
47     this.hasChildren = false;
48 };
49
50 WebInspector.ObjectTreeArrayIndexTreeElement.prototype = {
51     constructor: WebInspector.ObjectTreeArrayIndexTreeElement,
52     __proto__: WebInspector.GeneralTreeElement.prototype,
53
54     // Public
55
56     get property()
57     {
58         return this._property;
59     },
60
61     // Private
62
63     _resolvedValue: function()
64     {
65         if (this._getterValue)
66             return this._getterValue;
67         if (this._property.hasValue())
68             return this._property.value;
69         return null;
70     },
71
72     _propertyPathType: function()
73     {
74         if (this._getterValue || this._property.hasValue())
75             return WebInspector.PropertyPath.Type.Value;
76         if (this._property.hasGetter())
77             return WebInspector.PropertyPath.Type.Getter;
78         if (this._property.hasSetter())
79             return WebInspector.PropertyPath.Type.Setter;
80         return WebInspector.PropertyPath.Type.Value;
81     },
82
83     _resolvedValuePropertyPath: function()
84     {
85         if (this._getterValue)
86             return this._propertyPath.appendPropertyDescriptor(this._getterValue, this._property, WebInspector.PropertyPath.Type.Value);
87         if (this._property.hasValue())
88             return this._propertyPath.appendPropertyDescriptor(this._property.value, this._property, WebInspector.PropertyPath.Type.Value);
89         return null;
90     },
91
92     _thisPropertyPath: function()
93     {
94         return this._propertyPath.appendPropertyDescriptor(null, this._property, this._propertyPathType());
95     },
96
97     _propertyPathString: function(propertyPath)
98     {
99         if (propertyPath.isFullPathImpossible())
100             return WebInspector.UIString("Unable to determine path to property from root");
101
102         return propertyPath.displayPath(this._propertyPathType());
103     },
104
105     _updateTitle: function()
106     {
107         this.mainTitle = this._titleFragment();
108
109         if (this._getterValue)
110             this.removeClassName("accessor");
111
112         this._updateHasChildren();
113     },
114
115     _titleFragment: function()
116     {
117         var container = document.createDocumentFragment();
118
119         // Array index name.
120         var nameElement = container.appendChild(document.createElement("span"));
121         nameElement.className = "index-name";
122         nameElement.textContent = this._property.name;
123         nameElement.title = this._propertyPathString(this._thisPropertyPath());
124
125         // Value.
126         var valueElement = container.appendChild(document.createElement("span"));
127         valueElement.className = "index-value";
128
129         var resolvedValue = this._resolvedValue();
130         if (resolvedValue)
131             valueElement.appendChild(WebInspector.FormattedValue.createObjectTreeOrFormattedValueForRemoteObject(resolvedValue, this._resolvedValuePropertyPath()));
132         else {
133             if (this._property.hasGetter())
134                 container.appendChild(this._createInteractiveGetterElement());
135             if (!this._property.hasSetter())
136                 container.appendChild(this._createReadOnlyIconElement());
137             // FIXME: What if just a setter?
138         }
139
140         valueElement.classList.add("value");
141         if (this._property.wasThrown || this._getterHadError)
142             valueElement.classList.add("error");
143
144         return container;
145     },
146
147     _createInteractiveGetterElement: function()
148     {
149         var getterElement = document.createElement("img");
150         getterElement.className = "getter";
151         getterElement.title = WebInspector.UIString("Invoke getter");
152
153         getterElement.addEventListener("click", function(event) {
154             event.stopPropagation();
155             var lastNonPrototypeObject = this._propertyPath.lastNonPrototypeObject;
156             var getterObject = this._property.get;
157             lastNonPrototypeObject.invokeGetter(getterObject, function(error, result, wasThrown) {
158                 this._getterHadError = !!(error || wasThrown);
159                 this._getterValue = result;
160                 this._updateTitle();
161             }.bind(this));
162         }.bind(this));
163
164         return getterElement;
165     },
166
167     _createReadOnlyIconElement: function()
168     {
169         var readOnlyElement = document.createElement("img");
170         readOnlyElement.className = "read-only";
171         readOnlyElement.title = WebInspector.UIString("Read only");
172         return readOnlyElement;
173     },
174 };