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