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