Home | History | Annotate | Download | only in front-end
      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