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