Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // Handle id counters.
     29 var next_handle_ = 0;
     30 var next_transient_handle_ = -1;
     31 
     32 // Mirror cache.
     33 var mirror_cache_ = [];
     34 
     35 
     36 /**
     37  * Clear the mirror handle cache.
     38  */
     39 function ClearMirrorCache() {
     40   next_handle_ = 0;
     41   mirror_cache_ = [];
     42 }
     43 
     44 
     45 /**
     46  * Returns the mirror for a specified value or object.
     47  *
     48  * @param {value or Object} value the value or object to retreive the mirror for
     49  * @param {boolean} transient indicate whether this object is transient and
     50  *    should not be added to the mirror cache. The default is not transient.
     51  * @returns {Mirror} the mirror reflects the passed value or object
     52  */
     53 function MakeMirror(value, opt_transient) {
     54   var mirror;
     55 
     56   // Look for non transient mirrors in the mirror cache.
     57   if (!opt_transient) {
     58     for (id in mirror_cache_) {
     59       mirror = mirror_cache_[id];
     60       if (mirror.value() === value) {
     61         return mirror;
     62       }
     63       // Special check for NaN as NaN == NaN is false.
     64       if (mirror.isNumber() && isNaN(mirror.value()) &&
     65           typeof value == 'number' && isNaN(value)) {
     66         return mirror;
     67       }
     68     }
     69   }
     70 
     71   if (IS_UNDEFINED(value)) {
     72     mirror = new UndefinedMirror();
     73   } else if (IS_NULL(value)) {
     74     mirror = new NullMirror();
     75   } else if (IS_BOOLEAN(value)) {
     76     mirror = new BooleanMirror(value);
     77   } else if (IS_NUMBER(value)) {
     78     mirror = new NumberMirror(value);
     79   } else if (IS_STRING(value)) {
     80     mirror = new StringMirror(value);
     81   } else if (IS_ARRAY(value)) {
     82     mirror = new ArrayMirror(value);
     83   } else if (IS_DATE(value)) {
     84     mirror = new DateMirror(value);
     85   } else if (IS_FUNCTION(value)) {
     86     mirror = new FunctionMirror(value);
     87   } else if (IS_REGEXP(value)) {
     88     mirror = new RegExpMirror(value);
     89   } else if (IS_ERROR(value)) {
     90     mirror = new ErrorMirror(value);
     91   } else if (IS_SCRIPT(value)) {
     92     mirror = new ScriptMirror(value);
     93   } else {
     94     mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
     95   }
     96 
     97   mirror_cache_[mirror.handle()] = mirror;
     98   return mirror;
     99 }
    100 
    101 
    102 /**
    103  * Returns the mirror for a specified mirror handle.
    104  *
    105  * @param {number} handle the handle to find the mirror for
    106  * @returns {Mirror or undefiend} the mirror with the requested handle or
    107  *     undefined if no mirror with the requested handle was found
    108  */
    109 function LookupMirror(handle) {
    110   return mirror_cache_[handle];
    111 }
    112 
    113 
    114 /**
    115  * Returns the mirror for the undefined value.
    116  *
    117  * @returns {Mirror} the mirror reflects the undefined value
    118  */
    119 function GetUndefinedMirror() {
    120   return MakeMirror(void 0);
    121 }
    122 
    123 
    124 /**
    125  * Inherit the prototype methods from one constructor into another.
    126  *
    127  * The Function.prototype.inherits from lang.js rewritten as a standalone
    128  * function (not on Function.prototype). NOTE: If this file is to be loaded
    129  * during bootstrapping this function needs to be revritten using some native
    130  * functions as prototype setup using normal JavaScript does not work as
    131  * expected during bootstrapping (see mirror.js in r114903).
    132  *
    133  * @param {function} ctor Constructor function which needs to inherit the
    134  *     prototype
    135  * @param {function} superCtor Constructor function to inherit prototype from
    136  */
    137 function inherits(ctor, superCtor) {
    138   var tempCtor = function(){};
    139   tempCtor.prototype = superCtor.prototype;
    140   ctor.super_ = superCtor.prototype;
    141   ctor.prototype = new tempCtor();
    142   ctor.prototype.constructor = ctor;
    143 }
    144 
    145 
    146 // Type names of the different mirrors.
    147 const UNDEFINED_TYPE = 'undefined';
    148 const NULL_TYPE = 'null';
    149 const BOOLEAN_TYPE = 'boolean';
    150 const NUMBER_TYPE = 'number';
    151 const STRING_TYPE = 'string';
    152 const OBJECT_TYPE = 'object';
    153 const FUNCTION_TYPE = 'function';
    154 const REGEXP_TYPE = 'regexp';
    155 const ERROR_TYPE = 'error';
    156 const PROPERTY_TYPE = 'property';
    157 const FRAME_TYPE = 'frame';
    158 const SCRIPT_TYPE = 'script';
    159 const CONTEXT_TYPE = 'context';
    160 const SCOPE_TYPE = 'scope';
    161 
    162 // Maximum length when sending strings through the JSON protocol.
    163 const kMaxProtocolStringLength = 80;
    164 
    165 // Different kind of properties.
    166 PropertyKind = {};
    167 PropertyKind.Named   = 1;
    168 PropertyKind.Indexed = 2;
    169 
    170 
    171 // A copy of the PropertyType enum from global.h
    172 PropertyType = {};
    173 PropertyType.Normal                  = 0;
    174 PropertyType.Field                   = 1;
    175 PropertyType.ConstantFunction        = 2;
    176 PropertyType.Callbacks               = 3;
    177 PropertyType.Interceptor             = 4;
    178 PropertyType.MapTransition           = 5;
    179 PropertyType.ExternalArrayTransition = 6;
    180 PropertyType.ConstantTransition      = 7;
    181 PropertyType.NullDescriptor          = 8;
    182 
    183 
    184 // Different attributes for a property.
    185 PropertyAttribute = {};
    186 PropertyAttribute.None       = NONE;
    187 PropertyAttribute.ReadOnly   = READ_ONLY;
    188 PropertyAttribute.DontEnum   = DONT_ENUM;
    189 PropertyAttribute.DontDelete = DONT_DELETE;
    190 
    191 
    192 // A copy of the scope types from runtime.cc.
    193 ScopeType = { Global: 0,
    194               Local: 1,
    195               With: 2,
    196               Closure: 3,
    197               Catch: 4 };
    198 
    199 
    200 // Mirror hierarchy:
    201 //   - Mirror
    202 //     - ValueMirror
    203 //       - UndefinedMirror
    204 //       - NullMirror
    205 //       - NumberMirror
    206 //       - StringMirror
    207 //       - ObjectMirror
    208 //         - FunctionMirror
    209 //           - UnresolvedFunctionMirror
    210 //         - ArrayMirror
    211 //         - DateMirror
    212 //         - RegExpMirror
    213 //         - ErrorMirror
    214 //     - PropertyMirror
    215 //     - FrameMirror
    216 //     - ScriptMirror
    217 
    218 
    219 /**
    220  * Base class for all mirror objects.
    221  * @param {string} type The type of the mirror
    222  * @constructor
    223  */
    224 function Mirror(type) {
    225   this.type_ = type;
    226 };
    227 
    228 
    229 Mirror.prototype.type = function() {
    230   return this.type_;
    231 };
    232 
    233 
    234 /**
    235  * Check whether the mirror reflects a value.
    236  * @returns {boolean} True if the mirror reflects a value.
    237  */
    238 Mirror.prototype.isValue = function() {
    239   return this instanceof ValueMirror;
    240 }
    241 
    242 
    243 /**
    244  * Check whether the mirror reflects the undefined value.
    245  * @returns {boolean} True if the mirror reflects the undefined value.
    246  */
    247 Mirror.prototype.isUndefined = function() {
    248   return this instanceof UndefinedMirror;
    249 }
    250 
    251 
    252 /**
    253  * Check whether the mirror reflects the null value.
    254  * @returns {boolean} True if the mirror reflects the null value
    255  */
    256 Mirror.prototype.isNull = function() {
    257   return this instanceof NullMirror;
    258 }
    259 
    260 
    261 /**
    262  * Check whether the mirror reflects a boolean value.
    263  * @returns {boolean} True if the mirror reflects a boolean value
    264  */
    265 Mirror.prototype.isBoolean = function() {
    266   return this instanceof BooleanMirror;
    267 }
    268 
    269 
    270 /**
    271  * Check whether the mirror reflects a number value.
    272  * @returns {boolean} True if the mirror reflects a number value
    273  */
    274 Mirror.prototype.isNumber = function() {
    275   return this instanceof NumberMirror;
    276 }
    277 
    278 
    279 /**
    280  * Check whether the mirror reflects a string value.
    281  * @returns {boolean} True if the mirror reflects a string value
    282  */
    283 Mirror.prototype.isString = function() {
    284   return this instanceof StringMirror;
    285 }
    286 
    287 
    288 /**
    289  * Check whether the mirror reflects an object.
    290  * @returns {boolean} True if the mirror reflects an object
    291  */
    292 Mirror.prototype.isObject = function() {
    293   return this instanceof ObjectMirror;
    294 }
    295 
    296 
    297 /**
    298  * Check whether the mirror reflects a function.
    299  * @returns {boolean} True if the mirror reflects a function
    300  */
    301 Mirror.prototype.isFunction = function() {
    302   return this instanceof FunctionMirror;
    303 }
    304 
    305 
    306 /**
    307  * Check whether the mirror reflects an unresolved function.
    308  * @returns {boolean} True if the mirror reflects an unresolved function
    309  */
    310 Mirror.prototype.isUnresolvedFunction = function() {
    311   return this instanceof UnresolvedFunctionMirror;
    312 }
    313 
    314 
    315 /**
    316  * Check whether the mirror reflects an array.
    317  * @returns {boolean} True if the mirror reflects an array
    318  */
    319 Mirror.prototype.isArray = function() {
    320   return this instanceof ArrayMirror;
    321 }
    322 
    323 
    324 /**
    325  * Check whether the mirror reflects a date.
    326  * @returns {boolean} True if the mirror reflects a date
    327  */
    328 Mirror.prototype.isDate = function() {
    329   return this instanceof DateMirror;
    330 }
    331 
    332 
    333 /**
    334  * Check whether the mirror reflects a regular expression.
    335  * @returns {boolean} True if the mirror reflects a regular expression
    336  */
    337 Mirror.prototype.isRegExp = function() {
    338   return this instanceof RegExpMirror;
    339 }
    340 
    341 
    342 /**
    343  * Check whether the mirror reflects an error.
    344  * @returns {boolean} True if the mirror reflects an error
    345  */
    346 Mirror.prototype.isError = function() {
    347   return this instanceof ErrorMirror;
    348 }
    349 
    350 
    351 /**
    352  * Check whether the mirror reflects a property.
    353  * @returns {boolean} True if the mirror reflects a property
    354  */
    355 Mirror.prototype.isProperty = function() {
    356   return this instanceof PropertyMirror;
    357 }
    358 
    359 
    360 /**
    361  * Check whether the mirror reflects a stack frame.
    362  * @returns {boolean} True if the mirror reflects a stack frame
    363  */
    364 Mirror.prototype.isFrame = function() {
    365   return this instanceof FrameMirror;
    366 }
    367 
    368 
    369 /**
    370  * Check whether the mirror reflects a script.
    371  * @returns {boolean} True if the mirror reflects a script
    372  */
    373 Mirror.prototype.isScript = function() {
    374   return this instanceof ScriptMirror;
    375 }
    376 
    377 
    378 /**
    379  * Check whether the mirror reflects a context.
    380  * @returns {boolean} True if the mirror reflects a context
    381  */
    382 Mirror.prototype.isContext = function() {
    383   return this instanceof ContextMirror;
    384 }
    385 
    386 
    387 /**
    388  * Check whether the mirror reflects a scope.
    389  * @returns {boolean} True if the mirror reflects a scope
    390  */
    391 Mirror.prototype.isScope = function() {
    392   return this instanceof ScopeMirror;
    393 }
    394 
    395 
    396 /**
    397  * Allocate a handle id for this object.
    398  */
    399 Mirror.prototype.allocateHandle_ = function() {
    400   this.handle_ = next_handle_++;
    401 }
    402 
    403 
    404 /**
    405  * Allocate a transient handle id for this object. Transient handles are
    406  * negative.
    407  */
    408 Mirror.prototype.allocateTransientHandle_ = function() {
    409   this.handle_ = next_transient_handle_--;
    410 }
    411 
    412 
    413 Mirror.prototype.toText = function() {
    414   // Simpel to text which is used when on specialization in subclass.
    415   return "#<" + this.constructor.name + ">";
    416 }
    417 
    418 
    419 /**
    420  * Base class for all value mirror objects.
    421  * @param {string} type The type of the mirror
    422  * @param {value} value The value reflected by this mirror
    423  * @param {boolean} transient indicate whether this object is transient with a
    424  *    transient handle
    425  * @constructor
    426  * @extends Mirror
    427  */
    428 function ValueMirror(type, value, transient) {
    429   %_CallFunction(this, type, Mirror);
    430   this.value_ = value;
    431   if (!transient) {
    432     this.allocateHandle_();
    433   } else {
    434     this.allocateTransientHandle_();
    435   }
    436 }
    437 inherits(ValueMirror, Mirror);
    438 
    439 
    440 Mirror.prototype.handle = function() {
    441   return this.handle_;
    442 };
    443 
    444 
    445 /**
    446  * Check whether this is a primitive value.
    447  * @return {boolean} True if the mirror reflects a primitive value
    448  */
    449 ValueMirror.prototype.isPrimitive = function() {
    450   var type = this.type();
    451   return type === 'undefined' ||
    452          type === 'null' ||
    453          type === 'boolean' ||
    454          type === 'number' ||
    455          type === 'string';
    456 };
    457 
    458 
    459 /**
    460  * Get the actual value reflected by this mirror.
    461  * @return {value} The value reflected by this mirror
    462  */
    463 ValueMirror.prototype.value = function() {
    464   return this.value_;
    465 };
    466 
    467 
    468 /**
    469  * Mirror object for Undefined.
    470  * @constructor
    471  * @extends ValueMirror
    472  */
    473 function UndefinedMirror() {
    474   %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror);
    475 }
    476 inherits(UndefinedMirror, ValueMirror);
    477 
    478 
    479 UndefinedMirror.prototype.toText = function() {
    480   return 'undefined';
    481 }
    482 
    483 
    484 /**
    485  * Mirror object for null.
    486  * @constructor
    487  * @extends ValueMirror
    488  */
    489 function NullMirror() {
    490   %_CallFunction(this, NULL_TYPE, null, ValueMirror);
    491 }
    492 inherits(NullMirror, ValueMirror);
    493 
    494 
    495 NullMirror.prototype.toText = function() {
    496   return 'null';
    497 }
    498 
    499 
    500 /**
    501  * Mirror object for boolean values.
    502  * @param {boolean} value The boolean value reflected by this mirror
    503  * @constructor
    504  * @extends ValueMirror
    505  */
    506 function BooleanMirror(value) {
    507   %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
    508 }
    509 inherits(BooleanMirror, ValueMirror);
    510 
    511 
    512 BooleanMirror.prototype.toText = function() {
    513   return this.value_ ? 'true' : 'false';
    514 }
    515 
    516 
    517 /**
    518  * Mirror object for number values.
    519  * @param {number} value The number value reflected by this mirror
    520  * @constructor
    521  * @extends ValueMirror
    522  */
    523 function NumberMirror(value) {
    524   %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
    525 }
    526 inherits(NumberMirror, ValueMirror);
    527 
    528 
    529 NumberMirror.prototype.toText = function() {
    530   return %NumberToString(this.value_);
    531 }
    532 
    533 
    534 /**
    535  * Mirror object for string values.
    536  * @param {string} value The string value reflected by this mirror
    537  * @constructor
    538  * @extends ValueMirror
    539  */
    540 function StringMirror(value) {
    541   %_CallFunction(this, STRING_TYPE, value, ValueMirror);
    542 }
    543 inherits(StringMirror, ValueMirror);
    544 
    545 
    546 StringMirror.prototype.length = function() {
    547   return this.value_.length;
    548 };
    549 
    550 StringMirror.prototype.getTruncatedValue = function(maxLength) {
    551   if (maxLength != -1 && this.length() > maxLength) {
    552     return this.value_.substring(0, maxLength) +
    553            '... (length: ' + this.length() + ')';
    554   }
    555   return this.value_;
    556 }
    557 
    558 StringMirror.prototype.toText = function() {
    559   return this.getTruncatedValue(kMaxProtocolStringLength);
    560 }
    561 
    562 
    563 /**
    564  * Mirror object for objects.
    565  * @param {object} value The object reflected by this mirror
    566  * @param {boolean} transient indicate whether this object is transient with a
    567  *    transient handle
    568  * @constructor
    569  * @extends ValueMirror
    570  */
    571 function ObjectMirror(value, type, transient) {
    572   %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
    573 }
    574 inherits(ObjectMirror, ValueMirror);
    575 
    576 
    577 ObjectMirror.prototype.className = function() {
    578   return %_ClassOf(this.value_);
    579 };
    580 
    581 
    582 ObjectMirror.prototype.constructorFunction = function() {
    583   return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
    584 };
    585 
    586 
    587 ObjectMirror.prototype.prototypeObject = function() {
    588   return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
    589 };
    590 
    591 
    592 ObjectMirror.prototype.protoObject = function() {
    593   return MakeMirror(%DebugGetPrototype(this.value_));
    594 };
    595 
    596 
    597 ObjectMirror.prototype.hasNamedInterceptor = function() {
    598   // Get information on interceptors for this object.
    599   var x = %GetInterceptorInfo(this.value_);
    600   return (x & 2) != 0;
    601 };
    602 
    603 
    604 ObjectMirror.prototype.hasIndexedInterceptor = function() {
    605   // Get information on interceptors for this object.
    606   var x = %GetInterceptorInfo(this.value_);
    607   return (x & 1) != 0;
    608 };
    609 
    610 
    611 /**
    612  * Return the property names for this object.
    613  * @param {number} kind Indicate whether named, indexed or both kinds of
    614  *     properties are requested
    615  * @param {number} limit Limit the number of names returend to the specified
    616        value
    617  * @return {Array} Property names for this object
    618  */
    619 ObjectMirror.prototype.propertyNames = function(kind, limit) {
    620   // Find kind and limit and allocate array for the result
    621   kind = kind || PropertyKind.Named | PropertyKind.Indexed;
    622 
    623   var propertyNames;
    624   var elementNames;
    625   var total = 0;
    626 
    627   // Find all the named properties.
    628   if (kind & PropertyKind.Named) {
    629     // Get the local property names.
    630     propertyNames = %GetLocalPropertyNames(this.value_);
    631     total += propertyNames.length;
    632 
    633     // Get names for named interceptor properties if any.
    634     if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
    635       var namedInterceptorNames =
    636           %GetNamedInterceptorPropertyNames(this.value_);
    637       if (namedInterceptorNames) {
    638         propertyNames = propertyNames.concat(namedInterceptorNames);
    639         total += namedInterceptorNames.length;
    640       }
    641     }
    642   }
    643 
    644   // Find all the indexed properties.
    645   if (kind & PropertyKind.Indexed) {
    646     // Get the local element names.
    647     elementNames = %GetLocalElementNames(this.value_);
    648     total += elementNames.length;
    649 
    650     // Get names for indexed interceptor properties.
    651     if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
    652       var indexedInterceptorNames =
    653           %GetIndexedInterceptorElementNames(this.value_);
    654       if (indexedInterceptorNames) {
    655         elementNames = elementNames.concat(indexedInterceptorNames);
    656         total += indexedInterceptorNames.length;
    657       }
    658     }
    659   }
    660   limit = Math.min(limit || total, total);
    661 
    662   var names = new Array(limit);
    663   var index = 0;
    664 
    665   // Copy names for named properties.
    666   if (kind & PropertyKind.Named) {
    667     for (var i = 0; index < limit && i < propertyNames.length; i++) {
    668       names[index++] = propertyNames[i];
    669     }
    670   }
    671 
    672   // Copy names for indexed properties.
    673   if (kind & PropertyKind.Indexed) {
    674     for (var i = 0; index < limit && i < elementNames.length; i++) {
    675       names[index++] = elementNames[i];
    676     }
    677   }
    678 
    679   return names;
    680 };
    681 
    682 
    683 /**
    684  * Return the properties for this object as an array of PropertyMirror objects.
    685  * @param {number} kind Indicate whether named, indexed or both kinds of
    686  *     properties are requested
    687  * @param {number} limit Limit the number of properties returend to the
    688        specified value
    689  * @return {Array} Property mirrors for this object
    690  */
    691 ObjectMirror.prototype.properties = function(kind, limit) {
    692   var names = this.propertyNames(kind, limit);
    693   var properties = new Array(names.length);
    694   for (var i = 0; i < names.length; i++) {
    695     properties[i] = this.property(names[i]);
    696   }
    697 
    698   return properties;
    699 };
    700 
    701 
    702 ObjectMirror.prototype.property = function(name) {
    703   var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
    704   if (details) {
    705     return new PropertyMirror(this, name, details);
    706   }
    707 
    708   // Nothing found.
    709   return GetUndefinedMirror();
    710 };
    711 
    712 
    713 
    714 /**
    715  * Try to find a property from its value.
    716  * @param {Mirror} value The property value to look for
    717  * @return {PropertyMirror} The property with the specified value. If no
    718  *     property was found with the specified value UndefinedMirror is returned
    719  */
    720 ObjectMirror.prototype.lookupProperty = function(value) {
    721   var properties = this.properties();
    722 
    723   // Look for property value in properties.
    724   for (var i = 0; i < properties.length; i++) {
    725 
    726     // Skip properties which are defined through assessors.
    727     var property = properties[i];
    728     if (property.propertyType() != PropertyType.Callbacks) {
    729       if (%_ObjectEquals(property.value_, value.value_)) {
    730         return property;
    731       }
    732     }
    733   }
    734 
    735   // Nothing found.
    736   return GetUndefinedMirror();
    737 };
    738 
    739 
    740 /**
    741  * Returns objects which has direct references to this object
    742  * @param {number} opt_max_objects Optional parameter specifying the maximum
    743  *     number of referencing objects to return.
    744  * @return {Array} The objects which has direct references to this object.
    745  */
    746 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
    747   // Find all objects with direct references to this object.
    748   var result = %DebugReferencedBy(this.value_,
    749                                   Mirror.prototype, opt_max_objects || 0);
    750 
    751   // Make mirrors for all the references found.
    752   for (var i = 0; i < result.length; i++) {
    753     result[i] = MakeMirror(result[i]);
    754   }
    755 
    756   return result;
    757 };
    758 
    759 
    760 ObjectMirror.prototype.toText = function() {
    761   var name;
    762   var ctor = this.constructorFunction();
    763   if (!ctor.isFunction()) {
    764     name = this.className();
    765   } else {
    766     name = ctor.name();
    767     if (!name) {
    768       name = this.className();
    769     }
    770   }
    771   return '#<' + name + '>';
    772 };
    773 
    774 
    775 /**
    776  * Mirror object for functions.
    777  * @param {function} value The function object reflected by this mirror.
    778  * @constructor
    779  * @extends ObjectMirror
    780  */
    781 function FunctionMirror(value) {
    782   %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
    783   this.resolved_ = true;
    784 }
    785 inherits(FunctionMirror, ObjectMirror);
    786 
    787 
    788 /**
    789  * Returns whether the function is resolved.
    790  * @return {boolean} True if the function is resolved. Unresolved functions can
    791  *     only originate as functions from stack frames
    792  */
    793 FunctionMirror.prototype.resolved = function() {
    794   return this.resolved_;
    795 };
    796 
    797 
    798 /**
    799  * Returns the name of the function.
    800  * @return {string} Name of the function
    801  */
    802 FunctionMirror.prototype.name = function() {
    803   return %FunctionGetName(this.value_);
    804 };
    805 
    806 
    807 /**
    808  * Returns the inferred name of the function.
    809  * @return {string} Name of the function
    810  */
    811 FunctionMirror.prototype.inferredName = function() {
    812   return %FunctionGetInferredName(this.value_);
    813 };
    814 
    815 
    816 /**
    817  * Returns the source code for the function.
    818  * @return {string or undefined} The source code for the function. If the
    819  *     function is not resolved undefined will be returned.
    820  */
    821 FunctionMirror.prototype.source = function() {
    822   // Return source if function is resolved. Otherwise just fall through to
    823   // return undefined.
    824   if (this.resolved()) {
    825     return builtins.FunctionSourceString(this.value_);
    826   }
    827 };
    828 
    829 
    830 /**
    831  * Returns the script object for the function.
    832  * @return {ScriptMirror or undefined} Script object for the function or
    833  *     undefined if the function has no script
    834  */
    835 FunctionMirror.prototype.script = function() {
    836   // Return script if function is resolved. Otherwise just fall through
    837   // to return undefined.
    838   if (this.resolved()) {
    839     var script = %FunctionGetScript(this.value_);
    840     if (script) {
    841       return MakeMirror(script);
    842     }
    843   }
    844 };
    845 
    846 
    847 /**
    848  * Returns the script source position for the function. Only makes sense
    849  * for functions which has a script defined.
    850  * @return {Number or undefined} in-script position for the function
    851  */
    852 FunctionMirror.prototype.sourcePosition_ = function() {
    853   // Return script if function is resolved. Otherwise just fall through
    854   // to return undefined.
    855   if (this.resolved()) {
    856     return %FunctionGetScriptSourcePosition(this.value_);
    857   }
    858 };
    859 
    860 
    861 /**
    862  * Returns the script source location object for the function. Only makes sense
    863  * for functions which has a script defined.
    864  * @return {Location or undefined} in-script location for the function begin
    865  */
    866 FunctionMirror.prototype.sourceLocation = function() {
    867   if (this.resolved() && this.script()) {
    868     return this.script().locationFromPosition(this.sourcePosition_(),
    869                                               true);
    870   }
    871 };
    872 
    873 
    874 /**
    875  * Returns objects constructed by this function.
    876  * @param {number} opt_max_instances Optional parameter specifying the maximum
    877  *     number of instances to return.
    878  * @return {Array or undefined} The objects constructed by this function.
    879  */
    880 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
    881   if (this.resolved()) {
    882     // Find all objects constructed from this function.
    883     var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
    884 
    885     // Make mirrors for all the instances found.
    886     for (var i = 0; i < result.length; i++) {
    887       result[i] = MakeMirror(result[i]);
    888     }
    889 
    890     return result;
    891   } else {
    892     return [];
    893   }
    894 };
    895 
    896 
    897 FunctionMirror.prototype.toText = function() {
    898   return this.source();
    899 }
    900 
    901 
    902 /**
    903  * Mirror object for unresolved functions.
    904  * @param {string} value The name for the unresolved function reflected by this
    905  *     mirror.
    906  * @constructor
    907  * @extends ObjectMirror
    908  */
    909 function UnresolvedFunctionMirror(value) {
    910   // Construct this using the ValueMirror as an unresolved function is not a
    911   // real object but just a string.
    912   %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
    913   this.propertyCount_ = 0;
    914   this.elementCount_ = 0;
    915   this.resolved_ = false;
    916 }
    917 inherits(UnresolvedFunctionMirror, FunctionMirror);
    918 
    919 
    920 UnresolvedFunctionMirror.prototype.className = function() {
    921   return 'Function';
    922 };
    923 
    924 
    925 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
    926   return GetUndefinedMirror();
    927 };
    928 
    929 
    930 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
    931   return GetUndefinedMirror();
    932 };
    933 
    934 
    935 UnresolvedFunctionMirror.prototype.protoObject = function() {
    936   return GetUndefinedMirror();
    937 };
    938 
    939 
    940 UnresolvedFunctionMirror.prototype.name = function() {
    941   return this.value_;
    942 };
    943 
    944 
    945 UnresolvedFunctionMirror.prototype.inferredName = function() {
    946   return undefined;
    947 };
    948 
    949 
    950 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
    951   return [];
    952 }
    953 
    954 
    955 /**
    956  * Mirror object for arrays.
    957  * @param {Array} value The Array object reflected by this mirror
    958  * @constructor
    959  * @extends ObjectMirror
    960  */
    961 function ArrayMirror(value) {
    962   %_CallFunction(this, value, ObjectMirror);
    963 }
    964 inherits(ArrayMirror, ObjectMirror);
    965 
    966 
    967 ArrayMirror.prototype.length = function() {
    968   return this.value_.length;
    969 };
    970 
    971 
    972 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_to_index) {
    973   var from_index = opt_from_index || 0;
    974   var to_index = opt_to_index || this.length() - 1;
    975   if (from_index > to_index) return new Array();
    976   var values = new Array(to_index - from_index + 1);
    977   for (var i = from_index; i <= to_index; i++) {
    978     var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
    979     var value;
    980     if (details) {
    981       value = new PropertyMirror(this, i, details);
    982     } else {
    983       value = GetUndefinedMirror();
    984     }
    985     values[i - from_index] = value;
    986   }
    987   return values;
    988 }
    989 
    990 
    991 /**
    992  * Mirror object for dates.
    993  * @param {Date} value The Date object reflected by this mirror
    994  * @constructor
    995  * @extends ObjectMirror
    996  */
    997 function DateMirror(value) {
    998   %_CallFunction(this, value, ObjectMirror);
    999 }
   1000 inherits(DateMirror, ObjectMirror);
   1001 
   1002 
   1003 DateMirror.prototype.toText = function() {
   1004   var s = JSON.stringify(this.value_);
   1005   return s.substring(1, s.length - 1);  // cut quotes
   1006 }
   1007 
   1008 
   1009 /**
   1010  * Mirror object for regular expressions.
   1011  * @param {RegExp} value The RegExp object reflected by this mirror
   1012  * @constructor
   1013  * @extends ObjectMirror
   1014  */
   1015 function RegExpMirror(value) {
   1016   %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
   1017 }
   1018 inherits(RegExpMirror, ObjectMirror);
   1019 
   1020 
   1021 /**
   1022  * Returns the source to the regular expression.
   1023  * @return {string or undefined} The source to the regular expression
   1024  */
   1025 RegExpMirror.prototype.source = function() {
   1026   return this.value_.source;
   1027 };
   1028 
   1029 
   1030 /**
   1031  * Returns whether this regular expression has the global (g) flag set.
   1032  * @return {boolean} Value of the global flag
   1033  */
   1034 RegExpMirror.prototype.global = function() {
   1035   return this.value_.global;
   1036 };
   1037 
   1038 
   1039 /**
   1040  * Returns whether this regular expression has the ignore case (i) flag set.
   1041  * @return {boolean} Value of the ignore case flag
   1042  */
   1043 RegExpMirror.prototype.ignoreCase = function() {
   1044   return this.value_.ignoreCase;
   1045 };
   1046 
   1047 
   1048 /**
   1049  * Returns whether this regular expression has the multiline (m) flag set.
   1050  * @return {boolean} Value of the multiline flag
   1051  */
   1052 RegExpMirror.prototype.multiline = function() {
   1053   return this.value_.multiline;
   1054 };
   1055 
   1056 
   1057 RegExpMirror.prototype.toText = function() {
   1058   // Simpel to text which is used when on specialization in subclass.
   1059   return "/" + this.source() + "/";
   1060 }
   1061 
   1062 
   1063 /**
   1064  * Mirror object for error objects.
   1065  * @param {Error} value The error object reflected by this mirror
   1066  * @constructor
   1067  * @extends ObjectMirror
   1068  */
   1069 function ErrorMirror(value) {
   1070   %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
   1071 }
   1072 inherits(ErrorMirror, ObjectMirror);
   1073 
   1074 
   1075 /**
   1076  * Returns the message for this eror object.
   1077  * @return {string or undefined} The message for this eror object
   1078  */
   1079 ErrorMirror.prototype.message = function() {
   1080   return this.value_.message;
   1081 };
   1082 
   1083 
   1084 ErrorMirror.prototype.toText = function() {
   1085   // Use the same text representation as in messages.js.
   1086   var text;
   1087   try {
   1088     str = %_CallFunction(this.value_, builtins.errorToString);
   1089   } catch (e) {
   1090     str = '#<Error>';
   1091   }
   1092   return str;
   1093 }
   1094 
   1095 
   1096 /**
   1097  * Base mirror object for properties.
   1098  * @param {ObjectMirror} mirror The mirror object having this property
   1099  * @param {string} name The name of the property
   1100  * @param {Array} details Details about the property
   1101  * @constructor
   1102  * @extends Mirror
   1103  */
   1104 function PropertyMirror(mirror, name, details) {
   1105   %_CallFunction(this, PROPERTY_TYPE, Mirror);
   1106   this.mirror_ = mirror;
   1107   this.name_ = name;
   1108   this.value_ = details[0];
   1109   this.details_ = details[1];
   1110   if (details.length > 2) {
   1111     this.exception_ = details[2]
   1112     this.getter_ = details[3];
   1113     this.setter_ = details[4];
   1114   }
   1115 }
   1116 inherits(PropertyMirror, Mirror);
   1117 
   1118 
   1119 PropertyMirror.prototype.isReadOnly = function() {
   1120   return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
   1121 }
   1122 
   1123 
   1124 PropertyMirror.prototype.isEnum = function() {
   1125   return (this.attributes() & PropertyAttribute.DontEnum) == 0;
   1126 }
   1127 
   1128 
   1129 PropertyMirror.prototype.canDelete = function() {
   1130   return (this.attributes() & PropertyAttribute.DontDelete) == 0;
   1131 }
   1132 
   1133 
   1134 PropertyMirror.prototype.name = function() {
   1135   return this.name_;
   1136 }
   1137 
   1138 
   1139 PropertyMirror.prototype.isIndexed = function() {
   1140   for (var i = 0; i < this.name_.length; i++) {
   1141     if (this.name_[i] < '0' || '9' < this.name_[i]) {
   1142       return false;
   1143     }
   1144   }
   1145   return true;
   1146 }
   1147 
   1148 
   1149 PropertyMirror.prototype.value = function() {
   1150   return MakeMirror(this.value_, false);
   1151 }
   1152 
   1153 
   1154 /**
   1155  * Returns whether this property value is an exception.
   1156  * @return {booolean} True if this property value is an exception
   1157  */
   1158 PropertyMirror.prototype.isException = function() {
   1159   return this.exception_ ? true : false;
   1160 }
   1161 
   1162 
   1163 PropertyMirror.prototype.attributes = function() {
   1164   return %DebugPropertyAttributesFromDetails(this.details_);
   1165 }
   1166 
   1167 
   1168 PropertyMirror.prototype.propertyType = function() {
   1169   return %DebugPropertyTypeFromDetails(this.details_);
   1170 }
   1171 
   1172 
   1173 PropertyMirror.prototype.insertionIndex = function() {
   1174   return %DebugPropertyIndexFromDetails(this.details_);
   1175 }
   1176 
   1177 
   1178 /**
   1179  * Returns whether this property has a getter defined through __defineGetter__.
   1180  * @return {booolean} True if this property has a getter
   1181  */
   1182 PropertyMirror.prototype.hasGetter = function() {
   1183   return this.getter_ ? true : false;
   1184 }
   1185 
   1186 
   1187 /**
   1188  * Returns whether this property has a setter defined through __defineSetter__.
   1189  * @return {booolean} True if this property has a setter
   1190  */
   1191 PropertyMirror.prototype.hasSetter = function() {
   1192   return this.setter_ ? true : false;
   1193 }
   1194 
   1195 
   1196 /**
   1197  * Returns the getter for this property defined through __defineGetter__.
   1198  * @return {Mirror} FunctionMirror reflecting the getter function or
   1199  *     UndefinedMirror if there is no getter for this property
   1200  */
   1201 PropertyMirror.prototype.getter = function() {
   1202   if (this.hasGetter()) {
   1203     return MakeMirror(this.getter_);
   1204   } else {
   1205     return GetUndefinedMirror();
   1206   }
   1207 }
   1208 
   1209 
   1210 /**
   1211  * Returns the setter for this property defined through __defineSetter__.
   1212  * @return {Mirror} FunctionMirror reflecting the setter function or
   1213  *     UndefinedMirror if there is no setter for this property
   1214  */
   1215 PropertyMirror.prototype.setter = function() {
   1216   if (this.hasSetter()) {
   1217     return MakeMirror(this.setter_);
   1218   } else {
   1219     return GetUndefinedMirror();
   1220   }
   1221 }
   1222 
   1223 
   1224 /**
   1225  * Returns whether this property is natively implemented by the host or a set
   1226  * through JavaScript code.
   1227  * @return {boolean} True if the property is
   1228  *     UndefinedMirror if there is no setter for this property
   1229  */
   1230 PropertyMirror.prototype.isNative = function() {
   1231   return (this.propertyType() == PropertyType.Interceptor) ||
   1232          ((this.propertyType() == PropertyType.Callbacks) &&
   1233           !this.hasGetter() && !this.hasSetter());
   1234 }
   1235 
   1236 
   1237 const kFrameDetailsFrameIdIndex = 0;
   1238 const kFrameDetailsReceiverIndex = 1;
   1239 const kFrameDetailsFunctionIndex = 2;
   1240 const kFrameDetailsArgumentCountIndex = 3;
   1241 const kFrameDetailsLocalCountIndex = 4;
   1242 const kFrameDetailsSourcePositionIndex = 5;
   1243 const kFrameDetailsConstructCallIndex = 6;
   1244 const kFrameDetailsAtReturnIndex = 7;
   1245 const kFrameDetailsDebuggerFrameIndex = 8;
   1246 const kFrameDetailsFirstDynamicIndex = 9;
   1247 
   1248 const kFrameDetailsNameIndex = 0;
   1249 const kFrameDetailsValueIndex = 1;
   1250 const kFrameDetailsNameValueSize = 2;
   1251 
   1252 /**
   1253  * Wrapper for the frame details information retreived from the VM. The frame
   1254  * details from the VM is an array with the following content. See runtime.cc
   1255  * Runtime_GetFrameDetails.
   1256  *     0: Id
   1257  *     1: Receiver
   1258  *     2: Function
   1259  *     3: Argument count
   1260  *     4: Local count
   1261  *     5: Source position
   1262  *     6: Construct call
   1263  *     7: Is at return
   1264  *     8: Debugger frame
   1265  *     Arguments name, value
   1266  *     Locals name, value
   1267  *     Return value if any
   1268  * @param {number} break_id Current break id
   1269  * @param {number} index Frame number
   1270  * @constructor
   1271  */
   1272 function FrameDetails(break_id, index) {
   1273   this.break_id_ = break_id;
   1274   this.details_ = %GetFrameDetails(break_id, index);
   1275 }
   1276 
   1277 
   1278 FrameDetails.prototype.frameId = function() {
   1279   %CheckExecutionState(this.break_id_);
   1280   return this.details_[kFrameDetailsFrameIdIndex];
   1281 }
   1282 
   1283 
   1284 FrameDetails.prototype.receiver = function() {
   1285   %CheckExecutionState(this.break_id_);
   1286   return this.details_[kFrameDetailsReceiverIndex];
   1287 }
   1288 
   1289 
   1290 FrameDetails.prototype.func = function() {
   1291   %CheckExecutionState(this.break_id_);
   1292   return this.details_[kFrameDetailsFunctionIndex];
   1293 }
   1294 
   1295 
   1296 FrameDetails.prototype.isConstructCall = function() {
   1297   %CheckExecutionState(this.break_id_);
   1298   return this.details_[kFrameDetailsConstructCallIndex];
   1299 }
   1300 
   1301 
   1302 FrameDetails.prototype.isAtReturn = function() {
   1303   %CheckExecutionState(this.break_id_);
   1304   return this.details_[kFrameDetailsAtReturnIndex];
   1305 }
   1306 
   1307 
   1308 FrameDetails.prototype.isDebuggerFrame = function() {
   1309   %CheckExecutionState(this.break_id_);
   1310   return this.details_[kFrameDetailsDebuggerFrameIndex];
   1311 }
   1312 
   1313 
   1314 FrameDetails.prototype.argumentCount = function() {
   1315   %CheckExecutionState(this.break_id_);
   1316   return this.details_[kFrameDetailsArgumentCountIndex];
   1317 }
   1318 
   1319 
   1320 FrameDetails.prototype.argumentName = function(index) {
   1321   %CheckExecutionState(this.break_id_);
   1322   if (index >= 0 && index < this.argumentCount()) {
   1323     return this.details_[kFrameDetailsFirstDynamicIndex +
   1324                          index * kFrameDetailsNameValueSize +
   1325                          kFrameDetailsNameIndex]
   1326   }
   1327 }
   1328 
   1329 
   1330 FrameDetails.prototype.argumentValue = function(index) {
   1331   %CheckExecutionState(this.break_id_);
   1332   if (index >= 0 && index < this.argumentCount()) {
   1333     return this.details_[kFrameDetailsFirstDynamicIndex +
   1334                          index * kFrameDetailsNameValueSize +
   1335                          kFrameDetailsValueIndex]
   1336   }
   1337 }
   1338 
   1339 
   1340 FrameDetails.prototype.localCount = function() {
   1341   %CheckExecutionState(this.break_id_);
   1342   return this.details_[kFrameDetailsLocalCountIndex];
   1343 }
   1344 
   1345 
   1346 FrameDetails.prototype.sourcePosition = function() {
   1347   %CheckExecutionState(this.break_id_);
   1348   return this.details_[kFrameDetailsSourcePositionIndex];
   1349 }
   1350 
   1351 
   1352 FrameDetails.prototype.localName = function(index) {
   1353   %CheckExecutionState(this.break_id_);
   1354   if (index >= 0 && index < this.localCount()) {
   1355     var locals_offset = kFrameDetailsFirstDynamicIndex +
   1356                         this.argumentCount() * kFrameDetailsNameValueSize
   1357     return this.details_[locals_offset +
   1358                          index * kFrameDetailsNameValueSize +
   1359                          kFrameDetailsNameIndex]
   1360   }
   1361 }
   1362 
   1363 
   1364 FrameDetails.prototype.localValue = function(index) {
   1365   %CheckExecutionState(this.break_id_);
   1366   if (index >= 0 && index < this.localCount()) {
   1367     var locals_offset = kFrameDetailsFirstDynamicIndex +
   1368                         this.argumentCount() * kFrameDetailsNameValueSize
   1369     return this.details_[locals_offset +
   1370                          index * kFrameDetailsNameValueSize +
   1371                          kFrameDetailsValueIndex]
   1372   }
   1373 }
   1374 
   1375 
   1376 FrameDetails.prototype.returnValue = function() {
   1377   %CheckExecutionState(this.break_id_);
   1378   var return_value_offset =
   1379       kFrameDetailsFirstDynamicIndex +
   1380       (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
   1381   if (this.details_[kFrameDetailsAtReturnIndex]) {
   1382     return this.details_[return_value_offset];
   1383   }
   1384 }
   1385 
   1386 
   1387 FrameDetails.prototype.scopeCount = function() {
   1388   return %GetScopeCount(this.break_id_, this.frameId());
   1389 }
   1390 
   1391 
   1392 /**
   1393  * Mirror object for stack frames.
   1394  * @param {number} break_id The break id in the VM for which this frame is
   1395        valid
   1396  * @param {number} index The frame index (top frame is index 0)
   1397  * @constructor
   1398  * @extends Mirror
   1399  */
   1400 function FrameMirror(break_id, index) {
   1401   %_CallFunction(this, FRAME_TYPE, Mirror);
   1402   this.break_id_ = break_id;
   1403   this.index_ = index;
   1404   this.details_ = new FrameDetails(break_id, index);
   1405 }
   1406 inherits(FrameMirror, Mirror);
   1407 
   1408 
   1409 FrameMirror.prototype.index = function() {
   1410   return this.index_;
   1411 };
   1412 
   1413 
   1414 FrameMirror.prototype.func = function() {
   1415   // Get the function for this frame from the VM.
   1416   var f = this.details_.func();
   1417 
   1418   // Create a function mirror. NOTE: MakeMirror cannot be used here as the
   1419   // value returned from the VM might be a string if the function for the
   1420   // frame is unresolved.
   1421   if (IS_FUNCTION(f)) {
   1422     return MakeMirror(f);
   1423   } else {
   1424     return new UnresolvedFunctionMirror(f);
   1425   }
   1426 };
   1427 
   1428 
   1429 FrameMirror.prototype.receiver = function() {
   1430   return MakeMirror(this.details_.receiver());
   1431 };
   1432 
   1433 
   1434 FrameMirror.prototype.isConstructCall = function() {
   1435   return this.details_.isConstructCall();
   1436 };
   1437 
   1438 
   1439 FrameMirror.prototype.isAtReturn = function() {
   1440   return this.details_.isAtReturn();
   1441 };
   1442 
   1443 
   1444 FrameMirror.prototype.isDebuggerFrame = function() {
   1445   return this.details_.isDebuggerFrame();
   1446 };
   1447 
   1448 
   1449 FrameMirror.prototype.argumentCount = function() {
   1450   return this.details_.argumentCount();
   1451 };
   1452 
   1453 
   1454 FrameMirror.prototype.argumentName = function(index) {
   1455   return this.details_.argumentName(index);
   1456 };
   1457 
   1458 
   1459 FrameMirror.prototype.argumentValue = function(index) {
   1460   return MakeMirror(this.details_.argumentValue(index));
   1461 };
   1462 
   1463 
   1464 FrameMirror.prototype.localCount = function() {
   1465   return this.details_.localCount();
   1466 };
   1467 
   1468 
   1469 FrameMirror.prototype.localName = function(index) {
   1470   return this.details_.localName(index);
   1471 };
   1472 
   1473 
   1474 FrameMirror.prototype.localValue = function(index) {
   1475   return MakeMirror(this.details_.localValue(index));
   1476 };
   1477 
   1478 
   1479 FrameMirror.prototype.returnValue = function() {
   1480   return MakeMirror(this.details_.returnValue());
   1481 };
   1482 
   1483 
   1484 FrameMirror.prototype.sourcePosition = function() {
   1485   return this.details_.sourcePosition();
   1486 };
   1487 
   1488 
   1489 FrameMirror.prototype.sourceLocation = function() {
   1490   if (this.func().resolved() && this.func().script()) {
   1491     return this.func().script().locationFromPosition(this.sourcePosition(),
   1492                                                      true);
   1493   }
   1494 };
   1495 
   1496 
   1497 FrameMirror.prototype.sourceLine = function() {
   1498   if (this.func().resolved()) {
   1499     var location = this.sourceLocation();
   1500     if (location) {
   1501       return location.line;
   1502     }
   1503   }
   1504 };
   1505 
   1506 
   1507 FrameMirror.prototype.sourceColumn = function() {
   1508   if (this.func().resolved()) {
   1509     var location = this.sourceLocation();
   1510     if (location) {
   1511       return location.column;
   1512     }
   1513   }
   1514 };
   1515 
   1516 
   1517 FrameMirror.prototype.sourceLineText = function() {
   1518   if (this.func().resolved()) {
   1519     var location = this.sourceLocation();
   1520     if (location) {
   1521       return location.sourceText();
   1522     }
   1523   }
   1524 };
   1525 
   1526 
   1527 FrameMirror.prototype.scopeCount = function() {
   1528   return this.details_.scopeCount();
   1529 };
   1530 
   1531 
   1532 FrameMirror.prototype.scope = function(index) {
   1533   return new ScopeMirror(this, index);
   1534 };
   1535 
   1536 
   1537 FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
   1538   var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
   1539                               source, Boolean(disable_break), opt_context_object);
   1540   return MakeMirror(result);
   1541 };
   1542 
   1543 
   1544 FrameMirror.prototype.invocationText = function() {
   1545   // Format frame invoaction (receiver, function and arguments).
   1546   var result = '';
   1547   var func = this.func();
   1548   var receiver = this.receiver();
   1549   if (this.isConstructCall()) {
   1550     // For constructor frames display new followed by the function name.
   1551     result += 'new ';
   1552     result += func.name() ? func.name() : '[anonymous]';
   1553   } else if (this.isDebuggerFrame()) {
   1554     result += '[debugger]';
   1555   } else {
   1556     // If the receiver has a className which is 'global' don't display it.
   1557     var display_receiver = !receiver.className || receiver.className() != 'global';
   1558     if (display_receiver) {
   1559       result += receiver.toText();
   1560     }
   1561     // Try to find the function as a property in the receiver. Include the
   1562     // prototype chain in the lookup.
   1563     var property = GetUndefinedMirror();
   1564     if (!receiver.isUndefined()) {
   1565       for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) {
   1566         property = r.lookupProperty(func);
   1567       }
   1568     }
   1569     if (!property.isUndefined()) {
   1570       // The function invoked was found on the receiver. Use the property name
   1571       // for the backtrace.
   1572       if (!property.isIndexed()) {
   1573         if (display_receiver) {
   1574           result += '.';
   1575         }
   1576         result += property.name();
   1577       } else {
   1578         result += '[';
   1579         result += property.name();
   1580         result += ']';
   1581       }
   1582       // Also known as - if the name in the function doesn't match the name
   1583       // under which it was looked up.
   1584       if (func.name() && func.name() != property.name()) {
   1585         result += '(aka ' + func.name() + ')';
   1586       }
   1587     } else {
   1588       // The function invoked was not found on the receiver. Use the function
   1589       // name if available for the backtrace.
   1590       if (display_receiver) {
   1591         result += '.';
   1592       }
   1593       result += func.name() ? func.name() : '[anonymous]';
   1594     }
   1595   }
   1596 
   1597   // Render arguments for normal frames.
   1598   if (!this.isDebuggerFrame()) {
   1599     result += '(';
   1600     for (var i = 0; i < this.argumentCount(); i++) {
   1601       if (i != 0) result += ', ';
   1602       if (this.argumentName(i)) {
   1603         result += this.argumentName(i);
   1604         result += '=';
   1605       }
   1606       result += this.argumentValue(i).toText();
   1607     }
   1608     result += ')';
   1609   }
   1610 
   1611   if (this.isAtReturn()) {
   1612     result += ' returning ';
   1613     result += this.returnValue().toText();
   1614   }
   1615 
   1616   return result;
   1617 }
   1618 
   1619 
   1620 FrameMirror.prototype.sourceAndPositionText = function() {
   1621   // Format source and position.
   1622   var result = '';
   1623   var func = this.func();
   1624   if (func.resolved()) {
   1625     if (func.script()) {
   1626       if (func.script().name()) {
   1627         result += func.script().name();
   1628       } else {
   1629         result += '[unnamed]';
   1630       }
   1631       if (!this.isDebuggerFrame()) {
   1632         var location = this.sourceLocation();
   1633         result += ' line ';
   1634         result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
   1635         result += ' column ';
   1636         result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
   1637         if (!IS_UNDEFINED(this.sourcePosition())) {
   1638           result += ' (position ' + (this.sourcePosition() + 1) + ')';
   1639         }
   1640       }
   1641     } else {
   1642       result += '[no source]';
   1643     }
   1644   } else {
   1645     result += '[unresolved]';
   1646   }
   1647 
   1648   return result;
   1649 }
   1650 
   1651 
   1652 FrameMirror.prototype.localsText = function() {
   1653   // Format local variables.
   1654   var result = '';
   1655   var locals_count = this.localCount()
   1656   if (locals_count > 0) {
   1657     for (var i = 0; i < locals_count; ++i) {
   1658       result += '      var ';
   1659       result += this.localName(i);
   1660       result += ' = ';
   1661       result += this.localValue(i).toText();
   1662       if (i < locals_count - 1) result += '\n';
   1663     }
   1664   }
   1665 
   1666   return result;
   1667 }
   1668 
   1669 
   1670 FrameMirror.prototype.toText = function(opt_locals) {
   1671   var result = '';
   1672   result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
   1673   result += ' ';
   1674   result += this.invocationText();
   1675   result += ' ';
   1676   result += this.sourceAndPositionText();
   1677   if (opt_locals) {
   1678     result += '\n';
   1679     result += this.localsText();
   1680   }
   1681   return result;
   1682 }
   1683 
   1684 
   1685 const kScopeDetailsTypeIndex = 0;
   1686 const kScopeDetailsObjectIndex = 1;
   1687 
   1688 function ScopeDetails(frame, index) {
   1689   this.break_id_ = frame.break_id_;
   1690   this.details_ = %GetScopeDetails(frame.break_id_,
   1691                                    frame.details_.frameId(),
   1692                                    index);
   1693 }
   1694 
   1695 
   1696 ScopeDetails.prototype.type = function() {
   1697   %CheckExecutionState(this.break_id_);
   1698   return this.details_[kScopeDetailsTypeIndex];
   1699 }
   1700 
   1701 
   1702 ScopeDetails.prototype.object = function() {
   1703   %CheckExecutionState(this.break_id_);
   1704   return this.details_[kScopeDetailsObjectIndex];
   1705 }
   1706 
   1707 
   1708 /**
   1709  * Mirror object for scope.
   1710  * @param {FrameMirror} frame The frame this scope is a part of
   1711  * @param {number} index The scope index in the frame
   1712  * @constructor
   1713  * @extends Mirror
   1714  */
   1715 function ScopeMirror(frame, index) {
   1716   %_CallFunction(this, SCOPE_TYPE, Mirror);
   1717   this.frame_index_ = frame.index_;
   1718   this.scope_index_ = index;
   1719   this.details_ = new ScopeDetails(frame, index);
   1720 }
   1721 inherits(ScopeMirror, Mirror);
   1722 
   1723 
   1724 ScopeMirror.prototype.frameIndex = function() {
   1725   return this.frame_index_;
   1726 };
   1727 
   1728 
   1729 ScopeMirror.prototype.scopeIndex = function() {
   1730   return this.scope_index_;
   1731 };
   1732 
   1733 
   1734 ScopeMirror.prototype.scopeType = function() {
   1735   return this.details_.type();
   1736 };
   1737 
   1738 
   1739 ScopeMirror.prototype.scopeObject = function() {
   1740   // For local and closure scopes create a transient mirror as these objects are
   1741   // created on the fly materializing the local or closure scopes and
   1742   // therefore will not preserve identity.
   1743   var transient = this.scopeType() == ScopeType.Local ||
   1744                   this.scopeType() == ScopeType.Closure;
   1745   return MakeMirror(this.details_.object(), transient);
   1746 };
   1747 
   1748 
   1749 /**
   1750  * Mirror object for script source.
   1751  * @param {Script} script The script object
   1752  * @constructor
   1753  * @extends Mirror
   1754  */
   1755 function ScriptMirror(script) {
   1756   %_CallFunction(this, SCRIPT_TYPE, Mirror);
   1757   this.script_ = script;
   1758   this.context_ = new ContextMirror(script.context_data);
   1759   this.allocateHandle_();
   1760 }
   1761 inherits(ScriptMirror, Mirror);
   1762 
   1763 
   1764 ScriptMirror.prototype.value = function() {
   1765   return this.script_;
   1766 };
   1767 
   1768 
   1769 ScriptMirror.prototype.name = function() {
   1770   return this.script_.name || this.script_.nameOrSourceURL();
   1771 };
   1772 
   1773 
   1774 ScriptMirror.prototype.id = function() {
   1775   return this.script_.id;
   1776 };
   1777 
   1778 
   1779 ScriptMirror.prototype.source = function() {
   1780   return this.script_.source;
   1781 };
   1782 
   1783 
   1784 ScriptMirror.prototype.lineOffset = function() {
   1785   return this.script_.line_offset;
   1786 };
   1787 
   1788 
   1789 ScriptMirror.prototype.columnOffset = function() {
   1790   return this.script_.column_offset;
   1791 };
   1792 
   1793 
   1794 ScriptMirror.prototype.data = function() {
   1795   return this.script_.data;
   1796 };
   1797 
   1798 
   1799 ScriptMirror.prototype.scriptType = function() {
   1800   return this.script_.type;
   1801 };
   1802 
   1803 
   1804 ScriptMirror.prototype.compilationType = function() {
   1805   return this.script_.compilation_type;
   1806 };
   1807 
   1808 
   1809 ScriptMirror.prototype.lineCount = function() {
   1810   return this.script_.lineCount();
   1811 };
   1812 
   1813 
   1814 ScriptMirror.prototype.locationFromPosition = function(
   1815     position, include_resource_offset) {
   1816   return this.script_.locationFromPosition(position, include_resource_offset);
   1817 }
   1818 
   1819 
   1820 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
   1821   return this.script_.sourceSlice(opt_from_line, opt_to_line);
   1822 }
   1823 
   1824 
   1825 ScriptMirror.prototype.context = function() {
   1826   return this.context_;
   1827 };
   1828 
   1829 
   1830 ScriptMirror.prototype.evalFromScript = function() {
   1831   return MakeMirror(this.script_.eval_from_script);
   1832 };
   1833 
   1834 
   1835 ScriptMirror.prototype.evalFromFunctionName = function() {
   1836   return MakeMirror(this.script_.eval_from_function_name);
   1837 };
   1838 
   1839 
   1840 ScriptMirror.prototype.evalFromLocation = function() {
   1841   var eval_from_script = this.evalFromScript();
   1842   if (!eval_from_script.isUndefined()) {
   1843     var position = this.script_.eval_from_script_position;
   1844     return eval_from_script.locationFromPosition(position, true);
   1845   }
   1846 };
   1847 
   1848 
   1849 ScriptMirror.prototype.toText = function() {
   1850   var result = '';
   1851   result += this.name();
   1852   result += ' (lines: ';
   1853   if (this.lineOffset() > 0) {
   1854     result += this.lineOffset();
   1855     result += '-';
   1856     result += this.lineOffset() + this.lineCount() - 1;
   1857   } else {
   1858     result += this.lineCount();
   1859   }
   1860   result += ')';
   1861   return result;
   1862 }
   1863 
   1864 
   1865 /**
   1866  * Mirror object for context.
   1867  * @param {Object} data The context data
   1868  * @constructor
   1869  * @extends Mirror
   1870  */
   1871 function ContextMirror(data) {
   1872   %_CallFunction(this, CONTEXT_TYPE, Mirror);
   1873   this.data_ = data;
   1874   this.allocateHandle_();
   1875 }
   1876 inherits(ContextMirror, Mirror);
   1877 
   1878 
   1879 ContextMirror.prototype.data = function() {
   1880   return this.data_;
   1881 };
   1882 
   1883 
   1884 /**
   1885  * Returns a mirror serializer
   1886  *
   1887  * @param {boolean} details Set to true to include details
   1888  * @param {Object} options Options comtrolling the serialization
   1889  *     The following options can be set:
   1890  *       includeSource: include ths full source of scripts
   1891  * @returns {MirrorSerializer} mirror serializer
   1892  */
   1893 function MakeMirrorSerializer(details, options) {
   1894   return new JSONProtocolSerializer(details, options);
   1895 }
   1896 
   1897 
   1898 /**
   1899  * Object for serializing a mirror objects and its direct references.
   1900  * @param {boolean} details Indicates whether to include details for the mirror
   1901  *     serialized
   1902  * @constructor
   1903  */
   1904 function JSONProtocolSerializer(details, options) {
   1905   this.details_ = details;
   1906   this.options_ = options;
   1907   this.mirrors_ = [ ];
   1908 }
   1909 
   1910 
   1911 /**
   1912  * Returns a serialization of an object reference. The referenced object are
   1913  * added to the serialization state.
   1914  *
   1915  * @param {Mirror} mirror The mirror to serialize
   1916  * @returns {String} JSON serialization
   1917  */
   1918 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
   1919   return this.serialize_(mirror, true, true);
   1920 }
   1921 
   1922 
   1923 /**
   1924  * Returns a serialization of an object value. The referenced objects are
   1925  * added to the serialization state.
   1926  *
   1927  * @param {Mirror} mirror The mirror to serialize
   1928  * @returns {String} JSON serialization
   1929  */
   1930 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
   1931   var json = this.serialize_(mirror, false, true);
   1932   return json;
   1933 }
   1934 
   1935 
   1936 /**
   1937  * Returns a serialization of all the objects referenced.
   1938  *
   1939  * @param {Mirror} mirror The mirror to serialize.
   1940  * @returns {Array.<Object>} Array of the referenced objects converted to
   1941  *     protcol objects.
   1942  */
   1943 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
   1944   // Collect the protocol representation of the referenced objects in an array.
   1945   var content = [];
   1946 
   1947   // Get the number of referenced objects.
   1948   var count = this.mirrors_.length;
   1949 
   1950   for (var i = 0; i < count; i++) {
   1951     content.push(this.serialize_(this.mirrors_[i], false, false));
   1952   }
   1953 
   1954   return content;
   1955 }
   1956 
   1957 
   1958 JSONProtocolSerializer.prototype.includeSource_ = function() {
   1959   return this.options_ && this.options_.includeSource;
   1960 }
   1961 
   1962 
   1963 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
   1964   return this.options_ && this.options_.inlineRefs;
   1965 }
   1966 
   1967 
   1968 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
   1969   if (IS_UNDEFINED(this.options_) ||
   1970       IS_UNDEFINED(this.options_.maxStringLength)) {
   1971     return kMaxProtocolStringLength;
   1972   }
   1973   return this.options_.maxStringLength;
   1974 }
   1975 
   1976 
   1977 JSONProtocolSerializer.prototype.add_ = function(mirror) {
   1978   // If this mirror is already in the list just return.
   1979   for (var i = 0; i < this.mirrors_.length; i++) {
   1980     if (this.mirrors_[i] === mirror) {
   1981       return;
   1982     }
   1983   }
   1984 
   1985   // Add the mirror to the list of mirrors to be serialized.
   1986   this.mirrors_.push(mirror);
   1987 }
   1988 
   1989 
   1990 /**
   1991  * Formats mirror object to protocol reference object with some data that can
   1992  * be used to display the value in debugger.
   1993  * @param {Mirror} mirror Mirror to serialize.
   1994  * @return {Object} Protocol reference object.
   1995  */
   1996 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
   1997     function(mirror) {
   1998   var o = {};
   1999   o.ref = mirror.handle();
   2000   o.type = mirror.type();
   2001   switch (mirror.type()) {
   2002     case UNDEFINED_TYPE:
   2003     case NULL_TYPE:
   2004     case BOOLEAN_TYPE:
   2005     case NUMBER_TYPE:
   2006       o.value = mirror.value();
   2007       break;
   2008     case STRING_TYPE:
   2009       o.value = mirror.getTruncatedValue(this.maxStringLength_());
   2010       break;
   2011     case FUNCTION_TYPE:
   2012       o.name = mirror.name();
   2013       o.inferredName = mirror.inferredName();
   2014       if (mirror.script()) {
   2015         o.scriptId = mirror.script().id();
   2016       }
   2017       break;
   2018     case ERROR_TYPE:
   2019     case REGEXP_TYPE:
   2020       o.value = mirror.toText();
   2021       break;
   2022     case OBJECT_TYPE:
   2023       o.className = mirror.className();
   2024       break;
   2025   }
   2026   return o;
   2027 };
   2028 
   2029 
   2030 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
   2031                                                        details) {
   2032   // If serializing a reference to a mirror just return the reference and add
   2033   // the mirror to the referenced mirrors.
   2034   if (reference &&
   2035       (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
   2036     if (this.inlineRefs_() && mirror.isValue()) {
   2037       return this.serializeReferenceWithDisplayData_(mirror);
   2038     } else {
   2039       this.add_(mirror);
   2040       return {'ref' : mirror.handle()};
   2041     }
   2042   }
   2043 
   2044   // Collect the JSON property/value pairs.
   2045   var content = {};
   2046 
   2047   // Add the mirror handle.
   2048   if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
   2049     content.handle = mirror.handle();
   2050   }
   2051 
   2052   // Always add the type.
   2053   content.type = mirror.type();
   2054 
   2055   switch (mirror.type()) {
   2056     case UNDEFINED_TYPE:
   2057     case NULL_TYPE:
   2058       // Undefined and null are represented just by their type.
   2059       break;
   2060 
   2061     case BOOLEAN_TYPE:
   2062       // Boolean values are simply represented by their value.
   2063       content.value = mirror.value();
   2064       break;
   2065 
   2066     case NUMBER_TYPE:
   2067       // Number values are simply represented by their value.
   2068       content.value = NumberToJSON_(mirror.value());
   2069       break;
   2070 
   2071     case STRING_TYPE:
   2072       // String values might have their value cropped to keep down size.
   2073       if (this.maxStringLength_() != -1 &&
   2074           mirror.length() > this.maxStringLength_()) {
   2075         var str = mirror.getTruncatedValue(this.maxStringLength_());
   2076         content.value = str;
   2077         content.fromIndex = 0;
   2078         content.toIndex = this.maxStringLength_();
   2079       } else {
   2080         content.value = mirror.value();
   2081       }
   2082       content.length = mirror.length();
   2083       break;
   2084 
   2085     case OBJECT_TYPE:
   2086     case FUNCTION_TYPE:
   2087     case ERROR_TYPE:
   2088     case REGEXP_TYPE:
   2089       // Add object representation.
   2090       this.serializeObject_(mirror, content, details);
   2091       break;
   2092 
   2093     case PROPERTY_TYPE:
   2094       throw new Error('PropertyMirror cannot be serialized independeltly')
   2095       break;
   2096 
   2097     case FRAME_TYPE:
   2098       // Add object representation.
   2099       this.serializeFrame_(mirror, content);
   2100       break;
   2101 
   2102     case SCOPE_TYPE:
   2103       // Add object representation.
   2104       this.serializeScope_(mirror, content);
   2105       break;
   2106 
   2107     case SCRIPT_TYPE:
   2108       // Script is represented by id, name and source attributes.
   2109       if (mirror.name()) {
   2110         content.name = mirror.name();
   2111       }
   2112       content.id = mirror.id();
   2113       content.lineOffset = mirror.lineOffset();
   2114       content.columnOffset = mirror.columnOffset();
   2115       content.lineCount = mirror.lineCount();
   2116       if (mirror.data()) {
   2117         content.data = mirror.data();
   2118       }
   2119       if (this.includeSource_()) {
   2120         content.source = mirror.source();
   2121       } else {
   2122         var sourceStart = mirror.source().substring(0, 80);
   2123         content.sourceStart = sourceStart;
   2124       }
   2125       content.sourceLength = mirror.source().length;
   2126       content.scriptType = mirror.scriptType();
   2127       content.compilationType = mirror.compilationType();
   2128       // For compilation type eval emit information on the script from which
   2129       // eval was called if a script is present.
   2130       if (mirror.compilationType() == 1 &&
   2131           mirror.evalFromScript()) {
   2132         content.evalFromScript =
   2133             this.serializeReference(mirror.evalFromScript());
   2134         var evalFromLocation = mirror.evalFromLocation()
   2135         if (evalFromLocation) {
   2136           content.evalFromLocation = { line: evalFromLocation.line,
   2137                                        column: evalFromLocation.column };
   2138         }
   2139         if (mirror.evalFromFunctionName()) {
   2140           content.evalFromFunctionName = mirror.evalFromFunctionName();
   2141         }
   2142       }
   2143       if (mirror.context()) {
   2144         content.context = this.serializeReference(mirror.context());
   2145       }
   2146       break;
   2147 
   2148     case CONTEXT_TYPE:
   2149       content.data = mirror.data();
   2150       break;
   2151   }
   2152 
   2153   // Always add the text representation.
   2154   content.text = mirror.toText();
   2155 
   2156   // Create and return the JSON string.
   2157   return content;
   2158 }
   2159 
   2160 
   2161 /**
   2162  * Serialize object information to the following JSON format.
   2163  *
   2164  *   {"className":"<class name>",
   2165  *    "constructorFunction":{"ref":<number>},
   2166  *    "protoObject":{"ref":<number>},
   2167  *    "prototypeObject":{"ref":<number>},
   2168  *    "namedInterceptor":<boolean>,
   2169  *    "indexedInterceptor":<boolean>,
   2170  *    "properties":[<properties>]}
   2171  */
   2172 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
   2173                                                              details) {
   2174   // Add general object properties.
   2175   content.className = mirror.className();
   2176   content.constructorFunction =
   2177       this.serializeReference(mirror.constructorFunction());
   2178   content.protoObject = this.serializeReference(mirror.protoObject());
   2179   content.prototypeObject = this.serializeReference(mirror.prototypeObject());
   2180 
   2181   // Add flags to indicate whether there are interceptors.
   2182   if (mirror.hasNamedInterceptor()) {
   2183     content.namedInterceptor = true;
   2184   }
   2185   if (mirror.hasIndexedInterceptor()) {
   2186     content.indexedInterceptor = true;
   2187   }
   2188 
   2189   // Add function specific properties.
   2190   if (mirror.isFunction()) {
   2191     // Add function specific properties.
   2192     content.name = mirror.name();
   2193     if (!IS_UNDEFINED(mirror.inferredName())) {
   2194       content.inferredName = mirror.inferredName();
   2195     }
   2196     content.resolved = mirror.resolved();
   2197     if (mirror.resolved()) {
   2198       content.source = mirror.source();
   2199     }
   2200     if (mirror.script()) {
   2201       content.script = this.serializeReference(mirror.script());
   2202       content.scriptId = mirror.script().id();
   2203 
   2204       serializeLocationFields(mirror.sourceLocation(), content);
   2205     }
   2206   }
   2207 
   2208   // Add date specific properties.
   2209   if (mirror.isDate()) {
   2210     // Add date specific properties.
   2211     content.value = mirror.value();
   2212   }
   2213 
   2214   // Add actual properties - named properties followed by indexed properties.
   2215   var propertyNames = mirror.propertyNames(PropertyKind.Named);
   2216   var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
   2217   var p = new Array(propertyNames.length + propertyIndexes.length);
   2218   for (var i = 0; i < propertyNames.length; i++) {
   2219     var propertyMirror = mirror.property(propertyNames[i]);
   2220     p[i] = this.serializeProperty_(propertyMirror);
   2221     if (details) {
   2222       this.add_(propertyMirror.value());
   2223     }
   2224   }
   2225   for (var i = 0; i < propertyIndexes.length; i++) {
   2226     var propertyMirror = mirror.property(propertyIndexes[i]);
   2227     p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
   2228     if (details) {
   2229       this.add_(propertyMirror.value());
   2230     }
   2231   }
   2232   content.properties = p;
   2233 }
   2234 
   2235 
   2236 /**
   2237  * Serialize location information to the following JSON format:
   2238  *
   2239  *   "position":"<position>",
   2240  *   "line":"<line>",
   2241  *   "column":"<column>",
   2242  *
   2243  * @param {SourceLocation} location The location to serialize, may be undefined.
   2244  */
   2245 function serializeLocationFields (location, content) {
   2246   if (!location) {
   2247     return;
   2248   }
   2249   content.position = location.position;
   2250   var line = location.line;
   2251   if (!IS_UNDEFINED(line)) {
   2252     content.line = line;
   2253   }
   2254   var column = location.column;
   2255   if (!IS_UNDEFINED(column)) {
   2256     content.column = column;
   2257   }
   2258 }
   2259 
   2260 
   2261 /**
   2262  * Serialize property information to the following JSON format for building the
   2263  * array of properties.
   2264  *
   2265  *   {"name":"<property name>",
   2266  *    "attributes":<number>,
   2267  *    "propertyType":<number>,
   2268  *    "ref":<number>}
   2269  *
   2270  * If the attribute for the property is PropertyAttribute.None it is not added.
   2271  * If the propertyType for the property is PropertyType.Normal it is not added.
   2272  * Here are a couple of examples.
   2273  *
   2274  *   {"name":"hello","ref":1}
   2275  *   {"name":"length","attributes":7,"propertyType":3,"ref":2}
   2276  *
   2277  * @param {PropertyMirror} propertyMirror The property to serialize.
   2278  * @returns {Object} Protocol object representing the property.
   2279  */
   2280 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
   2281   var result = {};
   2282 
   2283   result.name = propertyMirror.name();
   2284   var propertyValue = propertyMirror.value();
   2285   if (this.inlineRefs_() && propertyValue.isValue()) {
   2286     result.value = this.serializeReferenceWithDisplayData_(propertyValue);
   2287   } else {
   2288     if (propertyMirror.attributes() != PropertyAttribute.None) {
   2289       result.attributes = propertyMirror.attributes();
   2290     }
   2291     if (propertyMirror.propertyType() != PropertyType.Normal) {
   2292       result.propertyType = propertyMirror.propertyType();
   2293     }
   2294     result.ref = propertyValue.handle();
   2295   }
   2296   return result;
   2297 }
   2298 
   2299 
   2300 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
   2301   content.index = mirror.index();
   2302   content.receiver = this.serializeReference(mirror.receiver());
   2303   var func = mirror.func();
   2304   content.func = this.serializeReference(func);
   2305   if (func.script()) {
   2306     content.script = this.serializeReference(func.script());
   2307   }
   2308   content.constructCall = mirror.isConstructCall();
   2309   content.atReturn = mirror.isAtReturn();
   2310   if (mirror.isAtReturn()) {
   2311     content.returnValue = this.serializeReference(mirror.returnValue());
   2312   }
   2313   content.debuggerFrame = mirror.isDebuggerFrame();
   2314   var x = new Array(mirror.argumentCount());
   2315   for (var i = 0; i < mirror.argumentCount(); i++) {
   2316     var arg = {};
   2317     var argument_name = mirror.argumentName(i)
   2318     if (argument_name) {
   2319       arg.name = argument_name;
   2320     }
   2321     arg.value = this.serializeReference(mirror.argumentValue(i));
   2322     x[i] = arg;
   2323   }
   2324   content.arguments = x;
   2325   var x = new Array(mirror.localCount());
   2326   for (var i = 0; i < mirror.localCount(); i++) {
   2327     var local = {};
   2328     local.name = mirror.localName(i);
   2329     local.value = this.serializeReference(mirror.localValue(i));
   2330     x[i] = local;
   2331   }
   2332   content.locals = x;
   2333   serializeLocationFields(mirror.sourceLocation(), content);
   2334   var source_line_text = mirror.sourceLineText();
   2335   if (!IS_UNDEFINED(source_line_text)) {
   2336     content.sourceLineText = source_line_text;
   2337   }
   2338 
   2339   content.scopes = [];
   2340   for (var i = 0; i < mirror.scopeCount(); i++) {
   2341     var scope = mirror.scope(i);
   2342     content.scopes.push({
   2343       type: scope.scopeType(),
   2344       index: i
   2345     });
   2346   }
   2347 }
   2348 
   2349 
   2350 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
   2351   content.index = mirror.scopeIndex();
   2352   content.frameIndex = mirror.frameIndex();
   2353   content.type = mirror.scopeType();
   2354   content.object = this.inlineRefs_() ?
   2355                    this.serializeValue(mirror.scopeObject()) :
   2356                    this.serializeReference(mirror.scopeObject());
   2357 }
   2358 
   2359 
   2360 /**
   2361  * Convert a number to a protocol value. For all finite numbers the number
   2362  * itself is returned. For non finite numbers NaN, Infinite and
   2363  * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
   2364  * (not including the quotes) is returned.
   2365  *
   2366  * @param {number} value The number value to convert to a protocol value.
   2367  * @returns {number|string} Protocol value.
   2368  */
   2369 function NumberToJSON_(value) {
   2370   if (isNaN(value)) {
   2371     return 'NaN';
   2372   }
   2373   if (!NUMBER_IS_FINITE(value)) {
   2374     if (value > 0) {
   2375       return 'Infinity';
   2376     } else {
   2377       return '-Infinity';
   2378     }
   2379   }
   2380   return value;
   2381 }
   2382