Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Handle id counters.
      6 var next_handle_ = 0;
      7 var next_transient_handle_ = -1;
      8 
      9 // Mirror cache.
     10 var mirror_cache_ = [];
     11 var mirror_cache_enabled_ = true;
     12 
     13 
     14 function ToggleMirrorCache(value) {
     15   mirror_cache_enabled_ = value;
     16   next_handle_ = 0;
     17   mirror_cache_ = [];
     18 }
     19 
     20 
     21 // Wrapper to check whether an object is a Promise.  The call may not work
     22 // if promises are not enabled.
     23 // TODO(yangguo): remove try-catch once promises are enabled by default.
     24 function ObjectIsPromise(value) {
     25   try {
     26     return IS_SPEC_OBJECT(value) &&
     27            !IS_UNDEFINED(%DebugGetProperty(value, builtins.promiseStatus));
     28   } catch (e) {
     29     return false;
     30   }
     31 }
     32 
     33 
     34 /**
     35  * Returns the mirror for a specified value or object.
     36  *
     37  * @param {value or Object} value the value or object to retreive the mirror for
     38  * @param {boolean} transient indicate whether this object is transient and
     39  *    should not be added to the mirror cache. The default is not transient.
     40  * @returns {Mirror} the mirror reflects the passed value or object
     41  */
     42 function MakeMirror(value, opt_transient) {
     43   var mirror;
     44 
     45   // Look for non transient mirrors in the mirror cache.
     46   if (!opt_transient && mirror_cache_enabled_) {
     47     for (id in mirror_cache_) {
     48       mirror = mirror_cache_[id];
     49       if (mirror.value() === value) {
     50         return mirror;
     51       }
     52       // Special check for NaN as NaN == NaN is false.
     53       if (mirror.isNumber() && isNaN(mirror.value()) &&
     54           typeof value == 'number' && isNaN(value)) {
     55         return mirror;
     56       }
     57     }
     58   }
     59 
     60   if (IS_UNDEFINED(value)) {
     61     mirror = new UndefinedMirror();
     62   } else if (IS_NULL(value)) {
     63     mirror = new NullMirror();
     64   } else if (IS_BOOLEAN(value)) {
     65     mirror = new BooleanMirror(value);
     66   } else if (IS_NUMBER(value)) {
     67     mirror = new NumberMirror(value);
     68   } else if (IS_STRING(value)) {
     69     mirror = new StringMirror(value);
     70   } else if (IS_SYMBOL(value)) {
     71     mirror = new SymbolMirror(value);
     72   } else if (IS_ARRAY(value)) {
     73     mirror = new ArrayMirror(value);
     74   } else if (IS_DATE(value)) {
     75     mirror = new DateMirror(value);
     76   } else if (IS_FUNCTION(value)) {
     77     mirror = new FunctionMirror(value);
     78   } else if (IS_REGEXP(value)) {
     79     mirror = new RegExpMirror(value);
     80   } else if (IS_ERROR(value)) {
     81     mirror = new ErrorMirror(value);
     82   } else if (IS_SCRIPT(value)) {
     83     mirror = new ScriptMirror(value);
     84   } else if (IS_MAP(value) || IS_WEAKMAP(value)) {
     85     mirror = new MapMirror(value);
     86   } else if (IS_SET(value) || IS_WEAKSET(value)) {
     87     mirror = new SetMirror(value);
     88   } else if (ObjectIsPromise(value)) {
     89     mirror = new PromiseMirror(value);
     90   } else if (IS_GENERATOR(value)) {
     91     mirror = new GeneratorMirror(value);
     92   } else {
     93     mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
     94   }
     95 
     96   if (mirror_cache_enabled_) mirror_cache_[mirror.handle()] = mirror;
     97   return mirror;
     98 }
     99 
    100 
    101 /**
    102  * Returns the mirror for a specified mirror handle.
    103  *
    104  * @param {number} handle the handle to find the mirror for
    105  * @returns {Mirror or undefiend} the mirror with the requested handle or
    106  *     undefined if no mirror with the requested handle was found
    107  */
    108 function LookupMirror(handle) {
    109   if (!mirror_cache_enabled_) throw new Error("Mirror cache is disabled");
    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(UNDEFINED);
    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 var UNDEFINED_TYPE = 'undefined';
    148 var NULL_TYPE = 'null';
    149 var BOOLEAN_TYPE = 'boolean';
    150 var NUMBER_TYPE = 'number';
    151 var STRING_TYPE = 'string';
    152 var SYMBOL_TYPE = 'symbol';
    153 var OBJECT_TYPE = 'object';
    154 var FUNCTION_TYPE = 'function';
    155 var REGEXP_TYPE = 'regexp';
    156 var ERROR_TYPE = 'error';
    157 var PROPERTY_TYPE = 'property';
    158 var INTERNAL_PROPERTY_TYPE = 'internalProperty';
    159 var FRAME_TYPE = 'frame';
    160 var SCRIPT_TYPE = 'script';
    161 var CONTEXT_TYPE = 'context';
    162 var SCOPE_TYPE = 'scope';
    163 var PROMISE_TYPE = 'promise';
    164 var MAP_TYPE = 'map';
    165 var SET_TYPE = 'set';
    166 var GENERATOR_TYPE = 'generator';
    167 
    168 // Maximum length when sending strings through the JSON protocol.
    169 var kMaxProtocolStringLength = 80;
    170 
    171 // Different kind of properties.
    172 var PropertyKind = {};
    173 PropertyKind.Named   = 1;
    174 PropertyKind.Indexed = 2;
    175 
    176 
    177 // A copy of the PropertyType enum from property-details.h
    178 var PropertyType = {};
    179 PropertyType.Normal                  = 0;
    180 PropertyType.Field                   = 1;
    181 PropertyType.Constant                = 2;
    182 PropertyType.Callbacks               = 3;
    183 
    184 
    185 // Different attributes for a property.
    186 var PropertyAttribute = {};
    187 PropertyAttribute.None       = NONE;
    188 PropertyAttribute.ReadOnly   = READ_ONLY;
    189 PropertyAttribute.DontEnum   = DONT_ENUM;
    190 PropertyAttribute.DontDelete = DONT_DELETE;
    191 
    192 
    193 // A copy of the scope types from runtime.cc.
    194 var ScopeType = { Global: 0,
    195                   Local: 1,
    196                   With: 2,
    197                   Closure: 3,
    198                   Catch: 4,
    199                   Block: 5 };
    200 
    201 
    202 // Mirror hierarchy:
    203 //   - Mirror
    204 //     - ValueMirror
    205 //       - UndefinedMirror
    206 //       - NullMirror
    207 //       - NumberMirror
    208 //       - StringMirror
    209 //       - SymbolMirror
    210 //       - ObjectMirror
    211 //         - FunctionMirror
    212 //           - UnresolvedFunctionMirror
    213 //         - ArrayMirror
    214 //         - DateMirror
    215 //         - RegExpMirror
    216 //         - ErrorMirror
    217 //         - PromiseMirror
    218 //         - MapMirror
    219 //         - SetMirror
    220 //         - GeneratorMirror
    221 //     - PropertyMirror
    222 //     - InternalPropertyMirror
    223 //     - FrameMirror
    224 //     - ScriptMirror
    225 
    226 
    227 /**
    228  * Base class for all mirror objects.
    229  * @param {string} type The type of the mirror
    230  * @constructor
    231  */
    232 function Mirror(type) {
    233   this.type_ = type;
    234 }
    235 
    236 
    237 Mirror.prototype.type = function() {
    238   return this.type_;
    239 };
    240 
    241 
    242 /**
    243  * Check whether the mirror reflects a value.
    244  * @returns {boolean} True if the mirror reflects a value.
    245  */
    246 Mirror.prototype.isValue = function() {
    247   return this instanceof ValueMirror;
    248 };
    249 
    250 
    251 /**
    252  * Check whether the mirror reflects the undefined value.
    253  * @returns {boolean} True if the mirror reflects the undefined value.
    254  */
    255 Mirror.prototype.isUndefined = function() {
    256   return this instanceof UndefinedMirror;
    257 };
    258 
    259 
    260 /**
    261  * Check whether the mirror reflects the null value.
    262  * @returns {boolean} True if the mirror reflects the null value
    263  */
    264 Mirror.prototype.isNull = function() {
    265   return this instanceof NullMirror;
    266 };
    267 
    268 
    269 /**
    270  * Check whether the mirror reflects a boolean value.
    271  * @returns {boolean} True if the mirror reflects a boolean value
    272  */
    273 Mirror.prototype.isBoolean = function() {
    274   return this instanceof BooleanMirror;
    275 };
    276 
    277 
    278 /**
    279  * Check whether the mirror reflects a number value.
    280  * @returns {boolean} True if the mirror reflects a number value
    281  */
    282 Mirror.prototype.isNumber = function() {
    283   return this instanceof NumberMirror;
    284 };
    285 
    286 
    287 /**
    288  * Check whether the mirror reflects a string value.
    289  * @returns {boolean} True if the mirror reflects a string value
    290  */
    291 Mirror.prototype.isString = function() {
    292   return this instanceof StringMirror;
    293 };
    294 
    295 
    296 /**
    297  * Check whether the mirror reflects a symbol.
    298  * @returns {boolean} True if the mirror reflects a symbol
    299  */
    300 Mirror.prototype.isSymbol = function() {
    301   return this instanceof SymbolMirror;
    302 };
    303 
    304 
    305 /**
    306  * Check whether the mirror reflects an object.
    307  * @returns {boolean} True if the mirror reflects an object
    308  */
    309 Mirror.prototype.isObject = function() {
    310   return this instanceof ObjectMirror;
    311 };
    312 
    313 
    314 /**
    315  * Check whether the mirror reflects a function.
    316  * @returns {boolean} True if the mirror reflects a function
    317  */
    318 Mirror.prototype.isFunction = function() {
    319   return this instanceof FunctionMirror;
    320 };
    321 
    322 
    323 /**
    324  * Check whether the mirror reflects an unresolved function.
    325  * @returns {boolean} True if the mirror reflects an unresolved function
    326  */
    327 Mirror.prototype.isUnresolvedFunction = function() {
    328   return this instanceof UnresolvedFunctionMirror;
    329 };
    330 
    331 
    332 /**
    333  * Check whether the mirror reflects an array.
    334  * @returns {boolean} True if the mirror reflects an array
    335  */
    336 Mirror.prototype.isArray = function() {
    337   return this instanceof ArrayMirror;
    338 };
    339 
    340 
    341 /**
    342  * Check whether the mirror reflects a date.
    343  * @returns {boolean} True if the mirror reflects a date
    344  */
    345 Mirror.prototype.isDate = function() {
    346   return this instanceof DateMirror;
    347 };
    348 
    349 
    350 /**
    351  * Check whether the mirror reflects a regular expression.
    352  * @returns {boolean} True if the mirror reflects a regular expression
    353  */
    354 Mirror.prototype.isRegExp = function() {
    355   return this instanceof RegExpMirror;
    356 };
    357 
    358 
    359 /**
    360  * Check whether the mirror reflects an error.
    361  * @returns {boolean} True if the mirror reflects an error
    362  */
    363 Mirror.prototype.isError = function() {
    364   return this instanceof ErrorMirror;
    365 };
    366 
    367 
    368 /**
    369  * Check whether the mirror reflects a promise.
    370  * @returns {boolean} True if the mirror reflects a promise
    371  */
    372 Mirror.prototype.isPromise = function() {
    373   return this instanceof PromiseMirror;
    374 };
    375 
    376 
    377 /**
    378  * Check whether the mirror reflects a generator object.
    379  * @returns {boolean} True if the mirror reflects a generator object
    380  */
    381 Mirror.prototype.isGenerator = function() {
    382   return this instanceof GeneratorMirror;
    383 };
    384 
    385 
    386 /**
    387  * Check whether the mirror reflects a property.
    388  * @returns {boolean} True if the mirror reflects a property
    389  */
    390 Mirror.prototype.isProperty = function() {
    391   return this instanceof PropertyMirror;
    392 };
    393 
    394 
    395 /**
    396  * Check whether the mirror reflects an internal property.
    397  * @returns {boolean} True if the mirror reflects an internal property
    398  */
    399 Mirror.prototype.isInternalProperty = function() {
    400   return this instanceof InternalPropertyMirror;
    401 };
    402 
    403 
    404 /**
    405  * Check whether the mirror reflects a stack frame.
    406  * @returns {boolean} True if the mirror reflects a stack frame
    407  */
    408 Mirror.prototype.isFrame = function() {
    409   return this instanceof FrameMirror;
    410 };
    411 
    412 
    413 /**
    414  * Check whether the mirror reflects a script.
    415  * @returns {boolean} True if the mirror reflects a script
    416  */
    417 Mirror.prototype.isScript = function() {
    418   return this instanceof ScriptMirror;
    419 };
    420 
    421 
    422 /**
    423  * Check whether the mirror reflects a context.
    424  * @returns {boolean} True if the mirror reflects a context
    425  */
    426 Mirror.prototype.isContext = function() {
    427   return this instanceof ContextMirror;
    428 };
    429 
    430 
    431 /**
    432  * Check whether the mirror reflects a scope.
    433  * @returns {boolean} True if the mirror reflects a scope
    434  */
    435 Mirror.prototype.isScope = function() {
    436   return this instanceof ScopeMirror;
    437 };
    438 
    439 
    440 /**
    441  * Check whether the mirror reflects a map.
    442  * @returns {boolean} True if the mirror reflects a map
    443  */
    444 Mirror.prototype.isMap = function() {
    445   return this instanceof MapMirror;
    446 };
    447 
    448 
    449 /**
    450  * Check whether the mirror reflects a set.
    451  * @returns {boolean} True if the mirror reflects a set
    452  */
    453 Mirror.prototype.isSet = function() {
    454   return this instanceof SetMirror;
    455 };
    456 
    457 
    458 /**
    459  * Allocate a handle id for this object.
    460  */
    461 Mirror.prototype.allocateHandle_ = function() {
    462   if (mirror_cache_enabled_) this.handle_ = next_handle_++;
    463 };
    464 
    465 
    466 /**
    467  * Allocate a transient handle id for this object. Transient handles are
    468  * negative.
    469  */
    470 Mirror.prototype.allocateTransientHandle_ = function() {
    471   this.handle_ = next_transient_handle_--;
    472 };
    473 
    474 
    475 Mirror.prototype.toText = function() {
    476   // Simpel to text which is used when on specialization in subclass.
    477   return "#<" + this.constructor.name + ">";
    478 };
    479 
    480 
    481 /**
    482  * Base class for all value mirror objects.
    483  * @param {string} type The type of the mirror
    484  * @param {value} value The value reflected by this mirror
    485  * @param {boolean} transient indicate whether this object is transient with a
    486  *    transient handle
    487  * @constructor
    488  * @extends Mirror
    489  */
    490 function ValueMirror(type, value, transient) {
    491   %_CallFunction(this, type, Mirror);
    492   this.value_ = value;
    493   if (!transient) {
    494     this.allocateHandle_();
    495   } else {
    496     this.allocateTransientHandle_();
    497   }
    498 }
    499 inherits(ValueMirror, Mirror);
    500 
    501 
    502 Mirror.prototype.handle = function() {
    503   return this.handle_;
    504 };
    505 
    506 
    507 /**
    508  * Check whether this is a primitive value.
    509  * @return {boolean} True if the mirror reflects a primitive value
    510  */
    511 ValueMirror.prototype.isPrimitive = function() {
    512   var type = this.type();
    513   return type === 'undefined' ||
    514          type === 'null' ||
    515          type === 'boolean' ||
    516          type === 'number' ||
    517          type === 'string' ||
    518          type === 'symbol';
    519 };
    520 
    521 
    522 /**
    523  * Get the actual value reflected by this mirror.
    524  * @return {value} The value reflected by this mirror
    525  */
    526 ValueMirror.prototype.value = function() {
    527   return this.value_;
    528 };
    529 
    530 
    531 /**
    532  * Mirror object for Undefined.
    533  * @constructor
    534  * @extends ValueMirror
    535  */
    536 function UndefinedMirror() {
    537   %_CallFunction(this, UNDEFINED_TYPE, UNDEFINED, ValueMirror);
    538 }
    539 inherits(UndefinedMirror, ValueMirror);
    540 
    541 
    542 UndefinedMirror.prototype.toText = function() {
    543   return 'undefined';
    544 };
    545 
    546 
    547 /**
    548  * Mirror object for null.
    549  * @constructor
    550  * @extends ValueMirror
    551  */
    552 function NullMirror() {
    553   %_CallFunction(this, NULL_TYPE, null, ValueMirror);
    554 }
    555 inherits(NullMirror, ValueMirror);
    556 
    557 
    558 NullMirror.prototype.toText = function() {
    559   return 'null';
    560 };
    561 
    562 
    563 /**
    564  * Mirror object for boolean values.
    565  * @param {boolean} value The boolean value reflected by this mirror
    566  * @constructor
    567  * @extends ValueMirror
    568  */
    569 function BooleanMirror(value) {
    570   %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
    571 }
    572 inherits(BooleanMirror, ValueMirror);
    573 
    574 
    575 BooleanMirror.prototype.toText = function() {
    576   return this.value_ ? 'true' : 'false';
    577 };
    578 
    579 
    580 /**
    581  * Mirror object for number values.
    582  * @param {number} value The number value reflected by this mirror
    583  * @constructor
    584  * @extends ValueMirror
    585  */
    586 function NumberMirror(value) {
    587   %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
    588 }
    589 inherits(NumberMirror, ValueMirror);
    590 
    591 
    592 NumberMirror.prototype.toText = function() {
    593   return %_NumberToString(this.value_);
    594 };
    595 
    596 
    597 /**
    598  * Mirror object for string values.
    599  * @param {string} value The string value reflected by this mirror
    600  * @constructor
    601  * @extends ValueMirror
    602  */
    603 function StringMirror(value) {
    604   %_CallFunction(this, STRING_TYPE, value, ValueMirror);
    605 }
    606 inherits(StringMirror, ValueMirror);
    607 
    608 
    609 StringMirror.prototype.length = function() {
    610   return this.value_.length;
    611 };
    612 
    613 StringMirror.prototype.getTruncatedValue = function(maxLength) {
    614   if (maxLength != -1 && this.length() > maxLength) {
    615     return this.value_.substring(0, maxLength) +
    616            '... (length: ' + this.length() + ')';
    617   }
    618   return this.value_;
    619 };
    620 
    621 StringMirror.prototype.toText = function() {
    622   return this.getTruncatedValue(kMaxProtocolStringLength);
    623 };
    624 
    625 
    626 /**
    627  * Mirror object for a Symbol
    628  * @param {Object} value The Symbol
    629  * @constructor
    630  * @extends Mirror
    631  */
    632 function SymbolMirror(value) {
    633   %_CallFunction(this, SYMBOL_TYPE, value, ValueMirror);
    634 }
    635 inherits(SymbolMirror, ValueMirror);
    636 
    637 
    638 SymbolMirror.prototype.description = function() {
    639   return %SymbolDescription(%_ValueOf(this.value_));
    640 }
    641 
    642 
    643 SymbolMirror.prototype.toText = function() {
    644   return %_CallFunction(this.value_, builtins.SymbolToString);
    645 }
    646 
    647 
    648 /**
    649  * Mirror object for objects.
    650  * @param {object} value The object reflected by this mirror
    651  * @param {boolean} transient indicate whether this object is transient with a
    652  *    transient handle
    653  * @constructor
    654  * @extends ValueMirror
    655  */
    656 function ObjectMirror(value, type, transient) {
    657   %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
    658 }
    659 inherits(ObjectMirror, ValueMirror);
    660 
    661 
    662 ObjectMirror.prototype.className = function() {
    663   return %_ClassOf(this.value_);
    664 };
    665 
    666 
    667 ObjectMirror.prototype.constructorFunction = function() {
    668   return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
    669 };
    670 
    671 
    672 ObjectMirror.prototype.prototypeObject = function() {
    673   return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
    674 };
    675 
    676 
    677 ObjectMirror.prototype.protoObject = function() {
    678   return MakeMirror(%DebugGetPrototype(this.value_));
    679 };
    680 
    681 
    682 ObjectMirror.prototype.hasNamedInterceptor = function() {
    683   // Get information on interceptors for this object.
    684   var x = %GetInterceptorInfo(this.value_);
    685   return (x & 2) != 0;
    686 };
    687 
    688 
    689 ObjectMirror.prototype.hasIndexedInterceptor = function() {
    690   // Get information on interceptors for this object.
    691   var x = %GetInterceptorInfo(this.value_);
    692   return (x & 1) != 0;
    693 };
    694 
    695 
    696 // Get all own property names except for private symbols.
    697 function TryGetPropertyNames(object) {
    698   try {
    699     // TODO(yangguo): Should there be a special debugger implementation of
    700     // %GetOwnPropertyNames that doesn't perform access checks?
    701     return %GetOwnPropertyNames(object, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
    702   } catch (e) {
    703     // Might have hit a failed access check.
    704     return [];
    705   }
    706 }
    707 
    708 
    709 /**
    710  * Return the property names for this object.
    711  * @param {number} kind Indicate whether named, indexed or both kinds of
    712  *     properties are requested
    713  * @param {number} limit Limit the number of names returend to the specified
    714        value
    715  * @return {Array} Property names for this object
    716  */
    717 ObjectMirror.prototype.propertyNames = function(kind, limit) {
    718   // Find kind and limit and allocate array for the result
    719   kind = kind || PropertyKind.Named | PropertyKind.Indexed;
    720 
    721   var propertyNames;
    722   var elementNames;
    723   var total = 0;
    724 
    725   // Find all the named properties.
    726   if (kind & PropertyKind.Named) {
    727     propertyNames = TryGetPropertyNames(this.value_);
    728     total += propertyNames.length;
    729 
    730     // Get names for named interceptor properties if any.
    731     if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
    732       var namedInterceptorNames =
    733           %GetNamedInterceptorPropertyNames(this.value_);
    734       if (namedInterceptorNames) {
    735         propertyNames = propertyNames.concat(namedInterceptorNames);
    736         total += namedInterceptorNames.length;
    737       }
    738     }
    739   }
    740 
    741   // Find all the indexed properties.
    742   if (kind & PropertyKind.Indexed) {
    743     // Get own element names.
    744     elementNames = %GetOwnElementNames(this.value_);
    745     total += elementNames.length;
    746 
    747     // Get names for indexed interceptor properties.
    748     if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
    749       var indexedInterceptorNames =
    750           %GetIndexedInterceptorElementNames(this.value_);
    751       if (indexedInterceptorNames) {
    752         elementNames = elementNames.concat(indexedInterceptorNames);
    753         total += indexedInterceptorNames.length;
    754       }
    755     }
    756   }
    757   limit = Math.min(limit || total, total);
    758 
    759   var names = new Array(limit);
    760   var index = 0;
    761 
    762   // Copy names for named properties.
    763   if (kind & PropertyKind.Named) {
    764     for (var i = 0; index < limit && i < propertyNames.length; i++) {
    765       names[index++] = propertyNames[i];
    766     }
    767   }
    768 
    769   // Copy names for indexed properties.
    770   if (kind & PropertyKind.Indexed) {
    771     for (var i = 0; index < limit && i < elementNames.length; i++) {
    772       names[index++] = elementNames[i];
    773     }
    774   }
    775 
    776   return names;
    777 };
    778 
    779 
    780 /**
    781  * Return the properties for this object as an array of PropertyMirror objects.
    782  * @param {number} kind Indicate whether named, indexed or both kinds of
    783  *     properties are requested
    784  * @param {number} limit Limit the number of properties returned to the
    785        specified value
    786  * @return {Array} Property mirrors for this object
    787  */
    788 ObjectMirror.prototype.properties = function(kind, limit) {
    789   var names = this.propertyNames(kind, limit);
    790   var properties = new Array(names.length);
    791   for (var i = 0; i < names.length; i++) {
    792     properties[i] = this.property(names[i]);
    793   }
    794 
    795   return properties;
    796 };
    797 
    798 
    799 /**
    800  * Return the internal properties for this object as an array of
    801  * InternalPropertyMirror objects.
    802  * @return {Array} Property mirrors for this object
    803  */
    804 ObjectMirror.prototype.internalProperties = function() {
    805   return ObjectMirror.GetInternalProperties(this.value_);
    806 }
    807 
    808 
    809 ObjectMirror.prototype.property = function(name) {
    810   var details = %DebugGetPropertyDetails(this.value_, %ToName(name));
    811   if (details) {
    812     return new PropertyMirror(this, name, details);
    813   }
    814 
    815   // Nothing found.
    816   return GetUndefinedMirror();
    817 };
    818 
    819 
    820 
    821 /**
    822  * Try to find a property from its value.
    823  * @param {Mirror} value The property value to look for
    824  * @return {PropertyMirror} The property with the specified value. If no
    825  *     property was found with the specified value UndefinedMirror is returned
    826  */
    827 ObjectMirror.prototype.lookupProperty = function(value) {
    828   var properties = this.properties();
    829 
    830   // Look for property value in properties.
    831   for (var i = 0; i < properties.length; i++) {
    832 
    833     // Skip properties which are defined through assessors.
    834     var property = properties[i];
    835     if (property.propertyType() != PropertyType.Callbacks) {
    836       if (%_ObjectEquals(property.value_, value.value_)) {
    837         return property;
    838       }
    839     }
    840   }
    841 
    842   // Nothing found.
    843   return GetUndefinedMirror();
    844 };
    845 
    846 
    847 /**
    848  * Returns objects which has direct references to this object
    849  * @param {number} opt_max_objects Optional parameter specifying the maximum
    850  *     number of referencing objects to return.
    851  * @return {Array} The objects which has direct references to this object.
    852  */
    853 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
    854   // Find all objects with direct references to this object.
    855   var result = %DebugReferencedBy(this.value_,
    856                                   Mirror.prototype, opt_max_objects || 0);
    857 
    858   // Make mirrors for all the references found.
    859   for (var i = 0; i < result.length; i++) {
    860     result[i] = MakeMirror(result[i]);
    861   }
    862 
    863   return result;
    864 };
    865 
    866 
    867 ObjectMirror.prototype.toText = function() {
    868   var name;
    869   var ctor = this.constructorFunction();
    870   if (!ctor.isFunction()) {
    871     name = this.className();
    872   } else {
    873     name = ctor.name();
    874     if (!name) {
    875       name = this.className();
    876     }
    877   }
    878   return '#<' + name + '>';
    879 };
    880 
    881 
    882 /**
    883  * Return the internal properties of the value, such as [[PrimitiveValue]] of
    884  * scalar wrapper objects, properties of the bound function and properties of
    885  * the promise.
    886  * This method is done static to be accessible from Debug API with the bare
    887  * values without mirrors.
    888  * @return {Array} array (possibly empty) of InternalProperty instances
    889  */
    890 ObjectMirror.GetInternalProperties = function(value) {
    891   if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) ||
    892       IS_BOOLEAN_WRAPPER(value)) {
    893     var primitiveValue = %_ValueOf(value);
    894     return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)];
    895   } else if (IS_FUNCTION(value)) {
    896     var bindings = %BoundFunctionGetBindings(value);
    897     var result = [];
    898     if (bindings && IS_ARRAY(bindings)) {
    899       result.push(new InternalPropertyMirror("[[TargetFunction]]",
    900                                              bindings[0]));
    901       result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1]));
    902       var boundArgs = [];
    903       for (var i = 2; i < bindings.length; i++) {
    904         boundArgs.push(bindings[i]);
    905       }
    906       result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs));
    907     }
    908     return result;
    909   } else if (ObjectIsPromise(value)) {
    910     var result = [];
    911     result.push(new InternalPropertyMirror("[[PromiseStatus]]",
    912                                            PromiseGetStatus_(value)));
    913     result.push(new InternalPropertyMirror("[[PromiseValue]]",
    914                                            PromiseGetValue_(value)));
    915     return result;
    916   }
    917   return [];
    918 }
    919 
    920 
    921 /**
    922  * Mirror object for functions.
    923  * @param {function} value The function object reflected by this mirror.
    924  * @constructor
    925  * @extends ObjectMirror
    926  */
    927 function FunctionMirror(value) {
    928   %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
    929   this.resolved_ = true;
    930 }
    931 inherits(FunctionMirror, ObjectMirror);
    932 
    933 
    934 /**
    935  * Returns whether the function is resolved.
    936  * @return {boolean} True if the function is resolved. Unresolved functions can
    937  *     only originate as functions from stack frames
    938  */
    939 FunctionMirror.prototype.resolved = function() {
    940   return this.resolved_;
    941 };
    942 
    943 
    944 /**
    945  * Returns the name of the function.
    946  * @return {string} Name of the function
    947  */
    948 FunctionMirror.prototype.name = function() {
    949   return %FunctionGetName(this.value_);
    950 };
    951 
    952 
    953 /**
    954  * Returns the inferred name of the function.
    955  * @return {string} Name of the function
    956  */
    957 FunctionMirror.prototype.inferredName = function() {
    958   return %FunctionGetInferredName(this.value_);
    959 };
    960 
    961 
    962 /**
    963  * Returns the source code for the function.
    964  * @return {string or undefined} The source code for the function. If the
    965  *     function is not resolved undefined will be returned.
    966  */
    967 FunctionMirror.prototype.source = function() {
    968   // Return source if function is resolved. Otherwise just fall through to
    969   // return undefined.
    970   if (this.resolved()) {
    971     return builtins.FunctionSourceString(this.value_);
    972   }
    973 };
    974 
    975 
    976 /**
    977  * Returns the script object for the function.
    978  * @return {ScriptMirror or undefined} Script object for the function or
    979  *     undefined if the function has no script
    980  */
    981 FunctionMirror.prototype.script = function() {
    982   // Return script if function is resolved. Otherwise just fall through
    983   // to return undefined.
    984   if (this.resolved()) {
    985     if (this.script_) {
    986       return this.script_;
    987     }
    988     var script = %FunctionGetScript(this.value_);
    989     if (script) {
    990       return this.script_ = MakeMirror(script);
    991     }
    992   }
    993 };
    994 
    995 
    996 /**
    997  * Returns the script source position for the function. Only makes sense
    998  * for functions which has a script defined.
    999  * @return {Number or undefined} in-script position for the function
   1000  */
   1001 FunctionMirror.prototype.sourcePosition_ = function() {
   1002   // Return position if function is resolved. Otherwise just fall
   1003   // through to return undefined.
   1004   if (this.resolved()) {
   1005     return %FunctionGetScriptSourcePosition(this.value_);
   1006   }
   1007 };
   1008 
   1009 
   1010 /**
   1011  * Returns the script source location object for the function. Only makes sense
   1012  * for functions which has a script defined.
   1013  * @return {Location or undefined} in-script location for the function begin
   1014  */
   1015 FunctionMirror.prototype.sourceLocation = function() {
   1016   if (this.resolved()) {
   1017     var script = this.script();
   1018     if (script) {
   1019       return script.locationFromPosition(this.sourcePosition_(), true);
   1020     }
   1021   }
   1022 };
   1023 
   1024 
   1025 /**
   1026  * Returns objects constructed by this function.
   1027  * @param {number} opt_max_instances Optional parameter specifying the maximum
   1028  *     number of instances to return.
   1029  * @return {Array or undefined} The objects constructed by this function.
   1030  */
   1031 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
   1032   if (this.resolved()) {
   1033     // Find all objects constructed from this function.
   1034     var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
   1035 
   1036     // Make mirrors for all the instances found.
   1037     for (var i = 0; i < result.length; i++) {
   1038       result[i] = MakeMirror(result[i]);
   1039     }
   1040 
   1041     return result;
   1042   } else {
   1043     return [];
   1044   }
   1045 };
   1046 
   1047 
   1048 FunctionMirror.prototype.scopeCount = function() {
   1049   if (this.resolved()) {
   1050     if (IS_UNDEFINED(this.scopeCount_)) {
   1051       this.scopeCount_ = %GetFunctionScopeCount(this.value());
   1052     }
   1053     return this.scopeCount_;
   1054   } else {
   1055     return 0;
   1056   }
   1057 };
   1058 
   1059 
   1060 FunctionMirror.prototype.scope = function(index) {
   1061   if (this.resolved()) {
   1062     return new ScopeMirror(UNDEFINED, this, index);
   1063   }
   1064 };
   1065 
   1066 
   1067 FunctionMirror.prototype.toText = function() {
   1068   return this.source();
   1069 };
   1070 
   1071 
   1072 /**
   1073  * Mirror object for unresolved functions.
   1074  * @param {string} value The name for the unresolved function reflected by this
   1075  *     mirror.
   1076  * @constructor
   1077  * @extends ObjectMirror
   1078  */
   1079 function UnresolvedFunctionMirror(value) {
   1080   // Construct this using the ValueMirror as an unresolved function is not a
   1081   // real object but just a string.
   1082   %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
   1083   this.propertyCount_ = 0;
   1084   this.elementCount_ = 0;
   1085   this.resolved_ = false;
   1086 }
   1087 inherits(UnresolvedFunctionMirror, FunctionMirror);
   1088 
   1089 
   1090 UnresolvedFunctionMirror.prototype.className = function() {
   1091   return 'Function';
   1092 };
   1093 
   1094 
   1095 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
   1096   return GetUndefinedMirror();
   1097 };
   1098 
   1099 
   1100 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
   1101   return GetUndefinedMirror();
   1102 };
   1103 
   1104 
   1105 UnresolvedFunctionMirror.prototype.protoObject = function() {
   1106   return GetUndefinedMirror();
   1107 };
   1108 
   1109 
   1110 UnresolvedFunctionMirror.prototype.name = function() {
   1111   return this.value_;
   1112 };
   1113 
   1114 
   1115 UnresolvedFunctionMirror.prototype.inferredName = function() {
   1116   return undefined;
   1117 };
   1118 
   1119 
   1120 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
   1121   return [];
   1122 };
   1123 
   1124 
   1125 /**
   1126  * Mirror object for arrays.
   1127  * @param {Array} value The Array object reflected by this mirror
   1128  * @constructor
   1129  * @extends ObjectMirror
   1130  */
   1131 function ArrayMirror(value) {
   1132   %_CallFunction(this, value, ObjectMirror);
   1133 }
   1134 inherits(ArrayMirror, ObjectMirror);
   1135 
   1136 
   1137 ArrayMirror.prototype.length = function() {
   1138   return this.value_.length;
   1139 };
   1140 
   1141 
   1142 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
   1143                                                             opt_to_index) {
   1144   var from_index = opt_from_index || 0;
   1145   var to_index = opt_to_index || this.length() - 1;
   1146   if (from_index > to_index) return new Array();
   1147   var values = new Array(to_index - from_index + 1);
   1148   for (var i = from_index; i <= to_index; i++) {
   1149     var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
   1150     var value;
   1151     if (details) {
   1152       value = new PropertyMirror(this, i, details);
   1153     } else {
   1154       value = GetUndefinedMirror();
   1155     }
   1156     values[i - from_index] = value;
   1157   }
   1158   return values;
   1159 };
   1160 
   1161 
   1162 /**
   1163  * Mirror object for dates.
   1164  * @param {Date} value The Date object reflected by this mirror
   1165  * @constructor
   1166  * @extends ObjectMirror
   1167  */
   1168 function DateMirror(value) {
   1169   %_CallFunction(this, value, ObjectMirror);
   1170 }
   1171 inherits(DateMirror, ObjectMirror);
   1172 
   1173 
   1174 DateMirror.prototype.toText = function() {
   1175   var s = JSON.stringify(this.value_);
   1176   return s.substring(1, s.length - 1);  // cut quotes
   1177 };
   1178 
   1179 
   1180 /**
   1181  * Mirror object for regular expressions.
   1182  * @param {RegExp} value The RegExp object reflected by this mirror
   1183  * @constructor
   1184  * @extends ObjectMirror
   1185  */
   1186 function RegExpMirror(value) {
   1187   %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
   1188 }
   1189 inherits(RegExpMirror, ObjectMirror);
   1190 
   1191 
   1192 /**
   1193  * Returns the source to the regular expression.
   1194  * @return {string or undefined} The source to the regular expression
   1195  */
   1196 RegExpMirror.prototype.source = function() {
   1197   return this.value_.source;
   1198 };
   1199 
   1200 
   1201 /**
   1202  * Returns whether this regular expression has the global (g) flag set.
   1203  * @return {boolean} Value of the global flag
   1204  */
   1205 RegExpMirror.prototype.global = function() {
   1206   return this.value_.global;
   1207 };
   1208 
   1209 
   1210 /**
   1211  * Returns whether this regular expression has the ignore case (i) flag set.
   1212  * @return {boolean} Value of the ignore case flag
   1213  */
   1214 RegExpMirror.prototype.ignoreCase = function() {
   1215   return this.value_.ignoreCase;
   1216 };
   1217 
   1218 
   1219 /**
   1220  * Returns whether this regular expression has the multiline (m) flag set.
   1221  * @return {boolean} Value of the multiline flag
   1222  */
   1223 RegExpMirror.prototype.multiline = function() {
   1224   return this.value_.multiline;
   1225 };
   1226 
   1227 
   1228 RegExpMirror.prototype.toText = function() {
   1229   // Simpel to text which is used when on specialization in subclass.
   1230   return "/" + this.source() + "/";
   1231 };
   1232 
   1233 
   1234 /**
   1235  * Mirror object for error objects.
   1236  * @param {Error} value The error object reflected by this mirror
   1237  * @constructor
   1238  * @extends ObjectMirror
   1239  */
   1240 function ErrorMirror(value) {
   1241   %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
   1242 }
   1243 inherits(ErrorMirror, ObjectMirror);
   1244 
   1245 
   1246 /**
   1247  * Returns the message for this eror object.
   1248  * @return {string or undefined} The message for this eror object
   1249  */
   1250 ErrorMirror.prototype.message = function() {
   1251   return this.value_.message;
   1252 };
   1253 
   1254 
   1255 ErrorMirror.prototype.toText = function() {
   1256   // Use the same text representation as in messages.js.
   1257   var text;
   1258   try {
   1259     str = %_CallFunction(this.value_, builtins.ErrorToString);
   1260   } catch (e) {
   1261     str = '#<Error>';
   1262   }
   1263   return str;
   1264 };
   1265 
   1266 
   1267 /**
   1268  * Mirror object for a Promise object.
   1269  * @param {Object} value The Promise object
   1270  * @constructor
   1271  * @extends ObjectMirror
   1272  */
   1273 function PromiseMirror(value) {
   1274   %_CallFunction(this, value, PROMISE_TYPE, ObjectMirror);
   1275 }
   1276 inherits(PromiseMirror, ObjectMirror);
   1277 
   1278 
   1279 function PromiseGetStatus_(value) {
   1280   var status = %DebugGetProperty(value, builtins.promiseStatus);
   1281   if (status == 0) return "pending";
   1282   if (status == 1) return "resolved";
   1283   return "rejected";
   1284 }
   1285 
   1286 
   1287 function PromiseGetValue_(value) {
   1288   return %DebugGetProperty(value, builtins.promiseValue);
   1289 }
   1290 
   1291 
   1292 PromiseMirror.prototype.status = function() {
   1293   return PromiseGetStatus_(this.value_);
   1294 };
   1295 
   1296 
   1297 PromiseMirror.prototype.promiseValue = function() {
   1298   return MakeMirror(PromiseGetValue_(this.value_));
   1299 };
   1300 
   1301 
   1302 function MapMirror(value) {
   1303   %_CallFunction(this, value, MAP_TYPE, ObjectMirror);
   1304 }
   1305 inherits(MapMirror, ObjectMirror);
   1306 
   1307 
   1308 /**
   1309  * Returns an array of key/value pairs of a map.
   1310  * This will keep keys alive for WeakMaps.
   1311  *
   1312  * @returns {Array.<Object>} Array of key/value pairs of a map.
   1313  */
   1314 MapMirror.prototype.entries = function() {
   1315   var result = [];
   1316 
   1317   if (IS_WEAKMAP(this.value_)) {
   1318     var entries = %GetWeakMapEntries(this.value_);
   1319     for (var i = 0; i < entries.length; i += 2) {
   1320       result.push({
   1321         key: entries[i],
   1322         value: entries[i + 1]
   1323       });
   1324     }
   1325     return result;
   1326   }
   1327 
   1328   var iter = %_CallFunction(this.value_, builtins.MapEntries);
   1329   var next;
   1330   while (!(next = iter.next()).done) {
   1331     result.push({
   1332       key: next.value[0],
   1333       value: next.value[1]
   1334     });
   1335   }
   1336   return result;
   1337 };
   1338 
   1339 
   1340 function SetMirror(value) {
   1341   %_CallFunction(this, value, SET_TYPE, ObjectMirror);
   1342 }
   1343 inherits(SetMirror, ObjectMirror);
   1344 
   1345 
   1346 /**
   1347  * Returns an array of elements of a set.
   1348  * This will keep elements alive for WeakSets.
   1349  *
   1350  * @returns {Array.<Object>} Array of elements of a set.
   1351  */
   1352 SetMirror.prototype.values = function() {
   1353   if (IS_WEAKSET(this.value_)) {
   1354     return %GetWeakSetValues(this.value_);
   1355   }
   1356 
   1357   var result = [];
   1358   var iter = %_CallFunction(this.value_, builtins.SetValues);
   1359   var next;
   1360   while (!(next = iter.next()).done) {
   1361     result.push(next.value);
   1362   }
   1363   return result;
   1364 };
   1365 
   1366 
   1367 /**
   1368  * Mirror object for a Generator object.
   1369  * @param {Object} data The Generator object
   1370  * @constructor
   1371  * @extends Mirror
   1372  */
   1373 function GeneratorMirror(value) {
   1374   %_CallFunction(this, value, GENERATOR_TYPE, ObjectMirror);
   1375 }
   1376 inherits(GeneratorMirror, ObjectMirror);
   1377 
   1378 
   1379 GeneratorMirror.prototype.status = function() {
   1380   var continuation = %GeneratorGetContinuation(this.value_);
   1381   if (continuation < 0) return "running";
   1382   if (continuation == 0) return "closed";
   1383   return "suspended";
   1384 };
   1385 
   1386 
   1387 GeneratorMirror.prototype.sourcePosition_ = function() {
   1388   return %GeneratorGetSourcePosition(this.value_);
   1389 };
   1390 
   1391 
   1392 GeneratorMirror.prototype.sourceLocation = function() {
   1393   var pos = this.sourcePosition_();
   1394   if (!IS_UNDEFINED(pos)) {
   1395     var script = this.func().script();
   1396     if (script) {
   1397       return script.locationFromPosition(pos, true);
   1398     }
   1399   }
   1400 };
   1401 
   1402 
   1403 GeneratorMirror.prototype.func = function() {
   1404   if (!this.func_) {
   1405     this.func_ = MakeMirror(%GeneratorGetFunction(this.value_));
   1406   }
   1407   return this.func_;
   1408 };
   1409 
   1410 
   1411 GeneratorMirror.prototype.context = function() {
   1412   if (!this.context_) {
   1413     this.context_ = new ContextMirror(%GeneratorGetContext(this.value_));
   1414   }
   1415   return this.context_;
   1416 };
   1417 
   1418 
   1419 GeneratorMirror.prototype.receiver = function() {
   1420   if (!this.receiver_) {
   1421     this.receiver_ = MakeMirror(%GeneratorGetReceiver(this.value_));
   1422   }
   1423   return this.receiver_;
   1424 };
   1425 
   1426 
   1427 /**
   1428  * Base mirror object for properties.
   1429  * @param {ObjectMirror} mirror The mirror object having this property
   1430  * @param {string} name The name of the property
   1431  * @param {Array} details Details about the property
   1432  * @constructor
   1433  * @extends Mirror
   1434  */
   1435 function PropertyMirror(mirror, name, details) {
   1436   %_CallFunction(this, PROPERTY_TYPE, Mirror);
   1437   this.mirror_ = mirror;
   1438   this.name_ = name;
   1439   this.value_ = details[0];
   1440   this.details_ = details[1];
   1441   this.is_interceptor_ = details[2];
   1442   if (details.length > 3) {
   1443     this.exception_ = details[3];
   1444     this.getter_ = details[4];
   1445     this.setter_ = details[5];
   1446   }
   1447 }
   1448 inherits(PropertyMirror, Mirror);
   1449 
   1450 
   1451 PropertyMirror.prototype.isReadOnly = function() {
   1452   return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
   1453 };
   1454 
   1455 
   1456 PropertyMirror.prototype.isEnum = function() {
   1457   return (this.attributes() & PropertyAttribute.DontEnum) == 0;
   1458 };
   1459 
   1460 
   1461 PropertyMirror.prototype.canDelete = function() {
   1462   return (this.attributes() & PropertyAttribute.DontDelete) == 0;
   1463 };
   1464 
   1465 
   1466 PropertyMirror.prototype.name = function() {
   1467   return this.name_;
   1468 };
   1469 
   1470 
   1471 PropertyMirror.prototype.isIndexed = function() {
   1472   for (var i = 0; i < this.name_.length; i++) {
   1473     if (this.name_[i] < '0' || '9' < this.name_[i]) {
   1474       return false;
   1475     }
   1476   }
   1477   return true;
   1478 };
   1479 
   1480 
   1481 PropertyMirror.prototype.value = function() {
   1482   return MakeMirror(this.value_, false);
   1483 };
   1484 
   1485 
   1486 /**
   1487  * Returns whether this property value is an exception.
   1488  * @return {booolean} True if this property value is an exception
   1489  */
   1490 PropertyMirror.prototype.isException = function() {
   1491   return this.exception_ ? true : false;
   1492 };
   1493 
   1494 
   1495 PropertyMirror.prototype.attributes = function() {
   1496   return %DebugPropertyAttributesFromDetails(this.details_);
   1497 };
   1498 
   1499 
   1500 PropertyMirror.prototype.propertyType = function() {
   1501   return %DebugPropertyTypeFromDetails(this.details_);
   1502 };
   1503 
   1504 
   1505 PropertyMirror.prototype.insertionIndex = function() {
   1506   return %DebugPropertyIndexFromDetails(this.details_);
   1507 };
   1508 
   1509 
   1510 /**
   1511  * Returns whether this property has a getter defined through __defineGetter__.
   1512  * @return {booolean} True if this property has a getter
   1513  */
   1514 PropertyMirror.prototype.hasGetter = function() {
   1515   return this.getter_ ? true : false;
   1516 };
   1517 
   1518 
   1519 /**
   1520  * Returns whether this property has a setter defined through __defineSetter__.
   1521  * @return {booolean} True if this property has a setter
   1522  */
   1523 PropertyMirror.prototype.hasSetter = function() {
   1524   return this.setter_ ? true : false;
   1525 };
   1526 
   1527 
   1528 /**
   1529  * Returns the getter for this property defined through __defineGetter__.
   1530  * @return {Mirror} FunctionMirror reflecting the getter function or
   1531  *     UndefinedMirror if there is no getter for this property
   1532  */
   1533 PropertyMirror.prototype.getter = function() {
   1534   if (this.hasGetter()) {
   1535     return MakeMirror(this.getter_);
   1536   } else {
   1537     return GetUndefinedMirror();
   1538   }
   1539 };
   1540 
   1541 
   1542 /**
   1543  * Returns the setter for this property defined through __defineSetter__.
   1544  * @return {Mirror} FunctionMirror reflecting the setter function or
   1545  *     UndefinedMirror if there is no setter for this property
   1546  */
   1547 PropertyMirror.prototype.setter = function() {
   1548   if (this.hasSetter()) {
   1549     return MakeMirror(this.setter_);
   1550   } else {
   1551     return GetUndefinedMirror();
   1552   }
   1553 };
   1554 
   1555 
   1556 /**
   1557  * Returns whether this property is natively implemented by the host or a set
   1558  * through JavaScript code.
   1559  * @return {boolean} True if the property is
   1560  *     UndefinedMirror if there is no setter for this property
   1561  */
   1562 PropertyMirror.prototype.isNative = function() {
   1563   return this.is_interceptor_ ||
   1564          ((this.propertyType() == PropertyType.Callbacks) &&
   1565           !this.hasGetter() && !this.hasSetter());
   1566 };
   1567 
   1568 
   1569 /**
   1570  * Mirror object for internal properties. Internal property reflects properties
   1571  * not accessible from user code such as [[BoundThis]] in bound function.
   1572  * Their names are merely symbolic.
   1573  * @param {string} name The name of the property
   1574  * @param {value} property value
   1575  * @constructor
   1576  * @extends Mirror
   1577  */
   1578 function InternalPropertyMirror(name, value) {
   1579   %_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror);
   1580   this.name_ = name;
   1581   this.value_ = value;
   1582 }
   1583 inherits(InternalPropertyMirror, Mirror);
   1584 
   1585 
   1586 InternalPropertyMirror.prototype.name = function() {
   1587   return this.name_;
   1588 };
   1589 
   1590 
   1591 InternalPropertyMirror.prototype.value = function() {
   1592   return MakeMirror(this.value_, false);
   1593 };
   1594 
   1595 
   1596 var kFrameDetailsFrameIdIndex = 0;
   1597 var kFrameDetailsReceiverIndex = 1;
   1598 var kFrameDetailsFunctionIndex = 2;
   1599 var kFrameDetailsArgumentCountIndex = 3;
   1600 var kFrameDetailsLocalCountIndex = 4;
   1601 var kFrameDetailsSourcePositionIndex = 5;
   1602 var kFrameDetailsConstructCallIndex = 6;
   1603 var kFrameDetailsAtReturnIndex = 7;
   1604 var kFrameDetailsFlagsIndex = 8;
   1605 var kFrameDetailsFirstDynamicIndex = 9;
   1606 
   1607 var kFrameDetailsNameIndex = 0;
   1608 var kFrameDetailsValueIndex = 1;
   1609 var kFrameDetailsNameValueSize = 2;
   1610 
   1611 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
   1612 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
   1613 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
   1614 
   1615 /**
   1616  * Wrapper for the frame details information retreived from the VM. The frame
   1617  * details from the VM is an array with the following content. See runtime.cc
   1618  * Runtime_GetFrameDetails.
   1619  *     0: Id
   1620  *     1: Receiver
   1621  *     2: Function
   1622  *     3: Argument count
   1623  *     4: Local count
   1624  *     5: Source position
   1625  *     6: Construct call
   1626  *     7: Is at return
   1627  *     8: Flags (debugger frame, optimized frame, inlined frame index)
   1628  *     Arguments name, value
   1629  *     Locals name, value
   1630  *     Return value if any
   1631  * @param {number} break_id Current break id
   1632  * @param {number} index Frame number
   1633  * @constructor
   1634  */
   1635 function FrameDetails(break_id, index) {
   1636   this.break_id_ = break_id;
   1637   this.details_ = %GetFrameDetails(break_id, index);
   1638 }
   1639 
   1640 
   1641 FrameDetails.prototype.frameId = function() {
   1642   %CheckExecutionState(this.break_id_);
   1643   return this.details_[kFrameDetailsFrameIdIndex];
   1644 };
   1645 
   1646 
   1647 FrameDetails.prototype.receiver = function() {
   1648   %CheckExecutionState(this.break_id_);
   1649   return this.details_[kFrameDetailsReceiverIndex];
   1650 };
   1651 
   1652 
   1653 FrameDetails.prototype.func = function() {
   1654   %CheckExecutionState(this.break_id_);
   1655   return this.details_[kFrameDetailsFunctionIndex];
   1656 };
   1657 
   1658 
   1659 FrameDetails.prototype.isConstructCall = function() {
   1660   %CheckExecutionState(this.break_id_);
   1661   return this.details_[kFrameDetailsConstructCallIndex];
   1662 };
   1663 
   1664 
   1665 FrameDetails.prototype.isAtReturn = function() {
   1666   %CheckExecutionState(this.break_id_);
   1667   return this.details_[kFrameDetailsAtReturnIndex];
   1668 };
   1669 
   1670 
   1671 FrameDetails.prototype.isDebuggerFrame = function() {
   1672   %CheckExecutionState(this.break_id_);
   1673   var f = kFrameDetailsFlagDebuggerFrameMask;
   1674   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
   1675 };
   1676 
   1677 
   1678 FrameDetails.prototype.isOptimizedFrame = function() {
   1679   %CheckExecutionState(this.break_id_);
   1680   var f = kFrameDetailsFlagOptimizedFrameMask;
   1681   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
   1682 };
   1683 
   1684 
   1685 FrameDetails.prototype.isInlinedFrame = function() {
   1686   return this.inlinedFrameIndex() > 0;
   1687 };
   1688 
   1689 
   1690 FrameDetails.prototype.inlinedFrameIndex = function() {
   1691   %CheckExecutionState(this.break_id_);
   1692   var f = kFrameDetailsFlagInlinedFrameIndexMask;
   1693   return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
   1694 };
   1695 
   1696 
   1697 FrameDetails.prototype.argumentCount = function() {
   1698   %CheckExecutionState(this.break_id_);
   1699   return this.details_[kFrameDetailsArgumentCountIndex];
   1700 };
   1701 
   1702 
   1703 FrameDetails.prototype.argumentName = function(index) {
   1704   %CheckExecutionState(this.break_id_);
   1705   if (index >= 0 && index < this.argumentCount()) {
   1706     return this.details_[kFrameDetailsFirstDynamicIndex +
   1707                          index * kFrameDetailsNameValueSize +
   1708                          kFrameDetailsNameIndex];
   1709   }
   1710 };
   1711 
   1712 
   1713 FrameDetails.prototype.argumentValue = function(index) {
   1714   %CheckExecutionState(this.break_id_);
   1715   if (index >= 0 && index < this.argumentCount()) {
   1716     return this.details_[kFrameDetailsFirstDynamicIndex +
   1717                          index * kFrameDetailsNameValueSize +
   1718                          kFrameDetailsValueIndex];
   1719   }
   1720 };
   1721 
   1722 
   1723 FrameDetails.prototype.localCount = function() {
   1724   %CheckExecutionState(this.break_id_);
   1725   return this.details_[kFrameDetailsLocalCountIndex];
   1726 };
   1727 
   1728 
   1729 FrameDetails.prototype.sourcePosition = function() {
   1730   %CheckExecutionState(this.break_id_);
   1731   return this.details_[kFrameDetailsSourcePositionIndex];
   1732 };
   1733 
   1734 
   1735 FrameDetails.prototype.localName = function(index) {
   1736   %CheckExecutionState(this.break_id_);
   1737   if (index >= 0 && index < this.localCount()) {
   1738     var locals_offset = kFrameDetailsFirstDynamicIndex +
   1739                         this.argumentCount() * kFrameDetailsNameValueSize;
   1740     return this.details_[locals_offset +
   1741                          index * kFrameDetailsNameValueSize +
   1742                          kFrameDetailsNameIndex];
   1743   }
   1744 };
   1745 
   1746 
   1747 FrameDetails.prototype.localValue = function(index) {
   1748   %CheckExecutionState(this.break_id_);
   1749   if (index >= 0 && index < this.localCount()) {
   1750     var locals_offset = kFrameDetailsFirstDynamicIndex +
   1751                         this.argumentCount() * kFrameDetailsNameValueSize;
   1752     return this.details_[locals_offset +
   1753                          index * kFrameDetailsNameValueSize +
   1754                          kFrameDetailsValueIndex];
   1755   }
   1756 };
   1757 
   1758 
   1759 FrameDetails.prototype.returnValue = function() {
   1760   %CheckExecutionState(this.break_id_);
   1761   var return_value_offset =
   1762       kFrameDetailsFirstDynamicIndex +
   1763       (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
   1764   if (this.details_[kFrameDetailsAtReturnIndex]) {
   1765     return this.details_[return_value_offset];
   1766   }
   1767 };
   1768 
   1769 
   1770 FrameDetails.prototype.scopeCount = function() {
   1771   if (IS_UNDEFINED(this.scopeCount_)) {
   1772     this.scopeCount_ = %GetScopeCount(this.break_id_, this.frameId());
   1773   }
   1774   return this.scopeCount_;
   1775 };
   1776 
   1777 
   1778 FrameDetails.prototype.stepInPositionsImpl = function() {
   1779   return %GetStepInPositions(this.break_id_, this.frameId());
   1780 };
   1781 
   1782 
   1783 /**
   1784  * Mirror object for stack frames.
   1785  * @param {number} break_id The break id in the VM for which this frame is
   1786        valid
   1787  * @param {number} index The frame index (top frame is index 0)
   1788  * @constructor
   1789  * @extends Mirror
   1790  */
   1791 function FrameMirror(break_id, index) {
   1792   %_CallFunction(this, FRAME_TYPE, Mirror);
   1793   this.break_id_ = break_id;
   1794   this.index_ = index;
   1795   this.details_ = new FrameDetails(break_id, index);
   1796 }
   1797 inherits(FrameMirror, Mirror);
   1798 
   1799 
   1800 FrameMirror.prototype.details = function() {
   1801   return this.details_;
   1802 };
   1803 
   1804 
   1805 FrameMirror.prototype.index = function() {
   1806   return this.index_;
   1807 };
   1808 
   1809 
   1810 FrameMirror.prototype.func = function() {
   1811   if (this.func_) {
   1812     return this.func_;
   1813   }
   1814 
   1815   // Get the function for this frame from the VM.
   1816   var f = this.details_.func();
   1817 
   1818   // Create a function mirror. NOTE: MakeMirror cannot be used here as the
   1819   // value returned from the VM might be a string if the function for the
   1820   // frame is unresolved.
   1821   if (IS_FUNCTION(f)) {
   1822     return this.func_ = MakeMirror(f);
   1823   } else {
   1824     return new UnresolvedFunctionMirror(f);
   1825   }
   1826 };
   1827 
   1828 
   1829 FrameMirror.prototype.receiver = function() {
   1830   return MakeMirror(this.details_.receiver());
   1831 };
   1832 
   1833 
   1834 FrameMirror.prototype.isConstructCall = function() {
   1835   return this.details_.isConstructCall();
   1836 };
   1837 
   1838 
   1839 FrameMirror.prototype.isAtReturn = function() {
   1840   return this.details_.isAtReturn();
   1841 };
   1842 
   1843 
   1844 FrameMirror.prototype.isDebuggerFrame = function() {
   1845   return this.details_.isDebuggerFrame();
   1846 };
   1847 
   1848 
   1849 FrameMirror.prototype.isOptimizedFrame = function() {
   1850   return this.details_.isOptimizedFrame();
   1851 };
   1852 
   1853 
   1854 FrameMirror.prototype.isInlinedFrame = function() {
   1855   return this.details_.isInlinedFrame();
   1856 };
   1857 
   1858 
   1859 FrameMirror.prototype.inlinedFrameIndex = function() {
   1860   return this.details_.inlinedFrameIndex();
   1861 };
   1862 
   1863 
   1864 FrameMirror.prototype.argumentCount = function() {
   1865   return this.details_.argumentCount();
   1866 };
   1867 
   1868 
   1869 FrameMirror.prototype.argumentName = function(index) {
   1870   return this.details_.argumentName(index);
   1871 };
   1872 
   1873 
   1874 FrameMirror.prototype.argumentValue = function(index) {
   1875   return MakeMirror(this.details_.argumentValue(index));
   1876 };
   1877 
   1878 
   1879 FrameMirror.prototype.localCount = function() {
   1880   return this.details_.localCount();
   1881 };
   1882 
   1883 
   1884 FrameMirror.prototype.localName = function(index) {
   1885   return this.details_.localName(index);
   1886 };
   1887 
   1888 
   1889 FrameMirror.prototype.localValue = function(index) {
   1890   return MakeMirror(this.details_.localValue(index));
   1891 };
   1892 
   1893 
   1894 FrameMirror.prototype.returnValue = function() {
   1895   return MakeMirror(this.details_.returnValue());
   1896 };
   1897 
   1898 
   1899 FrameMirror.prototype.sourcePosition = function() {
   1900   return this.details_.sourcePosition();
   1901 };
   1902 
   1903 
   1904 FrameMirror.prototype.sourceLocation = function() {
   1905   var func = this.func();
   1906   if (func.resolved()) {
   1907     var script = func.script();
   1908     if (script) {
   1909       return script.locationFromPosition(this.sourcePosition(), true);
   1910     }
   1911   }
   1912 };
   1913 
   1914 
   1915 FrameMirror.prototype.sourceLine = function() {
   1916   var location = this.sourceLocation();
   1917   if (location) {
   1918     return location.line;
   1919   }
   1920 };
   1921 
   1922 
   1923 FrameMirror.prototype.sourceColumn = function() {
   1924   var location = this.sourceLocation();
   1925   if (location) {
   1926     return location.column;
   1927   }
   1928 };
   1929 
   1930 
   1931 FrameMirror.prototype.sourceLineText = function() {
   1932   var location = this.sourceLocation();
   1933   if (location) {
   1934     return location.sourceText();
   1935   }
   1936 };
   1937 
   1938 
   1939 FrameMirror.prototype.scopeCount = function() {
   1940   return this.details_.scopeCount();
   1941 };
   1942 
   1943 
   1944 FrameMirror.prototype.scope = function(index) {
   1945   return new ScopeMirror(this, UNDEFINED, index);
   1946 };
   1947 
   1948 
   1949 FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) {
   1950   var scopeDetails = %GetAllScopesDetails(this.break_id_,
   1951                                           this.details_.frameId(),
   1952                                           this.details_.inlinedFrameIndex(),
   1953                                           !!opt_ignore_nested_scopes);
   1954   var result = [];
   1955   for (var i = 0; i < scopeDetails.length; ++i) {
   1956     result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
   1957   }
   1958   return result;
   1959 };
   1960 
   1961 
   1962 FrameMirror.prototype.stepInPositions = function() {
   1963   var script = this.func().script();
   1964   var funcOffset = this.func().sourcePosition_();
   1965 
   1966   var stepInRaw = this.details_.stepInPositionsImpl();
   1967   var result = [];
   1968   if (stepInRaw) {
   1969     for (var i = 0; i < stepInRaw.length; i++) {
   1970       var posStruct = {};
   1971       var offset = script.locationFromPosition(funcOffset + stepInRaw[i],
   1972                                                true);
   1973       serializeLocationFields(offset, posStruct);
   1974       var item = {
   1975         position: posStruct
   1976       };
   1977       result.push(item);
   1978     }
   1979   }
   1980 
   1981   return result;
   1982 };
   1983 
   1984 
   1985 FrameMirror.prototype.evaluate = function(source, disable_break,
   1986                                           opt_context_object) {
   1987   return MakeMirror(%DebugEvaluate(this.break_id_,
   1988                                    this.details_.frameId(),
   1989                                    this.details_.inlinedFrameIndex(),
   1990                                    source,
   1991                                    Boolean(disable_break),
   1992                                    opt_context_object));
   1993 };
   1994 
   1995 
   1996 FrameMirror.prototype.invocationText = function() {
   1997   // Format frame invoaction (receiver, function and arguments).
   1998   var result = '';
   1999   var func = this.func();
   2000   var receiver = this.receiver();
   2001   if (this.isConstructCall()) {
   2002     // For constructor frames display new followed by the function name.
   2003     result += 'new ';
   2004     result += func.name() ? func.name() : '[anonymous]';
   2005   } else if (this.isDebuggerFrame()) {
   2006     result += '[debugger]';
   2007   } else {
   2008     // If the receiver has a className which is 'global' don't display it.
   2009     var display_receiver =
   2010       !receiver.className || (receiver.className() != 'global');
   2011     if (display_receiver) {
   2012       result += receiver.toText();
   2013     }
   2014     // Try to find the function as a property in the receiver. Include the
   2015     // prototype chain in the lookup.
   2016     var property = GetUndefinedMirror();
   2017     if (receiver.isObject()) {
   2018       for (var r = receiver;
   2019            !r.isNull() && property.isUndefined();
   2020            r = r.protoObject()) {
   2021         property = r.lookupProperty(func);
   2022       }
   2023     }
   2024     if (!property.isUndefined()) {
   2025       // The function invoked was found on the receiver. Use the property name
   2026       // for the backtrace.
   2027       if (!property.isIndexed()) {
   2028         if (display_receiver) {
   2029           result += '.';
   2030         }
   2031         result += property.name();
   2032       } else {
   2033         result += '[';
   2034         result += property.name();
   2035         result += ']';
   2036       }
   2037       // Also known as - if the name in the function doesn't match the name
   2038       // under which it was looked up.
   2039       if (func.name() && func.name() != property.name()) {
   2040         result += '(aka ' + func.name() + ')';
   2041       }
   2042     } else {
   2043       // The function invoked was not found on the receiver. Use the function
   2044       // name if available for the backtrace.
   2045       if (display_receiver) {
   2046         result += '.';
   2047       }
   2048       result += func.name() ? func.name() : '[anonymous]';
   2049     }
   2050   }
   2051 
   2052   // Render arguments for normal frames.
   2053   if (!this.isDebuggerFrame()) {
   2054     result += '(';
   2055     for (var i = 0; i < this.argumentCount(); i++) {
   2056       if (i != 0) result += ', ';
   2057       if (this.argumentName(i)) {
   2058         result += this.argumentName(i);
   2059         result += '=';
   2060       }
   2061       result += this.argumentValue(i).toText();
   2062     }
   2063     result += ')';
   2064   }
   2065 
   2066   if (this.isAtReturn()) {
   2067     result += ' returning ';
   2068     result += this.returnValue().toText();
   2069   }
   2070 
   2071   return result;
   2072 };
   2073 
   2074 
   2075 FrameMirror.prototype.sourceAndPositionText = function() {
   2076   // Format source and position.
   2077   var result = '';
   2078   var func = this.func();
   2079   if (func.resolved()) {
   2080     var script = func.script();
   2081     if (script) {
   2082       if (script.name()) {
   2083         result += script.name();
   2084       } else {
   2085         result += '[unnamed]';
   2086       }
   2087       if (!this.isDebuggerFrame()) {
   2088         var location = this.sourceLocation();
   2089         result += ' line ';
   2090         result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
   2091         result += ' column ';
   2092         result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
   2093         if (!IS_UNDEFINED(this.sourcePosition())) {
   2094           result += ' (position ' + (this.sourcePosition() + 1) + ')';
   2095         }
   2096       }
   2097     } else {
   2098       result += '[no source]';
   2099     }
   2100   } else {
   2101     result += '[unresolved]';
   2102   }
   2103 
   2104   return result;
   2105 };
   2106 
   2107 
   2108 FrameMirror.prototype.localsText = function() {
   2109   // Format local variables.
   2110   var result = '';
   2111   var locals_count = this.localCount();
   2112   if (locals_count > 0) {
   2113     for (var i = 0; i < locals_count; ++i) {
   2114       result += '      var ';
   2115       result += this.localName(i);
   2116       result += ' = ';
   2117       result += this.localValue(i).toText();
   2118       if (i < locals_count - 1) result += '\n';
   2119     }
   2120   }
   2121 
   2122   return result;
   2123 };
   2124 
   2125 
   2126 FrameMirror.prototype.restart = function() {
   2127   var result = %LiveEditRestartFrame(this.break_id_, this.index_);
   2128   if (IS_UNDEFINED(result)) {
   2129     result = "Failed to find requested frame";
   2130   }
   2131   return result;
   2132 };
   2133 
   2134 
   2135 FrameMirror.prototype.toText = function(opt_locals) {
   2136   var result = '';
   2137   result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
   2138   result += ' ';
   2139   result += this.invocationText();
   2140   result += ' ';
   2141   result += this.sourceAndPositionText();
   2142   if (opt_locals) {
   2143     result += '\n';
   2144     result += this.localsText();
   2145   }
   2146   return result;
   2147 };
   2148 
   2149 
   2150 var kScopeDetailsTypeIndex = 0;
   2151 var kScopeDetailsObjectIndex = 1;
   2152 
   2153 function ScopeDetails(frame, fun, index, opt_details) {
   2154   if (frame) {
   2155     this.break_id_ = frame.break_id_;
   2156     this.details_ = opt_details ||
   2157                     %GetScopeDetails(frame.break_id_,
   2158                                      frame.details_.frameId(),
   2159                                      frame.details_.inlinedFrameIndex(),
   2160                                      index);
   2161     this.frame_id_ = frame.details_.frameId();
   2162     this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
   2163   } else {
   2164     this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index);
   2165     this.fun_value_ = fun.value();
   2166     this.break_id_ = undefined;
   2167   }
   2168   this.index_ = index;
   2169 }
   2170 
   2171 
   2172 ScopeDetails.prototype.type = function() {
   2173   if (!IS_UNDEFINED(this.break_id_)) {
   2174     %CheckExecutionState(this.break_id_);
   2175   }
   2176   return this.details_[kScopeDetailsTypeIndex];
   2177 };
   2178 
   2179 
   2180 ScopeDetails.prototype.object = function() {
   2181   if (!IS_UNDEFINED(this.break_id_)) {
   2182     %CheckExecutionState(this.break_id_);
   2183   }
   2184   return this.details_[kScopeDetailsObjectIndex];
   2185 };
   2186 
   2187 
   2188 ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
   2189   var raw_res;
   2190   if (!IS_UNDEFINED(this.break_id_)) {
   2191     %CheckExecutionState(this.break_id_);
   2192     raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_,
   2193         this.inlined_frame_id_, this.index_, name, new_value);
   2194   } else {
   2195     raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_,
   2196         name, new_value);
   2197   }
   2198   if (!raw_res) {
   2199     throw new Error("Failed to set variable value");
   2200   }
   2201 };
   2202 
   2203 
   2204 /**
   2205  * Mirror object for scope of frame or function. Either frame or function must
   2206  * be specified.
   2207  * @param {FrameMirror} frame The frame this scope is a part of
   2208  * @param {FunctionMirror} function The function this scope is a part of
   2209  * @param {number} index The scope index in the frame
   2210  * @param {Array=} opt_details Raw scope details data
   2211  * @constructor
   2212  * @extends Mirror
   2213  */
   2214 function ScopeMirror(frame, function, index, opt_details) {
   2215   %_CallFunction(this, SCOPE_TYPE, Mirror);
   2216   if (frame) {
   2217     this.frame_index_ = frame.index_;
   2218   } else {
   2219     this.frame_index_ = undefined;
   2220   }
   2221   this.scope_index_ = index;
   2222   this.details_ = new ScopeDetails(frame, function, index, opt_details);
   2223 }
   2224 inherits(ScopeMirror, Mirror);
   2225 
   2226 
   2227 ScopeMirror.prototype.details = function() {
   2228   return this.details_;
   2229 };
   2230 
   2231 
   2232 ScopeMirror.prototype.frameIndex = function() {
   2233   return this.frame_index_;
   2234 };
   2235 
   2236 
   2237 ScopeMirror.prototype.scopeIndex = function() {
   2238   return this.scope_index_;
   2239 };
   2240 
   2241 
   2242 ScopeMirror.prototype.scopeType = function() {
   2243   return this.details_.type();
   2244 };
   2245 
   2246 
   2247 ScopeMirror.prototype.scopeObject = function() {
   2248   // For local and closure scopes create a transient mirror as these objects are
   2249   // created on the fly materializing the local or closure scopes and
   2250   // therefore will not preserve identity.
   2251   var transient = this.scopeType() == ScopeType.Local ||
   2252                   this.scopeType() == ScopeType.Closure;
   2253   return MakeMirror(this.details_.object(), transient);
   2254 };
   2255 
   2256 
   2257 ScopeMirror.prototype.setVariableValue = function(name, new_value) {
   2258   this.details_.setVariableValueImpl(name, new_value);
   2259 };
   2260 
   2261 
   2262 /**
   2263  * Mirror object for script source.
   2264  * @param {Script} script The script object
   2265  * @constructor
   2266  * @extends Mirror
   2267  */
   2268 function ScriptMirror(script) {
   2269   %_CallFunction(this, SCRIPT_TYPE, Mirror);
   2270   this.script_ = script;
   2271   this.context_ = new ContextMirror(script.context_data);
   2272   this.allocateHandle_();
   2273 }
   2274 inherits(ScriptMirror, Mirror);
   2275 
   2276 
   2277 ScriptMirror.prototype.value = function() {
   2278   return this.script_;
   2279 };
   2280 
   2281 
   2282 ScriptMirror.prototype.name = function() {
   2283   return this.script_.name || this.script_.nameOrSourceURL();
   2284 };
   2285 
   2286 
   2287 ScriptMirror.prototype.id = function() {
   2288   return this.script_.id;
   2289 };
   2290 
   2291 
   2292 ScriptMirror.prototype.source = function() {
   2293   return this.script_.source;
   2294 };
   2295 
   2296 
   2297 ScriptMirror.prototype.setSource = function(source) {
   2298   %DebugSetScriptSource(this.script_, source);
   2299 };
   2300 
   2301 
   2302 ScriptMirror.prototype.lineOffset = function() {
   2303   return this.script_.line_offset;
   2304 };
   2305 
   2306 
   2307 ScriptMirror.prototype.columnOffset = function() {
   2308   return this.script_.column_offset;
   2309 };
   2310 
   2311 
   2312 ScriptMirror.prototype.data = function() {
   2313   return this.script_.data;
   2314 };
   2315 
   2316 
   2317 ScriptMirror.prototype.scriptType = function() {
   2318   return this.script_.type;
   2319 };
   2320 
   2321 
   2322 ScriptMirror.prototype.compilationType = function() {
   2323   return this.script_.compilation_type;
   2324 };
   2325 
   2326 
   2327 ScriptMirror.prototype.lineCount = function() {
   2328   return this.script_.lineCount();
   2329 };
   2330 
   2331 
   2332 ScriptMirror.prototype.locationFromPosition = function(
   2333     position, include_resource_offset) {
   2334   return this.script_.locationFromPosition(position, include_resource_offset);
   2335 };
   2336 
   2337 
   2338 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
   2339   return this.script_.sourceSlice(opt_from_line, opt_to_line);
   2340 };
   2341 
   2342 
   2343 ScriptMirror.prototype.context = function() {
   2344   return this.context_;
   2345 };
   2346 
   2347 
   2348 ScriptMirror.prototype.evalFromScript = function() {
   2349   return MakeMirror(this.script_.eval_from_script);
   2350 };
   2351 
   2352 
   2353 ScriptMirror.prototype.evalFromFunctionName = function() {
   2354   return MakeMirror(this.script_.eval_from_function_name);
   2355 };
   2356 
   2357 
   2358 ScriptMirror.prototype.evalFromLocation = function() {
   2359   var eval_from_script = this.evalFromScript();
   2360   if (!eval_from_script.isUndefined()) {
   2361     var position = this.script_.eval_from_script_position;
   2362     return eval_from_script.locationFromPosition(position, true);
   2363   }
   2364 };
   2365 
   2366 
   2367 ScriptMirror.prototype.toText = function() {
   2368   var result = '';
   2369   result += this.name();
   2370   result += ' (lines: ';
   2371   if (this.lineOffset() > 0) {
   2372     result += this.lineOffset();
   2373     result += '-';
   2374     result += this.lineOffset() + this.lineCount() - 1;
   2375   } else {
   2376     result += this.lineCount();
   2377   }
   2378   result += ')';
   2379   return result;
   2380 };
   2381 
   2382 
   2383 /**
   2384  * Mirror object for context.
   2385  * @param {Object} data The context data
   2386  * @constructor
   2387  * @extends Mirror
   2388  */
   2389 function ContextMirror(data) {
   2390   %_CallFunction(this, CONTEXT_TYPE, Mirror);
   2391   this.data_ = data;
   2392   this.allocateHandle_();
   2393 }
   2394 inherits(ContextMirror, Mirror);
   2395 
   2396 
   2397 ContextMirror.prototype.data = function() {
   2398   return this.data_;
   2399 };
   2400 
   2401 
   2402 /**
   2403  * Returns a mirror serializer
   2404  *
   2405  * @param {boolean} details Set to true to include details
   2406  * @param {Object} options Options comtrolling the serialization
   2407  *     The following options can be set:
   2408  *       includeSource: include ths full source of scripts
   2409  * @returns {MirrorSerializer} mirror serializer
   2410  */
   2411 function MakeMirrorSerializer(details, options) {
   2412   return new JSONProtocolSerializer(details, options);
   2413 }
   2414 
   2415 
   2416 /**
   2417  * Object for serializing a mirror objects and its direct references.
   2418  * @param {boolean} details Indicates whether to include details for the mirror
   2419  *     serialized
   2420  * @constructor
   2421  */
   2422 function JSONProtocolSerializer(details, options) {
   2423   this.details_ = details;
   2424   this.options_ = options;
   2425   this.mirrors_ = [ ];
   2426 }
   2427 
   2428 
   2429 /**
   2430  * Returns a serialization of an object reference. The referenced object are
   2431  * added to the serialization state.
   2432  *
   2433  * @param {Mirror} mirror The mirror to serialize
   2434  * @returns {String} JSON serialization
   2435  */
   2436 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
   2437   return this.serialize_(mirror, true, true);
   2438 };
   2439 
   2440 
   2441 /**
   2442  * Returns a serialization of an object value. The referenced objects are
   2443  * added to the serialization state.
   2444  *
   2445  * @param {Mirror} mirror The mirror to serialize
   2446  * @returns {String} JSON serialization
   2447  */
   2448 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
   2449   var json = this.serialize_(mirror, false, true);
   2450   return json;
   2451 };
   2452 
   2453 
   2454 /**
   2455  * Returns a serialization of all the objects referenced.
   2456  *
   2457  * @param {Mirror} mirror The mirror to serialize.
   2458  * @returns {Array.<Object>} Array of the referenced objects converted to
   2459  *     protcol objects.
   2460  */
   2461 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
   2462   // Collect the protocol representation of the referenced objects in an array.
   2463   var content = [];
   2464 
   2465   // Get the number of referenced objects.
   2466   var count = this.mirrors_.length;
   2467 
   2468   for (var i = 0; i < count; i++) {
   2469     content.push(this.serialize_(this.mirrors_[i], false, false));
   2470   }
   2471 
   2472   return content;
   2473 };
   2474 
   2475 
   2476 JSONProtocolSerializer.prototype.includeSource_ = function() {
   2477   return this.options_ && this.options_.includeSource;
   2478 };
   2479 
   2480 
   2481 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
   2482   return this.options_ && this.options_.inlineRefs;
   2483 };
   2484 
   2485 
   2486 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
   2487   if (IS_UNDEFINED(this.options_) ||
   2488       IS_UNDEFINED(this.options_.maxStringLength)) {
   2489     return kMaxProtocolStringLength;
   2490   }
   2491   return this.options_.maxStringLength;
   2492 };
   2493 
   2494 
   2495 JSONProtocolSerializer.prototype.add_ = function(mirror) {
   2496   // If this mirror is already in the list just return.
   2497   for (var i = 0; i < this.mirrors_.length; i++) {
   2498     if (this.mirrors_[i] === mirror) {
   2499       return;
   2500     }
   2501   }
   2502 
   2503   // Add the mirror to the list of mirrors to be serialized.
   2504   this.mirrors_.push(mirror);
   2505 };
   2506 
   2507 
   2508 /**
   2509  * Formats mirror object to protocol reference object with some data that can
   2510  * be used to display the value in debugger.
   2511  * @param {Mirror} mirror Mirror to serialize.
   2512  * @return {Object} Protocol reference object.
   2513  */
   2514 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
   2515     function(mirror) {
   2516   var o = {};
   2517   o.ref = mirror.handle();
   2518   o.type = mirror.type();
   2519   switch (mirror.type()) {
   2520     case UNDEFINED_TYPE:
   2521     case NULL_TYPE:
   2522     case BOOLEAN_TYPE:
   2523     case NUMBER_TYPE:
   2524       o.value = mirror.value();
   2525       break;
   2526     case STRING_TYPE:
   2527       o.value = mirror.getTruncatedValue(this.maxStringLength_());
   2528       break;
   2529     case SYMBOL_TYPE:
   2530       o.description = mirror.description();
   2531       break;
   2532     case FUNCTION_TYPE:
   2533       o.name = mirror.name();
   2534       o.inferredName = mirror.inferredName();
   2535       if (mirror.script()) {
   2536         o.scriptId = mirror.script().id();
   2537       }
   2538       break;
   2539     case ERROR_TYPE:
   2540     case REGEXP_TYPE:
   2541       o.value = mirror.toText();
   2542       break;
   2543     case OBJECT_TYPE:
   2544       o.className = mirror.className();
   2545       break;
   2546   }
   2547   return o;
   2548 };
   2549 
   2550 
   2551 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
   2552                                                        details) {
   2553   // If serializing a reference to a mirror just return the reference and add
   2554   // the mirror to the referenced mirrors.
   2555   if (reference &&
   2556       (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
   2557     if (this.inlineRefs_() && mirror.isValue()) {
   2558       return this.serializeReferenceWithDisplayData_(mirror);
   2559     } else {
   2560       this.add_(mirror);
   2561       return {'ref' : mirror.handle()};
   2562     }
   2563   }
   2564 
   2565   // Collect the JSON property/value pairs.
   2566   var content = {};
   2567 
   2568   // Add the mirror handle.
   2569   if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
   2570     content.handle = mirror.handle();
   2571   }
   2572 
   2573   // Always add the type.
   2574   content.type = mirror.type();
   2575 
   2576   switch (mirror.type()) {
   2577     case UNDEFINED_TYPE:
   2578     case NULL_TYPE:
   2579       // Undefined and null are represented just by their type.
   2580       break;
   2581 
   2582     case BOOLEAN_TYPE:
   2583       // Boolean values are simply represented by their value.
   2584       content.value = mirror.value();
   2585       break;
   2586 
   2587     case NUMBER_TYPE:
   2588       // Number values are simply represented by their value.
   2589       content.value = NumberToJSON_(mirror.value());
   2590       break;
   2591 
   2592     case STRING_TYPE:
   2593       // String values might have their value cropped to keep down size.
   2594       if (this.maxStringLength_() != -1 &&
   2595           mirror.length() > this.maxStringLength_()) {
   2596         var str = mirror.getTruncatedValue(this.maxStringLength_());
   2597         content.value = str;
   2598         content.fromIndex = 0;
   2599         content.toIndex = this.maxStringLength_();
   2600       } else {
   2601         content.value = mirror.value();
   2602       }
   2603       content.length = mirror.length();
   2604       break;
   2605 
   2606     case SYMBOL_TYPE:
   2607       content.description = mirror.description();
   2608       break;
   2609 
   2610     case OBJECT_TYPE:
   2611     case FUNCTION_TYPE:
   2612     case ERROR_TYPE:
   2613     case REGEXP_TYPE:
   2614     case PROMISE_TYPE:
   2615     case GENERATOR_TYPE:
   2616       // Add object representation.
   2617       this.serializeObject_(mirror, content, details);
   2618       break;
   2619 
   2620     case PROPERTY_TYPE:
   2621     case INTERNAL_PROPERTY_TYPE:
   2622       throw new Error('PropertyMirror cannot be serialized independently');
   2623       break;
   2624 
   2625     case FRAME_TYPE:
   2626       // Add object representation.
   2627       this.serializeFrame_(mirror, content);
   2628       break;
   2629 
   2630     case SCOPE_TYPE:
   2631       // Add object representation.
   2632       this.serializeScope_(mirror, content);
   2633       break;
   2634 
   2635     case SCRIPT_TYPE:
   2636       // Script is represented by id, name and source attributes.
   2637       if (mirror.name()) {
   2638         content.name = mirror.name();
   2639       }
   2640       content.id = mirror.id();
   2641       content.lineOffset = mirror.lineOffset();
   2642       content.columnOffset = mirror.columnOffset();
   2643       content.lineCount = mirror.lineCount();
   2644       if (mirror.data()) {
   2645         content.data = mirror.data();
   2646       }
   2647       if (this.includeSource_()) {
   2648         content.source = mirror.source();
   2649       } else {
   2650         var sourceStart = mirror.source().substring(0, 80);
   2651         content.sourceStart = sourceStart;
   2652       }
   2653       content.sourceLength = mirror.source().length;
   2654       content.scriptType = mirror.scriptType();
   2655       content.compilationType = mirror.compilationType();
   2656       // For compilation type eval emit information on the script from which
   2657       // eval was called if a script is present.
   2658       if (mirror.compilationType() == 1 &&
   2659           mirror.evalFromScript()) {
   2660         content.evalFromScript =
   2661             this.serializeReference(mirror.evalFromScript());
   2662         var evalFromLocation = mirror.evalFromLocation();
   2663         if (evalFromLocation) {
   2664           content.evalFromLocation = { line: evalFromLocation.line,
   2665                                        column: evalFromLocation.column };
   2666         }
   2667         if (mirror.evalFromFunctionName()) {
   2668           content.evalFromFunctionName = mirror.evalFromFunctionName();
   2669         }
   2670       }
   2671       if (mirror.context()) {
   2672         content.context = this.serializeReference(mirror.context());
   2673       }
   2674       break;
   2675 
   2676     case CONTEXT_TYPE:
   2677       content.data = mirror.data();
   2678       break;
   2679   }
   2680 
   2681   // Always add the text representation.
   2682   content.text = mirror.toText();
   2683 
   2684   // Create and return the JSON string.
   2685   return content;
   2686 };
   2687 
   2688 
   2689 /**
   2690  * Serialize object information to the following JSON format.
   2691  *
   2692  *   {"className":"<class name>",
   2693  *    "constructorFunction":{"ref":<number>},
   2694  *    "protoObject":{"ref":<number>},
   2695  *    "prototypeObject":{"ref":<number>},
   2696  *    "namedInterceptor":<boolean>,
   2697  *    "indexedInterceptor":<boolean>,
   2698  *    "properties":[<properties>],
   2699  *    "internalProperties":[<internal properties>]}
   2700  */
   2701 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
   2702                                                              details) {
   2703   // Add general object properties.
   2704   content.className = mirror.className();
   2705   content.constructorFunction =
   2706       this.serializeReference(mirror.constructorFunction());
   2707   content.protoObject = this.serializeReference(mirror.protoObject());
   2708   content.prototypeObject = this.serializeReference(mirror.prototypeObject());
   2709 
   2710   // Add flags to indicate whether there are interceptors.
   2711   if (mirror.hasNamedInterceptor()) {
   2712     content.namedInterceptor = true;
   2713   }
   2714   if (mirror.hasIndexedInterceptor()) {
   2715     content.indexedInterceptor = true;
   2716   }
   2717 
   2718   if (mirror.isFunction()) {
   2719     // Add function specific properties.
   2720     content.name = mirror.name();
   2721     if (!IS_UNDEFINED(mirror.inferredName())) {
   2722       content.inferredName = mirror.inferredName();
   2723     }
   2724     content.resolved = mirror.resolved();
   2725     if (mirror.resolved()) {
   2726       content.source = mirror.source();
   2727     }
   2728     if (mirror.script()) {
   2729       content.script = this.serializeReference(mirror.script());
   2730       content.scriptId = mirror.script().id();
   2731 
   2732       serializeLocationFields(mirror.sourceLocation(), content);
   2733     }
   2734 
   2735     content.scopes = [];
   2736     for (var i = 0; i < mirror.scopeCount(); i++) {
   2737       var scope = mirror.scope(i);
   2738       content.scopes.push({
   2739         type: scope.scopeType(),
   2740         index: i
   2741       });
   2742     }
   2743   }
   2744 
   2745   if (mirror.isGenerator()) {
   2746     // Add generator specific properties.
   2747 
   2748     // Either 'running', 'closed', or 'suspended'.
   2749     content.status = mirror.status();
   2750 
   2751     content.func = this.serializeReference(mirror.func())
   2752     content.receiver = this.serializeReference(mirror.receiver())
   2753 
   2754     // If the generator is suspended, the content add line/column properties.
   2755     serializeLocationFields(mirror.sourceLocation(), content);
   2756 
   2757     // TODO(wingo): Also serialize a reference to the context (scope chain).
   2758   }
   2759 
   2760   if (mirror.isDate()) {
   2761     // Add date specific properties.
   2762     content.value = mirror.value();
   2763   }
   2764 
   2765   if (mirror.isPromise()) {
   2766     // Add promise specific properties.
   2767     content.status = mirror.status();
   2768     content.promiseValue = this.serializeReference(mirror.promiseValue());
   2769   }
   2770 
   2771   // Add actual properties - named properties followed by indexed properties.
   2772   var propertyNames = mirror.propertyNames(PropertyKind.Named);
   2773   var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
   2774   var p = new Array(propertyNames.length + propertyIndexes.length);
   2775   for (var i = 0; i < propertyNames.length; i++) {
   2776     var propertyMirror = mirror.property(propertyNames[i]);
   2777     p[i] = this.serializeProperty_(propertyMirror);
   2778     if (details) {
   2779       this.add_(propertyMirror.value());
   2780     }
   2781   }
   2782   for (var i = 0; i < propertyIndexes.length; i++) {
   2783     var propertyMirror = mirror.property(propertyIndexes[i]);
   2784     p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
   2785     if (details) {
   2786       this.add_(propertyMirror.value());
   2787     }
   2788   }
   2789   content.properties = p;
   2790 
   2791   var internalProperties = mirror.internalProperties();
   2792   if (internalProperties.length > 0) {
   2793     var ip = [];
   2794     for (var i = 0; i < internalProperties.length; i++) {
   2795       ip.push(this.serializeInternalProperty_(internalProperties[i]));
   2796     }
   2797     content.internalProperties = ip;
   2798   }
   2799 };
   2800 
   2801 
   2802 /**
   2803  * Serialize location information to the following JSON format:
   2804  *
   2805  *   "position":"<position>",
   2806  *   "line":"<line>",
   2807  *   "column":"<column>",
   2808  *
   2809  * @param {SourceLocation} location The location to serialize, may be undefined.
   2810  */
   2811 function serializeLocationFields (location, content) {
   2812   if (!location) {
   2813     return;
   2814   }
   2815   content.position = location.position;
   2816   var line = location.line;
   2817   if (!IS_UNDEFINED(line)) {
   2818     content.line = line;
   2819   }
   2820   var column = location.column;
   2821   if (!IS_UNDEFINED(column)) {
   2822     content.column = column;
   2823   }
   2824 }
   2825 
   2826 
   2827 /**
   2828  * Serialize property information to the following JSON format for building the
   2829  * array of properties.
   2830  *
   2831  *   {"name":"<property name>",
   2832  *    "attributes":<number>,
   2833  *    "propertyType":<number>,
   2834  *    "ref":<number>}
   2835  *
   2836  * If the attribute for the property is PropertyAttribute.None it is not added.
   2837  * If the propertyType for the property is PropertyType.Normal it is not added.
   2838  * Here are a couple of examples.
   2839  *
   2840  *   {"name":"hello","ref":1}
   2841  *   {"name":"length","attributes":7,"propertyType":3,"ref":2}
   2842  *
   2843  * @param {PropertyMirror} propertyMirror The property to serialize.
   2844  * @returns {Object} Protocol object representing the property.
   2845  */
   2846 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
   2847   var result = {};
   2848 
   2849   result.name = propertyMirror.name();
   2850   var propertyValue = propertyMirror.value();
   2851   if (this.inlineRefs_() && propertyValue.isValue()) {
   2852     result.value = this.serializeReferenceWithDisplayData_(propertyValue);
   2853   } else {
   2854     if (propertyMirror.attributes() != PropertyAttribute.None) {
   2855       result.attributes = propertyMirror.attributes();
   2856     }
   2857     if (propertyMirror.propertyType() != PropertyType.Normal) {
   2858       result.propertyType = propertyMirror.propertyType();
   2859     }
   2860     result.ref = propertyValue.handle();
   2861   }
   2862   return result;
   2863 };
   2864 
   2865 
   2866 /**
   2867  * Serialize internal property information to the following JSON format for
   2868  * building the array of properties.
   2869  *
   2870  *   {"name":"<property name>",
   2871  *    "ref":<number>}
   2872  *
   2873  *   {"name":"[[BoundThis]]","ref":117}
   2874  *
   2875  * @param {InternalPropertyMirror} propertyMirror The property to serialize.
   2876  * @returns {Object} Protocol object representing the property.
   2877  */
   2878 JSONProtocolSerializer.prototype.serializeInternalProperty_ =
   2879     function(propertyMirror) {
   2880   var result = {};
   2881 
   2882   result.name = propertyMirror.name();
   2883   var propertyValue = propertyMirror.value();
   2884   if (this.inlineRefs_() && propertyValue.isValue()) {
   2885     result.value = this.serializeReferenceWithDisplayData_(propertyValue);
   2886   } else {
   2887     result.ref = propertyValue.handle();
   2888   }
   2889   return result;
   2890 };
   2891 
   2892 
   2893 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
   2894   content.index = mirror.index();
   2895   content.receiver = this.serializeReference(mirror.receiver());
   2896   var func = mirror.func();
   2897   content.func = this.serializeReference(func);
   2898   var script = func.script();
   2899   if (script) {
   2900     content.script = this.serializeReference(script);
   2901   }
   2902   content.constructCall = mirror.isConstructCall();
   2903   content.atReturn = mirror.isAtReturn();
   2904   if (mirror.isAtReturn()) {
   2905     content.returnValue = this.serializeReference(mirror.returnValue());
   2906   }
   2907   content.debuggerFrame = mirror.isDebuggerFrame();
   2908   var x = new Array(mirror.argumentCount());
   2909   for (var i = 0; i < mirror.argumentCount(); i++) {
   2910     var arg = {};
   2911     var argument_name = mirror.argumentName(i);
   2912     if (argument_name) {
   2913       arg.name = argument_name;
   2914     }
   2915     arg.value = this.serializeReference(mirror.argumentValue(i));
   2916     x[i] = arg;
   2917   }
   2918   content.arguments = x;
   2919   var x = new Array(mirror.localCount());
   2920   for (var i = 0; i < mirror.localCount(); i++) {
   2921     var local = {};
   2922     local.name = mirror.localName(i);
   2923     local.value = this.serializeReference(mirror.localValue(i));
   2924     x[i] = local;
   2925   }
   2926   content.locals = x;
   2927   serializeLocationFields(mirror.sourceLocation(), content);
   2928   var source_line_text = mirror.sourceLineText();
   2929   if (!IS_UNDEFINED(source_line_text)) {
   2930     content.sourceLineText = source_line_text;
   2931   }
   2932 
   2933   content.scopes = [];
   2934   for (var i = 0; i < mirror.scopeCount(); i++) {
   2935     var scope = mirror.scope(i);
   2936     content.scopes.push({
   2937       type: scope.scopeType(),
   2938       index: i
   2939     });
   2940   }
   2941 };
   2942 
   2943 
   2944 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
   2945   content.index = mirror.scopeIndex();
   2946   content.frameIndex = mirror.frameIndex();
   2947   content.type = mirror.scopeType();
   2948   content.object = this.inlineRefs_() ?
   2949                    this.serializeValue(mirror.scopeObject()) :
   2950                    this.serializeReference(mirror.scopeObject());
   2951 };
   2952 
   2953 
   2954 /**
   2955  * Convert a number to a protocol value. For all finite numbers the number
   2956  * itself is returned. For non finite numbers NaN, Infinite and
   2957  * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
   2958  * (not including the quotes) is returned.
   2959  *
   2960  * @param {number} value The number value to convert to a protocol value.
   2961  * @returns {number|string} Protocol value.
   2962  */
   2963 function NumberToJSON_(value) {
   2964   if (isNaN(value)) {
   2965     return 'NaN';
   2966   }
   2967   if (!NUMBER_IS_FINITE(value)) {
   2968     if (value > 0) {
   2969       return 'Infinity';
   2970     } else {
   2971       return '-Infinity';
   2972     }
   2973   }
   2974   return value;
   2975 }
   2976