2 * Copyright (C) 2009 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 WebInspector.RemoteObject = function(objectId, type, subtype, value, description, preview)
34 this._subtype = subtype;
37 this._objectId = objectId;
38 this._description = description;
39 this._hasChildren = type !== "symbol";
40 this._preview = preview;
42 // Primitive or null object.
43 console.assert(type !== "object" || value === null);
44 this._description = description || (value + "");
45 this._hasChildren = false;
50 WebInspector.RemoteObject.fromPrimitiveValue = function(value)
52 return new WebInspector.RemoteObject(undefined, typeof value, undefined, value);
55 WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback)
57 function mycallback(error, object)
65 callback(WebInspector.RemoteObject.fromPayload(object));
67 DOMAgent.resolveNode(node.id, objectGroup, mycallback);
70 WebInspector.RemoteObject.fromPayload = function(payload)
72 console.assert(typeof payload === "object", "Remote object payload should only be an object");
74 return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description, payload.preview);
77 WebInspector.RemoteObject.type = function(remoteObject)
79 if (remoteObject === null)
82 var type = typeof remoteObject;
83 if (type !== "object" && type !== "function")
86 return remoteObject.type;
89 WebInspector.RemoteObject.prototype = {
92 return this._objectId;
102 return this._subtype;
107 return this._description;
112 return this._hasChildren;
117 return this._preview;
120 getOwnProperties: function(callback)
122 this._getProperties(true, false, callback);
125 getOwnAndGetterProperties: function(callback)
127 this._getProperties(false, true, callback);
130 getAllProperties: function(callback)
132 this._getProperties(false, false, callback);
135 _getProperties: function(ownProperties, ownAndGetterProperties, callback)
137 if (!this._objectId || this._isSymbol()) {
142 function remoteObjectBinder(error, properties, internalProperties)
149 // FIXME: We should display Internal Properties visually distinct. For now treat as non-enumerable own properties.
150 if (internalProperties) {
151 properties = properties.concat(internalProperties.map(function(descriptor) {
152 descriptor.writable = false;
153 descriptor.configurable = false;
154 descriptor.enumerable = false;
155 descriptor.isOwn = true;
161 for (var i = 0; properties && i < properties.length; ++i) {
162 var property = properties[i];
163 if (property.get || property.set) {
165 result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property));
167 result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property));
169 result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property));
174 // COMPATIBILITY (iOS 8): RuntimeAgent.getProperties did not support ownerAndGetterProperties.
175 // Here we do our best to reimplement it by getting all properties and reducing them down.
176 if (ownAndGetterProperties && !RuntimeAgent.getProperties.supports("ownAndGetterProperties")) {
177 RuntimeAgent.getProperties(this._objectId, function(error, allProperties) {
178 var ownOrGetterPropertiesList = [];
180 for (var property of allProperties) {
181 if (property.isOwn || property.get || property.name === "__proto__") {
182 // Own property or getter property in prototype chain.
183 ownOrGetterPropertiesList.push(property);
184 } else if (property.value && property.name !== property.name.toUpperCase()) {
185 var type = property.value.type;
186 if (type && type !== "function" && property.name !== "constructor") {
187 // Possible native binding getter property converted to a value. Also, no CONSTANT name style and not "constructor".
188 ownOrGetterPropertiesList.push(property);
193 remoteObjectBinder(error, ownOrGetterPropertiesList);
198 RuntimeAgent.getProperties(this._objectId, ownProperties, ownAndGetterProperties, remoteObjectBinder);
201 setPropertyValue: function(name, value, callback)
203 if (!this._objectId || this._isSymbol()) {
204 callback("Can't set a property of non-object.");
208 RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this));
210 function evaluatedCallback(error, result, wasThrown)
212 if (error || wasThrown) {
213 callback(error || result.description);
217 function setPropertyValue(propertyName, propertyValue)
219 this[propertyName] = propertyValue;
222 delete result.description; // Optimize on traffic.
223 RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], true, undefined, propertySetCallback.bind(this));
224 if (result._objectId)
225 RuntimeAgent.releaseObject(result._objectId);
228 function propertySetCallback(error, result, wasThrown)
230 if (error || wasThrown) {
231 callback(error || result.description);
238 _isSymbol: function()
240 return this.type === "symbol";
243 isCollectionType: function()
245 return this.subtype === "map" || this.subtype === "set" || this.subtype === "weakmap";
248 isWeakCollection: function()
250 return this.subtype === "weakmap";
253 getCollectionEntries: function(start, numberToFetch, callback)
255 start = typeof start === "number" ? start : 0;
256 numberToFetch = typeof numberToFetch === "number" ? numberToFetch : 100;
258 console.assert(start >= 0);
259 console.assert(numberToFetch >= 0);
260 console.assert(this.isCollectionType());
262 // WeakMaps are not ordered. We should never send a non-zero start.
263 console.assert((this.subtype === "weakmap" && start === 0) || this.subtype !== "weakmap");
265 var objectGroup = this.isWeakCollection() ? this._weakCollectionObjectGroup() : "";
267 RuntimeAgent.getCollectionEntries(this._objectId, objectGroup, start, numberToFetch, function(error, entries) {
272 releaseWeakCollectionEntries: function()
274 console.assert(this.isWeakCollection());
276 RuntimeAgent.releaseObjectGroup(this._weakCollectionObjectGroup());
279 pushNodeToFrontend: function(callback)
282 WebInspector.domTreeManager.pushNodeToFrontend(this._objectId, callback);
287 callFunction: function(functionDeclaration, args, callback)
289 function mycallback(error, result, wasThrown)
291 callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result));
294 RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, mycallback);
297 callFunctionJSON: function(functionDeclaration, args, callback)
299 function mycallback(error, result, wasThrown)
301 callback((error || wasThrown) ? null : result.value);
304 RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, mycallback);
309 RuntimeAgent.releaseObject(this._objectId);
312 arrayLength: function()
314 if (this.subtype !== "array")
317 var matches = this._description.match(/\[([0-9]+)\]/);
320 return parseInt(matches[1], 10);
325 _weakCollectionObjectGroup: function()
327 return JSON.stringify(this._objectId) + "-WeakMap";
331 WebInspector.RemoteObjectProperty = function(name, value, descriptor)
335 this.enumerable = descriptor ? !!descriptor.enumerable : true;
336 this.writable = descriptor ? !!descriptor.writable : true;
337 if (descriptor && descriptor.wasThrown)
338 this.wasThrown = true;
341 WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value)
343 return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value));