1 /* 2 * Copyright (C) 2009 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 WebInspector.RemoteObject = function(objectId, type, description, hasChildren) 32 { 33 this._objectId = objectId; 34 this._type = type; 35 this._description = description; 36 this._hasChildren = hasChildren; 37 } 38 39 WebInspector.RemoteObject.fromPrimitiveValue = function(value) 40 { 41 return new WebInspector.RemoteObject(null, typeof value, value); 42 } 43 44 WebInspector.RemoteObject.fromLocalObject = function(value) 45 { 46 return new WebInspector.LocalJSONObject(value); 47 } 48 49 WebInspector.RemoteObject.resolveNode = function(node, callback) 50 { 51 function mycallback(error, object) 52 { 53 if (!callback) 54 return; 55 56 if (error || !object) 57 callback(null); 58 else 59 callback(WebInspector.RemoteObject.fromPayload(object)); 60 } 61 DOMAgent.resolveNode(node.id, mycallback); 62 } 63 64 WebInspector.RemoteObject.fromPayload = function(payload) 65 { 66 if (typeof payload === "object") 67 return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.description, payload.hasChildren); 68 // FIXME: make sure we only get here with real payloads in the new DebuggerAgent.js. 69 return payload; 70 } 71 72 WebInspector.RemoteObject.type = function(remoteObject) 73 { 74 if (remoteObject === null) 75 return "null"; 76 77 var type = typeof remoteObject; 78 if (type !== "object" && type !== "function") 79 return type; 80 81 return remoteObject.type; 82 } 83 84 WebInspector.RemoteObject.prototype = { 85 get objectId() 86 { 87 return this._objectId; 88 }, 89 90 get type() 91 { 92 return this._type; 93 }, 94 95 get description() 96 { 97 return this._description; 98 }, 99 100 get hasChildren() 101 { 102 return this._hasChildren; 103 }, 104 105 isError: function() 106 { 107 return this._type === "error"; 108 }, 109 110 getOwnProperties: function(callback) 111 { 112 this._getProperties(false, callback); 113 }, 114 115 getAllProperties: function(callback) 116 { 117 this._getProperties(true, callback); 118 }, 119 120 _getProperties: function(ignoreHasOwnProperty, callback) 121 { 122 if (!this._objectId) { 123 callback([]); 124 return; 125 } 126 function remoteObjectBinder(error, properties) 127 { 128 if (error) { 129 callback(null); 130 return; 131 } 132 for (var i = 0; properties && i < properties.length; ++i) 133 properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value); 134 callback(properties); 135 } 136 RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, remoteObjectBinder); 137 }, 138 139 setPropertyValue: function(name, value, callback) 140 { 141 if (!this._objectId) { 142 callback("Can't get a property of non-object."); 143 return; 144 } 145 RuntimeAgent.setPropertyValue(this._objectId, name, value, callback); 146 }, 147 148 pushNodeToFrontend: function(callback) 149 { 150 if (this._objectId) 151 WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback); 152 else 153 callback(0); 154 }, 155 156 evaluate: function(expression, callback) 157 { 158 RuntimeAgent.evaluateOn(this._objectId, expression, callback); 159 }, 160 161 release: function() 162 { 163 RuntimeAgent.releaseObject(this._objectId); 164 } 165 } 166 167 WebInspector.RemoteObjectProperty = function(name, value) 168 { 169 this.name = name; 170 this.value = value; 171 } 172 173 // The below is a wrapper around a local object that provides an interface comaptible 174 // with RemoteObject, to be used by the UI code (primarily ObjectPropertiesSection). 175 // Note that only JSON-compliant objects are currently supported, as there's no provision 176 // for traversing prototypes, extracting class names via constuctor, handling properties 177 // or functions. 178 179 WebInspector.LocalJSONObject = function(value) 180 { 181 this._value = value; 182 } 183 184 WebInspector.LocalJSONObject.prototype = { 185 get description() 186 { 187 if (this._cachedDescription) 188 return this._cachedDescription; 189 190 var type = this.type; 191 192 switch (type) { 193 case "array": 194 function formatArrayItem(property) 195 { 196 return property.value.description; 197 } 198 this._cachedDescription = this._concatenate("[", "]", formatArrayItem); 199 break; 200 case "object": 201 function formatObjectItem(property) 202 { 203 return property.name + ":" + property.value.description; 204 } 205 this._cachedDescription = this._concatenate("{", "}", formatObjectItem); 206 break; 207 default: 208 this._cachedDescription = String(this._value); 209 } 210 return this._cachedDescription; 211 }, 212 213 _concatenate: function(prefix, suffix, formatProperty) 214 { 215 const previewChars = 100; 216 217 var buffer = prefix; 218 var children = this._children(); 219 for (var i = 0; i < children.length; ++i) { 220 var itemDescription = formatProperty(children[i]); 221 if (buffer.length + itemDescription.length > previewChars) { 222 buffer += ",\u2026"; 223 break; 224 } 225 if (i) 226 buffer += ", "; 227 buffer += itemDescription; 228 } 229 buffer += suffix; 230 return buffer; 231 }, 232 233 get type() 234 { 235 if (this._value === null) 236 return "null"; 237 if (this._value instanceof Array) 238 return "array"; 239 return typeof this._value; 240 }, 241 242 get hasChildren() 243 { 244 return typeof this._value === "object" && this._value !== null && Object.keys(this._value).length; 245 }, 246 247 getOwnProperties: function(callback) 248 { 249 callback(this._children()); 250 }, 251 252 getAllProperties: function(callback) 253 { 254 callback(this._children()); 255 }, 256 257 _children: function() 258 { 259 function buildProperty(propName) 260 { 261 return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName])); 262 } 263 if (!this._cachedChildren) 264 this._cachedChildren = Object.keys(this._value).map(buildProperty.bind(this)); 265 return this._cachedChildren; 266 }, 267 268 isError: function() 269 { 270 return false; 271 } 272 } 273