[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / mirror-debugger.js
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 /**
600  * Return the primitive value if this is object of Boolean, Number or String
601  * type (but not Date). Otherwise return undefined.
602  */
603 ObjectMirror.prototype.primitiveValue = function() {
604   if (!IS_STRING_WRAPPER(this.value_) && !IS_NUMBER_WRAPPER(this.value_) &&
605       !IS_BOOLEAN_WRAPPER(this.value_)) {
606     return void 0;
607   }
608   var primitiveValue = %_ValueOf(this.value_);
609   if (IS_UNDEFINED(primitiveValue)) {
610     return void 0;
611   }
612   return MakeMirror(primitiveValue);
613 };
614
615
616 ObjectMirror.prototype.hasNamedInterceptor = function() {
617   // Get information on interceptors for this object.
618   var x = %GetInterceptorInfo(this.value_);
619   return (x & 2) != 0;
620 };
621
622
623 ObjectMirror.prototype.hasIndexedInterceptor = function() {
624   // Get information on interceptors for this object.
625   var x = %GetInterceptorInfo(this.value_);
626   return (x & 1) != 0;
627 };
628
629
630 /**
631  * Return the property names for this object.
632  * @param {number} kind Indicate whether named, indexed or both kinds of
633  *     properties are requested
634  * @param {number} limit Limit the number of names returend to the specified
635        value
636  * @return {Array} Property names for this object
637  */
638 ObjectMirror.prototype.propertyNames = function(kind, limit) {
639   // Find kind and limit and allocate array for the result
640   kind = kind || PropertyKind.Named | PropertyKind.Indexed;
641
642   var propertyNames;
643   var elementNames;
644   var total = 0;
645
646   // Find all the named properties.
647   if (kind & PropertyKind.Named) {
648     // Get the local property names.
649     propertyNames = %GetLocalPropertyNames(this.value_);
650     total += propertyNames.length;
651
652     // Get names for named interceptor properties if any.
653     if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
654       var namedInterceptorNames =
655           %GetNamedInterceptorPropertyNames(this.value_);
656       if (namedInterceptorNames) {
657         propertyNames = propertyNames.concat(namedInterceptorNames);
658         total += namedInterceptorNames.length;
659       }
660     }
661   }
662
663   // Find all the indexed properties.
664   if (kind & PropertyKind.Indexed) {
665     // Get the local element names.
666     elementNames = %GetLocalElementNames(this.value_);
667     total += elementNames.length;
668
669     // Get names for indexed interceptor properties.
670     if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
671       var indexedInterceptorNames =
672           %GetIndexedInterceptorElementNames(this.value_);
673       if (indexedInterceptorNames) {
674         elementNames = elementNames.concat(indexedInterceptorNames);
675         total += indexedInterceptorNames.length;
676       }
677     }
678   }
679   limit = Math.min(limit || total, total);
680
681   var names = new Array(limit);
682   var index = 0;
683
684   // Copy names for named properties.
685   if (kind & PropertyKind.Named) {
686     for (var i = 0; index < limit && i < propertyNames.length; i++) {
687       names[index++] = propertyNames[i];
688     }
689   }
690
691   // Copy names for indexed properties.
692   if (kind & PropertyKind.Indexed) {
693     for (var i = 0; index < limit && i < elementNames.length; i++) {
694       names[index++] = elementNames[i];
695     }
696   }
697
698   return names;
699 };
700
701
702 /**
703  * Return the properties for this object as an array of PropertyMirror objects.
704  * @param {number} kind Indicate whether named, indexed or both kinds of
705  *     properties are requested
706  * @param {number} limit Limit the number of properties returend to the
707        specified value
708  * @return {Array} Property mirrors for this object
709  */
710 ObjectMirror.prototype.properties = function(kind, limit) {
711   var names = this.propertyNames(kind, limit);
712   var properties = new Array(names.length);
713   for (var i = 0; i < names.length; i++) {
714     properties[i] = this.property(names[i]);
715   }
716
717   return properties;
718 };
719
720
721 ObjectMirror.prototype.property = function(name) {
722   var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
723   if (details) {
724     return new PropertyMirror(this, name, details);
725   }
726
727   // Nothing found.
728   return GetUndefinedMirror();
729 };
730
731
732
733 /**
734  * Try to find a property from its value.
735  * @param {Mirror} value The property value to look for
736  * @return {PropertyMirror} The property with the specified value. If no
737  *     property was found with the specified value UndefinedMirror is returned
738  */
739 ObjectMirror.prototype.lookupProperty = function(value) {
740   var properties = this.properties();
741
742   // Look for property value in properties.
743   for (var i = 0; i < properties.length; i++) {
744
745     // Skip properties which are defined through assessors.
746     var property = properties[i];
747     if (property.propertyType() != PropertyType.Callbacks) {
748       if (%_ObjectEquals(property.value_, value.value_)) {
749         return property;
750       }
751     }
752   }
753
754   // Nothing found.
755   return GetUndefinedMirror();
756 };
757
758
759 /**
760  * Returns objects which has direct references to this object
761  * @param {number} opt_max_objects Optional parameter specifying the maximum
762  *     number of referencing objects to return.
763  * @return {Array} The objects which has direct references to this object.
764  */
765 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
766   // Find all objects with direct references to this object.
767   var result = %DebugReferencedBy(this.value_,
768                                   Mirror.prototype, opt_max_objects || 0);
769
770   // Make mirrors for all the references found.
771   for (var i = 0; i < result.length; i++) {
772     result[i] = MakeMirror(result[i]);
773   }
774
775   return result;
776 };
777
778
779 ObjectMirror.prototype.toText = function() {
780   var name;
781   var ctor = this.constructorFunction();
782   if (!ctor.isFunction()) {
783     name = this.className();
784   } else {
785     name = ctor.name();
786     if (!name) {
787       name = this.className();
788     }
789   }
790   return '#<' + name + '>';
791 };
792
793
794 /**
795  * Mirror object for functions.
796  * @param {function} value The function object reflected by this mirror.
797  * @constructor
798  * @extends ObjectMirror
799  */
800 function FunctionMirror(value) {
801   %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
802   this.resolved_ = true;
803 }
804 inherits(FunctionMirror, ObjectMirror);
805
806
807 /**
808  * Returns whether the function is resolved.
809  * @return {boolean} True if the function is resolved. Unresolved functions can
810  *     only originate as functions from stack frames
811  */
812 FunctionMirror.prototype.resolved = function() {
813   return this.resolved_;
814 };
815
816
817 /**
818  * Returns the name of the function.
819  * @return {string} Name of the function
820  */
821 FunctionMirror.prototype.name = function() {
822   return %FunctionGetName(this.value_);
823 };
824
825
826 /**
827  * Returns the inferred name of the function.
828  * @return {string} Name of the function
829  */
830 FunctionMirror.prototype.inferredName = function() {
831   return %FunctionGetInferredName(this.value_);
832 };
833
834
835 /**
836  * Returns the source code for the function.
837  * @return {string or undefined} The source code for the function. If the
838  *     function is not resolved undefined will be returned.
839  */
840 FunctionMirror.prototype.source = function() {
841   // Return source if function is resolved. Otherwise just fall through to
842   // return undefined.
843   if (this.resolved()) {
844     return builtins.FunctionSourceString(this.value_);
845   }
846 };
847
848
849 /**
850  * Returns the script object for the function.
851  * @return {ScriptMirror or undefined} Script object for the function or
852  *     undefined if the function has no script
853  */
854 FunctionMirror.prototype.script = function() {
855   // Return script if function is resolved. Otherwise just fall through
856   // to return undefined.
857   if (this.resolved()) {
858     var script = %FunctionGetScript(this.value_);
859     if (script) {
860       return MakeMirror(script);
861     }
862   }
863 };
864
865
866 /**
867  * Returns the script source position for the function. Only makes sense
868  * for functions which has a script defined.
869  * @return {Number or undefined} in-script position for the function
870  */
871 FunctionMirror.prototype.sourcePosition_ = function() {
872   // Return script if function is resolved. Otherwise just fall through
873   // to return undefined.
874   if (this.resolved()) {
875     return %FunctionGetScriptSourcePosition(this.value_);
876   }
877 };
878
879
880 /**
881  * Returns the script source location object for the function. Only makes sense
882  * for functions which has a script defined.
883  * @return {Location or undefined} in-script location for the function begin
884  */
885 FunctionMirror.prototype.sourceLocation = function() {
886   if (this.resolved() && this.script()) {
887     return this.script().locationFromPosition(this.sourcePosition_(),
888                                               true);
889   }
890 };
891
892
893 /**
894  * Returns objects constructed by this function.
895  * @param {number} opt_max_instances Optional parameter specifying the maximum
896  *     number of instances to return.
897  * @return {Array or undefined} The objects constructed by this function.
898  */
899 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
900   if (this.resolved()) {
901     // Find all objects constructed from this function.
902     var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
903
904     // Make mirrors for all the instances found.
905     for (var i = 0; i < result.length; i++) {
906       result[i] = MakeMirror(result[i]);
907     }
908
909     return result;
910   } else {
911     return [];
912   }
913 };
914
915
916 FunctionMirror.prototype.scopeCount = function() {
917   if (this.resolved()) {
918     return %GetFunctionScopeCount(this.value());
919   } else {
920     return 0;
921   }
922 };
923
924
925 FunctionMirror.prototype.scope = function(index) {
926   if (this.resolved()) {
927     return new ScopeMirror(void 0, this, index);
928   }
929 };
930
931
932 FunctionMirror.prototype.toText = function() {
933   return this.source();
934 };
935
936
937 /**
938  * Mirror object for unresolved functions.
939  * @param {string} value The name for the unresolved function reflected by this
940  *     mirror.
941  * @constructor
942  * @extends ObjectMirror
943  */
944 function UnresolvedFunctionMirror(value) {
945   // Construct this using the ValueMirror as an unresolved function is not a
946   // real object but just a string.
947   %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
948   this.propertyCount_ = 0;
949   this.elementCount_ = 0;
950   this.resolved_ = false;
951 }
952 inherits(UnresolvedFunctionMirror, FunctionMirror);
953
954
955 UnresolvedFunctionMirror.prototype.className = function() {
956   return 'Function';
957 };
958
959
960 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
961   return GetUndefinedMirror();
962 };
963
964
965 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
966   return GetUndefinedMirror();
967 };
968
969
970 UnresolvedFunctionMirror.prototype.protoObject = function() {
971   return GetUndefinedMirror();
972 };
973
974
975 UnresolvedFunctionMirror.prototype.name = function() {
976   return this.value_;
977 };
978
979
980 UnresolvedFunctionMirror.prototype.inferredName = function() {
981   return undefined;
982 };
983
984
985 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
986   return [];
987 };
988
989
990 /**
991  * Mirror object for arrays.
992  * @param {Array} value The Array object reflected by this mirror
993  * @constructor
994  * @extends ObjectMirror
995  */
996 function ArrayMirror(value) {
997   %_CallFunction(this, value, ObjectMirror);
998 }
999 inherits(ArrayMirror, ObjectMirror);
1000
1001
1002 ArrayMirror.prototype.length = function() {
1003   return this.value_.length;
1004 };
1005
1006
1007 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
1008                                                             opt_to_index) {
1009   var from_index = opt_from_index || 0;
1010   var to_index = opt_to_index || this.length() - 1;
1011   if (from_index > to_index) return new Array();
1012   var values = new Array(to_index - from_index + 1);
1013   for (var i = from_index; i <= to_index; i++) {
1014     var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
1015     var value;
1016     if (details) {
1017       value = new PropertyMirror(this, i, details);
1018     } else {
1019       value = GetUndefinedMirror();
1020     }
1021     values[i - from_index] = value;
1022   }
1023   return values;
1024 };
1025
1026
1027 /**
1028  * Mirror object for dates.
1029  * @param {Date} value The Date object reflected by this mirror
1030  * @constructor
1031  * @extends ObjectMirror
1032  */
1033 function DateMirror(value) {
1034   %_CallFunction(this, value, ObjectMirror);
1035 }
1036 inherits(DateMirror, ObjectMirror);
1037
1038
1039 DateMirror.prototype.toText = function() {
1040   var s = JSON.stringify(this.value_);
1041   return s.substring(1, s.length - 1);  // cut quotes
1042 };
1043
1044
1045 /**
1046  * Mirror object for regular expressions.
1047  * @param {RegExp} value The RegExp object reflected by this mirror
1048  * @constructor
1049  * @extends ObjectMirror
1050  */
1051 function RegExpMirror(value) {
1052   %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
1053 }
1054 inherits(RegExpMirror, ObjectMirror);
1055
1056
1057 /**
1058  * Returns the source to the regular expression.
1059  * @return {string or undefined} The source to the regular expression
1060  */
1061 RegExpMirror.prototype.source = function() {
1062   return this.value_.source;
1063 };
1064
1065
1066 /**
1067  * Returns whether this regular expression has the global (g) flag set.
1068  * @return {boolean} Value of the global flag
1069  */
1070 RegExpMirror.prototype.global = function() {
1071   return this.value_.global;
1072 };
1073
1074
1075 /**
1076  * Returns whether this regular expression has the ignore case (i) flag set.
1077  * @return {boolean} Value of the ignore case flag
1078  */
1079 RegExpMirror.prototype.ignoreCase = function() {
1080   return this.value_.ignoreCase;
1081 };
1082
1083
1084 /**
1085  * Returns whether this regular expression has the multiline (m) flag set.
1086  * @return {boolean} Value of the multiline flag
1087  */
1088 RegExpMirror.prototype.multiline = function() {
1089   return this.value_.multiline;
1090 };
1091
1092
1093 RegExpMirror.prototype.toText = function() {
1094   // Simpel to text which is used when on specialization in subclass.
1095   return "/" + this.source() + "/";
1096 };
1097
1098
1099 /**
1100  * Mirror object for error objects.
1101  * @param {Error} value The error object reflected by this mirror
1102  * @constructor
1103  * @extends ObjectMirror
1104  */
1105 function ErrorMirror(value) {
1106   %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
1107 }
1108 inherits(ErrorMirror, ObjectMirror);
1109
1110
1111 /**
1112  * Returns the message for this eror object.
1113  * @return {string or undefined} The message for this eror object
1114  */
1115 ErrorMirror.prototype.message = function() {
1116   return this.value_.message;
1117 };
1118
1119
1120 ErrorMirror.prototype.toText = function() {
1121   // Use the same text representation as in messages.js.
1122   var text;
1123   try {
1124     str = %_CallFunction(this.value_, builtins.ErrorToString);
1125   } catch (e) {
1126     str = '#<Error>';
1127   }
1128   return str;
1129 };
1130
1131
1132 /**
1133  * Base mirror object for properties.
1134  * @param {ObjectMirror} mirror The mirror object having this property
1135  * @param {string} name The name of the property
1136  * @param {Array} details Details about the property
1137  * @constructor
1138  * @extends Mirror
1139  */
1140 function PropertyMirror(mirror, name, details) {
1141   %_CallFunction(this, PROPERTY_TYPE, Mirror);
1142   this.mirror_ = mirror;
1143   this.name_ = name;
1144   this.value_ = details[0];
1145   this.details_ = details[1];
1146   if (details.length > 2) {
1147     this.exception_ = details[2];
1148     this.getter_ = details[3];
1149     this.setter_ = details[4];
1150   }
1151 }
1152 inherits(PropertyMirror, Mirror);
1153
1154
1155 PropertyMirror.prototype.isReadOnly = function() {
1156   return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1157 };
1158
1159
1160 PropertyMirror.prototype.isEnum = function() {
1161   return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1162 };
1163
1164
1165 PropertyMirror.prototype.canDelete = function() {
1166   return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1167 };
1168
1169
1170 PropertyMirror.prototype.name = function() {
1171   return this.name_;
1172 };
1173
1174
1175 PropertyMirror.prototype.isIndexed = function() {
1176   for (var i = 0; i < this.name_.length; i++) {
1177     if (this.name_[i] < '0' || '9' < this.name_[i]) {
1178       return false;
1179     }
1180   }
1181   return true;
1182 };
1183
1184
1185 PropertyMirror.prototype.value = function() {
1186   return MakeMirror(this.value_, false);
1187 };
1188
1189
1190 /**
1191  * Returns whether this property value is an exception.
1192  * @return {booolean} True if this property value is an exception
1193  */
1194 PropertyMirror.prototype.isException = function() {
1195   return this.exception_ ? true : false;
1196 };
1197
1198
1199 PropertyMirror.prototype.attributes = function() {
1200   return %DebugPropertyAttributesFromDetails(this.details_);
1201 };
1202
1203
1204 PropertyMirror.prototype.propertyType = function() {
1205   return %DebugPropertyTypeFromDetails(this.details_);
1206 };
1207
1208
1209 PropertyMirror.prototype.insertionIndex = function() {
1210   return %DebugPropertyIndexFromDetails(this.details_);
1211 };
1212
1213
1214 /**
1215  * Returns whether this property has a getter defined through __defineGetter__.
1216  * @return {booolean} True if this property has a getter
1217  */
1218 PropertyMirror.prototype.hasGetter = function() {
1219   return this.getter_ ? true : false;
1220 };
1221
1222
1223 /**
1224  * Returns whether this property has a setter defined through __defineSetter__.
1225  * @return {booolean} True if this property has a setter
1226  */
1227 PropertyMirror.prototype.hasSetter = function() {
1228   return this.setter_ ? true : false;
1229 };
1230
1231
1232 /**
1233  * Returns the getter for this property defined through __defineGetter__.
1234  * @return {Mirror} FunctionMirror reflecting the getter function or
1235  *     UndefinedMirror if there is no getter for this property
1236  */
1237 PropertyMirror.prototype.getter = function() {
1238   if (this.hasGetter()) {
1239     return MakeMirror(this.getter_);
1240   } else {
1241     return GetUndefinedMirror();
1242   }
1243 };
1244
1245
1246 /**
1247  * Returns the setter for this property defined through __defineSetter__.
1248  * @return {Mirror} FunctionMirror reflecting the setter function or
1249  *     UndefinedMirror if there is no setter for this property
1250  */
1251 PropertyMirror.prototype.setter = function() {
1252   if (this.hasSetter()) {
1253     return MakeMirror(this.setter_);
1254   } else {
1255     return GetUndefinedMirror();
1256   }
1257 };
1258
1259
1260 /**
1261  * Returns whether this property is natively implemented by the host or a set
1262  * through JavaScript code.
1263  * @return {boolean} True if the property is
1264  *     UndefinedMirror if there is no setter for this property
1265  */
1266 PropertyMirror.prototype.isNative = function() {
1267   return (this.propertyType() == PropertyType.Interceptor) ||
1268          ((this.propertyType() == PropertyType.Callbacks) &&
1269           !this.hasGetter() && !this.hasSetter());
1270 };
1271
1272
1273 var kFrameDetailsFrameIdIndex = 0;
1274 var kFrameDetailsReceiverIndex = 1;
1275 var kFrameDetailsFunctionIndex = 2;
1276 var kFrameDetailsArgumentCountIndex = 3;
1277 var kFrameDetailsLocalCountIndex = 4;
1278 var kFrameDetailsSourcePositionIndex = 5;
1279 var kFrameDetailsConstructCallIndex = 6;
1280 var kFrameDetailsAtReturnIndex = 7;
1281 var kFrameDetailsFlagsIndex = 8;
1282 var kFrameDetailsFirstDynamicIndex = 9;
1283
1284 var kFrameDetailsNameIndex = 0;
1285 var kFrameDetailsValueIndex = 1;
1286 var kFrameDetailsNameValueSize = 2;
1287
1288 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1289 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1290 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
1291
1292 /**
1293  * Wrapper for the frame details information retreived from the VM. The frame
1294  * details from the VM is an array with the following content. See runtime.cc
1295  * Runtime_GetFrameDetails.
1296  *     0: Id
1297  *     1: Receiver
1298  *     2: Function
1299  *     3: Argument count
1300  *     4: Local count
1301  *     5: Source position
1302  *     6: Construct call
1303  *     7: Is at return
1304  *     8: Flags (debugger frame, optimized frame, inlined frame index)
1305  *     Arguments name, value
1306  *     Locals name, value
1307  *     Return value if any
1308  * @param {number} break_id Current break id
1309  * @param {number} index Frame number
1310  * @constructor
1311  */
1312 function FrameDetails(break_id, index) {
1313   this.break_id_ = break_id;
1314   this.details_ = %GetFrameDetails(break_id, index);
1315 }
1316
1317
1318 FrameDetails.prototype.frameId = function() {
1319   %CheckExecutionState(this.break_id_);
1320   return this.details_[kFrameDetailsFrameIdIndex];
1321 };
1322
1323
1324 FrameDetails.prototype.receiver = function() {
1325   %CheckExecutionState(this.break_id_);
1326   return this.details_[kFrameDetailsReceiverIndex];
1327 };
1328
1329
1330 FrameDetails.prototype.func = function() {
1331   %CheckExecutionState(this.break_id_);
1332   return this.details_[kFrameDetailsFunctionIndex];
1333 };
1334
1335
1336 FrameDetails.prototype.isConstructCall = function() {
1337   %CheckExecutionState(this.break_id_);
1338   return this.details_[kFrameDetailsConstructCallIndex];
1339 };
1340
1341
1342 FrameDetails.prototype.isAtReturn = function() {
1343   %CheckExecutionState(this.break_id_);
1344   return this.details_[kFrameDetailsAtReturnIndex];
1345 };
1346
1347
1348 FrameDetails.prototype.isDebuggerFrame = function() {
1349   %CheckExecutionState(this.break_id_);
1350   var f = kFrameDetailsFlagDebuggerFrameMask;
1351   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1352 };
1353
1354
1355 FrameDetails.prototype.isOptimizedFrame = function() {
1356   %CheckExecutionState(this.break_id_);
1357   var f = kFrameDetailsFlagOptimizedFrameMask;
1358   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1359 };
1360
1361
1362 FrameDetails.prototype.isInlinedFrame = function() {
1363   return this.inlinedFrameIndex() > 0;
1364 };
1365
1366
1367 FrameDetails.prototype.inlinedFrameIndex = function() {
1368   %CheckExecutionState(this.break_id_);
1369   var f = kFrameDetailsFlagInlinedFrameIndexMask;
1370   return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
1371 };
1372
1373
1374 FrameDetails.prototype.argumentCount = function() {
1375   %CheckExecutionState(this.break_id_);
1376   return this.details_[kFrameDetailsArgumentCountIndex];
1377 };
1378
1379
1380 FrameDetails.prototype.argumentName = function(index) {
1381   %CheckExecutionState(this.break_id_);
1382   if (index >= 0 && index < this.argumentCount()) {
1383     return this.details_[kFrameDetailsFirstDynamicIndex +
1384                          index * kFrameDetailsNameValueSize +
1385                          kFrameDetailsNameIndex];
1386   }
1387 };
1388
1389
1390 FrameDetails.prototype.argumentValue = function(index) {
1391   %CheckExecutionState(this.break_id_);
1392   if (index >= 0 && index < this.argumentCount()) {
1393     return this.details_[kFrameDetailsFirstDynamicIndex +
1394                          index * kFrameDetailsNameValueSize +
1395                          kFrameDetailsValueIndex];
1396   }
1397 };
1398
1399
1400 FrameDetails.prototype.localCount = function() {
1401   %CheckExecutionState(this.break_id_);
1402   return this.details_[kFrameDetailsLocalCountIndex];
1403 };
1404
1405
1406 FrameDetails.prototype.sourcePosition = function() {
1407   %CheckExecutionState(this.break_id_);
1408   return this.details_[kFrameDetailsSourcePositionIndex];
1409 };
1410
1411
1412 FrameDetails.prototype.localName = function(index) {
1413   %CheckExecutionState(this.break_id_);
1414   if (index >= 0 && index < this.localCount()) {
1415     var locals_offset = kFrameDetailsFirstDynamicIndex +
1416                         this.argumentCount() * kFrameDetailsNameValueSize;
1417     return this.details_[locals_offset +
1418                          index * kFrameDetailsNameValueSize +
1419                          kFrameDetailsNameIndex];
1420   }
1421 };
1422
1423
1424 FrameDetails.prototype.localValue = function(index) {
1425   %CheckExecutionState(this.break_id_);
1426   if (index >= 0 && index < this.localCount()) {
1427     var locals_offset = kFrameDetailsFirstDynamicIndex +
1428                         this.argumentCount() * kFrameDetailsNameValueSize;
1429     return this.details_[locals_offset +
1430                          index * kFrameDetailsNameValueSize +
1431                          kFrameDetailsValueIndex];
1432   }
1433 };
1434
1435
1436 FrameDetails.prototype.returnValue = function() {
1437   %CheckExecutionState(this.break_id_);
1438   var return_value_offset =
1439       kFrameDetailsFirstDynamicIndex +
1440       (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1441   if (this.details_[kFrameDetailsAtReturnIndex]) {
1442     return this.details_[return_value_offset];
1443   }
1444 };
1445
1446
1447 FrameDetails.prototype.scopeCount = function() {
1448   return %GetScopeCount(this.break_id_, this.frameId());
1449 };
1450
1451
1452 /**
1453  * Mirror object for stack frames.
1454  * @param {number} break_id The break id in the VM for which this frame is
1455        valid
1456  * @param {number} index The frame index (top frame is index 0)
1457  * @constructor
1458  * @extends Mirror
1459  */
1460 function FrameMirror(break_id, index) {
1461   %_CallFunction(this, FRAME_TYPE, Mirror);
1462   this.break_id_ = break_id;
1463   this.index_ = index;
1464   this.details_ = new FrameDetails(break_id, index);
1465 }
1466 inherits(FrameMirror, Mirror);
1467
1468
1469 FrameMirror.prototype.index = function() {
1470   return this.index_;
1471 };
1472
1473
1474 FrameMirror.prototype.func = function() {
1475   // Get the function for this frame from the VM.
1476   var f = this.details_.func();
1477
1478   // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1479   // value returned from the VM might be a string if the function for the
1480   // frame is unresolved.
1481   if (IS_FUNCTION(f)) {
1482     return MakeMirror(f);
1483   } else {
1484     return new UnresolvedFunctionMirror(f);
1485   }
1486 };
1487
1488
1489 FrameMirror.prototype.receiver = function() {
1490   return MakeMirror(this.details_.receiver());
1491 };
1492
1493
1494 FrameMirror.prototype.isConstructCall = function() {
1495   return this.details_.isConstructCall();
1496 };
1497
1498
1499 FrameMirror.prototype.isAtReturn = function() {
1500   return this.details_.isAtReturn();
1501 };
1502
1503
1504 FrameMirror.prototype.isDebuggerFrame = function() {
1505   return this.details_.isDebuggerFrame();
1506 };
1507
1508
1509 FrameMirror.prototype.isOptimizedFrame = function() {
1510   return this.details_.isOptimizedFrame();
1511 };
1512
1513
1514 FrameMirror.prototype.isInlinedFrame = function() {
1515   return this.details_.isInlinedFrame();
1516 };
1517
1518
1519 FrameMirror.prototype.inlinedFrameIndex = function() {
1520   return this.details_.inlinedFrameIndex();
1521 };
1522
1523
1524 FrameMirror.prototype.argumentCount = function() {
1525   return this.details_.argumentCount();
1526 };
1527
1528
1529 FrameMirror.prototype.argumentName = function(index) {
1530   return this.details_.argumentName(index);
1531 };
1532
1533
1534 FrameMirror.prototype.argumentValue = function(index) {
1535   return MakeMirror(this.details_.argumentValue(index));
1536 };
1537
1538
1539 FrameMirror.prototype.localCount = function() {
1540   return this.details_.localCount();
1541 };
1542
1543
1544 FrameMirror.prototype.localName = function(index) {
1545   return this.details_.localName(index);
1546 };
1547
1548
1549 FrameMirror.prototype.localValue = function(index) {
1550   return MakeMirror(this.details_.localValue(index));
1551 };
1552
1553
1554 FrameMirror.prototype.returnValue = function() {
1555   return MakeMirror(this.details_.returnValue());
1556 };
1557
1558
1559 FrameMirror.prototype.sourcePosition = function() {
1560   return this.details_.sourcePosition();
1561 };
1562
1563
1564 FrameMirror.prototype.sourceLocation = function() {
1565   if (this.func().resolved() && this.func().script()) {
1566     return this.func().script().locationFromPosition(this.sourcePosition(),
1567                                                      true);
1568   }
1569 };
1570
1571
1572 FrameMirror.prototype.sourceLine = function() {
1573   if (this.func().resolved()) {
1574     var location = this.sourceLocation();
1575     if (location) {
1576       return location.line;
1577     }
1578   }
1579 };
1580
1581
1582 FrameMirror.prototype.sourceColumn = function() {
1583   if (this.func().resolved()) {
1584     var location = this.sourceLocation();
1585     if (location) {
1586       return location.column;
1587     }
1588   }
1589 };
1590
1591
1592 FrameMirror.prototype.sourceLineText = function() {
1593   if (this.func().resolved()) {
1594     var location = this.sourceLocation();
1595     if (location) {
1596       return location.sourceText();
1597     }
1598   }
1599 };
1600
1601
1602 FrameMirror.prototype.scopeCount = function() {
1603   return this.details_.scopeCount();
1604 };
1605
1606
1607 FrameMirror.prototype.scope = function(index) {
1608   return new ScopeMirror(this, void 0, index);
1609 };
1610
1611
1612 FrameMirror.prototype.evaluate = function(source, disable_break,
1613                                           opt_context_object) {
1614   var result = %DebugEvaluate(this.break_id_,
1615                               this.details_.frameId(),
1616                               this.details_.inlinedFrameIndex(),
1617                               source,
1618                               Boolean(disable_break),
1619                               opt_context_object);
1620   return MakeMirror(result);
1621 };
1622
1623
1624 FrameMirror.prototype.invocationText = function() {
1625   // Format frame invoaction (receiver, function and arguments).
1626   var result = '';
1627   var func = this.func();
1628   var receiver = this.receiver();
1629   if (this.isConstructCall()) {
1630     // For constructor frames display new followed by the function name.
1631     result += 'new ';
1632     result += func.name() ? func.name() : '[anonymous]';
1633   } else if (this.isDebuggerFrame()) {
1634     result += '[debugger]';
1635   } else {
1636     // If the receiver has a className which is 'global' don't display it.
1637     var display_receiver =
1638       !receiver.className || (receiver.className() != 'global');
1639     if (display_receiver) {
1640       result += receiver.toText();
1641     }
1642     // Try to find the function as a property in the receiver. Include the
1643     // prototype chain in the lookup.
1644     var property = GetUndefinedMirror();
1645     if (receiver.isObject()) {
1646       for (var r = receiver;
1647            !r.isNull() && property.isUndefined();
1648            r = r.protoObject()) {
1649         property = r.lookupProperty(func);
1650       }
1651     }
1652     if (!property.isUndefined()) {
1653       // The function invoked was found on the receiver. Use the property name
1654       // for the backtrace.
1655       if (!property.isIndexed()) {
1656         if (display_receiver) {
1657           result += '.';
1658         }
1659         result += property.name();
1660       } else {
1661         result += '[';
1662         result += property.name();
1663         result += ']';
1664       }
1665       // Also known as - if the name in the function doesn't match the name
1666       // under which it was looked up.
1667       if (func.name() && func.name() != property.name()) {
1668         result += '(aka ' + func.name() + ')';
1669       }
1670     } else {
1671       // The function invoked was not found on the receiver. Use the function
1672       // name if available for the backtrace.
1673       if (display_receiver) {
1674         result += '.';
1675       }
1676       result += func.name() ? func.name() : '[anonymous]';
1677     }
1678   }
1679
1680   // Render arguments for normal frames.
1681   if (!this.isDebuggerFrame()) {
1682     result += '(';
1683     for (var i = 0; i < this.argumentCount(); i++) {
1684       if (i != 0) result += ', ';
1685       if (this.argumentName(i)) {
1686         result += this.argumentName(i);
1687         result += '=';
1688       }
1689       result += this.argumentValue(i).toText();
1690     }
1691     result += ')';
1692   }
1693
1694   if (this.isAtReturn()) {
1695     result += ' returning ';
1696     result += this.returnValue().toText();
1697   }
1698
1699   return result;
1700 };
1701
1702
1703 FrameMirror.prototype.sourceAndPositionText = function() {
1704   // Format source and position.
1705   var result = '';
1706   var func = this.func();
1707   if (func.resolved()) {
1708     if (func.script()) {
1709       if (func.script().name()) {
1710         result += func.script().name();
1711       } else {
1712         result += '[unnamed]';
1713       }
1714       if (!this.isDebuggerFrame()) {
1715         var location = this.sourceLocation();
1716         result += ' line ';
1717         result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1718         result += ' column ';
1719         result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1720         if (!IS_UNDEFINED(this.sourcePosition())) {
1721           result += ' (position ' + (this.sourcePosition() + 1) + ')';
1722         }
1723       }
1724     } else {
1725       result += '[no source]';
1726     }
1727   } else {
1728     result += '[unresolved]';
1729   }
1730
1731   return result;
1732 };
1733
1734
1735 FrameMirror.prototype.localsText = function() {
1736   // Format local variables.
1737   var result = '';
1738   var locals_count = this.localCount();
1739   if (locals_count > 0) {
1740     for (var i = 0; i < locals_count; ++i) {
1741       result += '      var ';
1742       result += this.localName(i);
1743       result += ' = ';
1744       result += this.localValue(i).toText();
1745       if (i < locals_count - 1) result += '\n';
1746     }
1747   }
1748
1749   return result;
1750 };
1751
1752
1753 FrameMirror.prototype.toText = function(opt_locals) {
1754   var result = '';
1755   result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1756   result += ' ';
1757   result += this.invocationText();
1758   result += ' ';
1759   result += this.sourceAndPositionText();
1760   if (opt_locals) {
1761     result += '\n';
1762     result += this.localsText();
1763   }
1764   return result;
1765 };
1766
1767
1768 var kScopeDetailsTypeIndex = 0;
1769 var kScopeDetailsObjectIndex = 1;
1770
1771 function ScopeDetails(frame, fun, index) {
1772   if (frame) {
1773     this.break_id_ = frame.break_id_;
1774     this.details_ = %GetScopeDetails(frame.break_id_,
1775                                      frame.details_.frameId(),
1776                                      frame.details_.inlinedFrameIndex(),
1777                                      index);
1778   } else {
1779     this.details_ = %GetFunctionScopeDetails(fun.value(), index);
1780     this.break_id_ = undefined;
1781   }
1782 }
1783
1784
1785 ScopeDetails.prototype.type = function() {
1786   if (!IS_UNDEFINED(this.break_id_)) {
1787     %CheckExecutionState(this.break_id_);
1788   }
1789   return this.details_[kScopeDetailsTypeIndex];
1790 };
1791
1792
1793 ScopeDetails.prototype.object = function() {
1794   if (!IS_UNDEFINED(this.break_id_)) {
1795     %CheckExecutionState(this.break_id_);
1796   }
1797   return this.details_[kScopeDetailsObjectIndex];
1798 };
1799
1800
1801 /**
1802  * Mirror object for scope of frame or function. Either frame or function must
1803  * be specified.
1804  * @param {FrameMirror} frame The frame this scope is a part of
1805  * @param {FunctionMirror} function The function this scope is a part of
1806  * @param {number} index The scope index in the frame
1807  * @constructor
1808  * @extends Mirror
1809  */
1810 function ScopeMirror(frame, function, index) {
1811   %_CallFunction(this, SCOPE_TYPE, Mirror);
1812   if (frame) {
1813     this.frame_index_ = frame.index_;
1814   } else {
1815     this.frame_index_ = undefined;
1816   }
1817   this.scope_index_ = index;
1818   this.details_ = new ScopeDetails(frame, function, index);
1819 }
1820 inherits(ScopeMirror, Mirror);
1821
1822
1823 ScopeMirror.prototype.frameIndex = function() {
1824   return this.frame_index_;
1825 };
1826
1827
1828 ScopeMirror.prototype.scopeIndex = function() {
1829   return this.scope_index_;
1830 };
1831
1832
1833 ScopeMirror.prototype.scopeType = function() {
1834   return this.details_.type();
1835 };
1836
1837
1838 ScopeMirror.prototype.scopeObject = function() {
1839   // For local and closure scopes create a transient mirror as these objects are
1840   // created on the fly materializing the local or closure scopes and
1841   // therefore will not preserve identity.
1842   var transient = this.scopeType() == ScopeType.Local ||
1843                   this.scopeType() == ScopeType.Closure;
1844   return MakeMirror(this.details_.object(), transient);
1845 };
1846
1847
1848 /**
1849  * Mirror object for script source.
1850  * @param {Script} script The script object
1851  * @constructor
1852  * @extends Mirror
1853  */
1854 function ScriptMirror(script) {
1855   %_CallFunction(this, SCRIPT_TYPE, Mirror);
1856   this.script_ = script;
1857   this.context_ = new ContextMirror(script.context_data);
1858   this.allocateHandle_();
1859 }
1860 inherits(ScriptMirror, Mirror);
1861
1862
1863 ScriptMirror.prototype.value = function() {
1864   return this.script_;
1865 };
1866
1867
1868 ScriptMirror.prototype.name = function() {
1869   return this.script_.name || this.script_.nameOrSourceURL();
1870 };
1871
1872
1873 ScriptMirror.prototype.id = function() {
1874   return this.script_.id;
1875 };
1876
1877
1878 ScriptMirror.prototype.source = function() {
1879   return this.script_.source;
1880 };
1881
1882
1883 ScriptMirror.prototype.setSource = function(source) {
1884   %DebugSetScriptSource(this.script_, source);
1885 };
1886
1887
1888 ScriptMirror.prototype.lineOffset = function() {
1889   return this.script_.line_offset;
1890 };
1891
1892
1893 ScriptMirror.prototype.columnOffset = function() {
1894   return this.script_.column_offset;
1895 };
1896
1897
1898 ScriptMirror.prototype.data = function() {
1899   return this.script_.data;
1900 };
1901
1902
1903 ScriptMirror.prototype.scriptType = function() {
1904   return this.script_.type;
1905 };
1906
1907
1908 ScriptMirror.prototype.compilationType = function() {
1909   return this.script_.compilation_type;
1910 };
1911
1912
1913 ScriptMirror.prototype.lineCount = function() {
1914   return this.script_.lineCount();
1915 };
1916
1917
1918 ScriptMirror.prototype.locationFromPosition = function(
1919     position, include_resource_offset) {
1920   return this.script_.locationFromPosition(position, include_resource_offset);
1921 };
1922
1923
1924 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
1925   return this.script_.sourceSlice(opt_from_line, opt_to_line);
1926 };
1927
1928
1929 ScriptMirror.prototype.context = function() {
1930   return this.context_;
1931 };
1932
1933
1934 ScriptMirror.prototype.evalFromScript = function() {
1935   return MakeMirror(this.script_.eval_from_script);
1936 };
1937
1938
1939 ScriptMirror.prototype.evalFromFunctionName = function() {
1940   return MakeMirror(this.script_.eval_from_function_name);
1941 };
1942
1943
1944 ScriptMirror.prototype.evalFromLocation = function() {
1945   var eval_from_script = this.evalFromScript();
1946   if (!eval_from_script.isUndefined()) {
1947     var position = this.script_.eval_from_script_position;
1948     return eval_from_script.locationFromPosition(position, true);
1949   }
1950 };
1951
1952
1953 ScriptMirror.prototype.toText = function() {
1954   var result = '';
1955   result += this.name();
1956   result += ' (lines: ';
1957   if (this.lineOffset() > 0) {
1958     result += this.lineOffset();
1959     result += '-';
1960     result += this.lineOffset() + this.lineCount() - 1;
1961   } else {
1962     result += this.lineCount();
1963   }
1964   result += ')';
1965   return result;
1966 };
1967
1968
1969 /**
1970  * Mirror object for context.
1971  * @param {Object} data The context data
1972  * @constructor
1973  * @extends Mirror
1974  */
1975 function ContextMirror(data) {
1976   %_CallFunction(this, CONTEXT_TYPE, Mirror);
1977   this.data_ = data;
1978   this.allocateHandle_();
1979 }
1980 inherits(ContextMirror, Mirror);
1981
1982
1983 ContextMirror.prototype.data = function() {
1984   return this.data_;
1985 };
1986
1987
1988 /**
1989  * Returns a mirror serializer
1990  *
1991  * @param {boolean} details Set to true to include details
1992  * @param {Object} options Options comtrolling the serialization
1993  *     The following options can be set:
1994  *       includeSource: include ths full source of scripts
1995  * @returns {MirrorSerializer} mirror serializer
1996  */
1997 function MakeMirrorSerializer(details, options) {
1998   return new JSONProtocolSerializer(details, options);
1999 }
2000
2001
2002 /**
2003  * Object for serializing a mirror objects and its direct references.
2004  * @param {boolean} details Indicates whether to include details for the mirror
2005  *     serialized
2006  * @constructor
2007  */
2008 function JSONProtocolSerializer(details, options) {
2009   this.details_ = details;
2010   this.options_ = options;
2011   this.mirrors_ = [ ];
2012 }
2013
2014
2015 /**
2016  * Returns a serialization of an object reference. The referenced object are
2017  * added to the serialization state.
2018  *
2019  * @param {Mirror} mirror The mirror to serialize
2020  * @returns {String} JSON serialization
2021  */
2022 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
2023   return this.serialize_(mirror, true, true);
2024 };
2025
2026
2027 /**
2028  * Returns a serialization of an object value. The referenced objects are
2029  * added to the serialization state.
2030  *
2031  * @param {Mirror} mirror The mirror to serialize
2032  * @returns {String} JSON serialization
2033  */
2034 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
2035   var json = this.serialize_(mirror, false, true);
2036   return json;
2037 };
2038
2039
2040 /**
2041  * Returns a serialization of all the objects referenced.
2042  *
2043  * @param {Mirror} mirror The mirror to serialize.
2044  * @returns {Array.<Object>} Array of the referenced objects converted to
2045  *     protcol objects.
2046  */
2047 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
2048   // Collect the protocol representation of the referenced objects in an array.
2049   var content = [];
2050
2051   // Get the number of referenced objects.
2052   var count = this.mirrors_.length;
2053
2054   for (var i = 0; i < count; i++) {
2055     content.push(this.serialize_(this.mirrors_[i], false, false));
2056   }
2057
2058   return content;
2059 };
2060
2061
2062 JSONProtocolSerializer.prototype.includeSource_ = function() {
2063   return this.options_ && this.options_.includeSource;
2064 };
2065
2066
2067 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2068   return this.options_ && this.options_.inlineRefs;
2069 };
2070
2071
2072 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2073   if (IS_UNDEFINED(this.options_) ||
2074       IS_UNDEFINED(this.options_.maxStringLength)) {
2075     return kMaxProtocolStringLength;
2076   }
2077   return this.options_.maxStringLength;
2078 };
2079
2080
2081 JSONProtocolSerializer.prototype.add_ = function(mirror) {
2082   // If this mirror is already in the list just return.
2083   for (var i = 0; i < this.mirrors_.length; i++) {
2084     if (this.mirrors_[i] === mirror) {
2085       return;
2086     }
2087   }
2088
2089   // Add the mirror to the list of mirrors to be serialized.
2090   this.mirrors_.push(mirror);
2091 };
2092
2093
2094 /**
2095  * Formats mirror object to protocol reference object with some data that can
2096  * be used to display the value in debugger.
2097  * @param {Mirror} mirror Mirror to serialize.
2098  * @return {Object} Protocol reference object.
2099  */
2100 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
2101     function(mirror) {
2102   var o = {};
2103   o.ref = mirror.handle();
2104   o.type = mirror.type();
2105   switch (mirror.type()) {
2106     case UNDEFINED_TYPE:
2107     case NULL_TYPE:
2108     case BOOLEAN_TYPE:
2109     case NUMBER_TYPE:
2110       o.value = mirror.value();
2111       break;
2112     case STRING_TYPE:
2113       o.value = mirror.getTruncatedValue(this.maxStringLength_());
2114       break;
2115     case FUNCTION_TYPE:
2116       o.name = mirror.name();
2117       o.inferredName = mirror.inferredName();
2118       if (mirror.script()) {
2119         o.scriptId = mirror.script().id();
2120       }
2121       break;
2122     case ERROR_TYPE:
2123     case REGEXP_TYPE:
2124       o.value = mirror.toText();
2125       break;
2126     case OBJECT_TYPE:
2127       o.className = mirror.className();
2128       break;
2129   }
2130   return o;
2131 };
2132
2133
2134 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2135                                                        details) {
2136   // If serializing a reference to a mirror just return the reference and add
2137   // the mirror to the referenced mirrors.
2138   if (reference &&
2139       (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
2140     if (this.inlineRefs_() && mirror.isValue()) {
2141       return this.serializeReferenceWithDisplayData_(mirror);
2142     } else {
2143       this.add_(mirror);
2144       return {'ref' : mirror.handle()};
2145     }
2146   }
2147
2148   // Collect the JSON property/value pairs.
2149   var content = {};
2150
2151   // Add the mirror handle.
2152   if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2153     content.handle = mirror.handle();
2154   }
2155
2156   // Always add the type.
2157   content.type = mirror.type();
2158
2159   switch (mirror.type()) {
2160     case UNDEFINED_TYPE:
2161     case NULL_TYPE:
2162       // Undefined and null are represented just by their type.
2163       break;
2164
2165     case BOOLEAN_TYPE:
2166       // Boolean values are simply represented by their value.
2167       content.value = mirror.value();
2168       break;
2169
2170     case NUMBER_TYPE:
2171       // Number values are simply represented by their value.
2172       content.value = NumberToJSON_(mirror.value());
2173       break;
2174
2175     case STRING_TYPE:
2176       // String values might have their value cropped to keep down size.
2177       if (this.maxStringLength_() != -1 &&
2178           mirror.length() > this.maxStringLength_()) {
2179         var str = mirror.getTruncatedValue(this.maxStringLength_());
2180         content.value = str;
2181         content.fromIndex = 0;
2182         content.toIndex = this.maxStringLength_();
2183       } else {
2184         content.value = mirror.value();
2185       }
2186       content.length = mirror.length();
2187       break;
2188
2189     case OBJECT_TYPE:
2190     case FUNCTION_TYPE:
2191     case ERROR_TYPE:
2192     case REGEXP_TYPE:
2193       // Add object representation.
2194       this.serializeObject_(mirror, content, details);
2195       break;
2196
2197     case PROPERTY_TYPE:
2198       throw new Error('PropertyMirror cannot be serialized independeltly');
2199       break;
2200
2201     case FRAME_TYPE:
2202       // Add object representation.
2203       this.serializeFrame_(mirror, content);
2204       break;
2205
2206     case SCOPE_TYPE:
2207       // Add object representation.
2208       this.serializeScope_(mirror, content);
2209       break;
2210
2211     case SCRIPT_TYPE:
2212       // Script is represented by id, name and source attributes.
2213       if (mirror.name()) {
2214         content.name = mirror.name();
2215       }
2216       content.id = mirror.id();
2217       content.lineOffset = mirror.lineOffset();
2218       content.columnOffset = mirror.columnOffset();
2219       content.lineCount = mirror.lineCount();
2220       if (mirror.data()) {
2221         content.data = mirror.data();
2222       }
2223       if (this.includeSource_()) {
2224         content.source = mirror.source();
2225       } else {
2226         var sourceStart = mirror.source().substring(0, 80);
2227         content.sourceStart = sourceStart;
2228       }
2229       content.sourceLength = mirror.source().length;
2230       content.scriptType = mirror.scriptType();
2231       content.compilationType = mirror.compilationType();
2232       // For compilation type eval emit information on the script from which
2233       // eval was called if a script is present.
2234       if (mirror.compilationType() == 1 &&
2235           mirror.evalFromScript()) {
2236         content.evalFromScript =
2237             this.serializeReference(mirror.evalFromScript());
2238         var evalFromLocation = mirror.evalFromLocation();
2239         if (evalFromLocation) {
2240           content.evalFromLocation = { line: evalFromLocation.line,
2241                                        column: evalFromLocation.column };
2242         }
2243         if (mirror.evalFromFunctionName()) {
2244           content.evalFromFunctionName = mirror.evalFromFunctionName();
2245         }
2246       }
2247       if (mirror.context()) {
2248         content.context = this.serializeReference(mirror.context());
2249       }
2250       break;
2251
2252     case CONTEXT_TYPE:
2253       content.data = mirror.data();
2254       break;
2255   }
2256
2257   // Always add the text representation.
2258   content.text = mirror.toText();
2259
2260   // Create and return the JSON string.
2261   return content;
2262 };
2263
2264
2265 /**
2266  * Serialize object information to the following JSON format.
2267  *
2268  *   {"className":"<class name>",
2269  *    "constructorFunction":{"ref":<number>},
2270  *    "protoObject":{"ref":<number>},
2271  *    "prototypeObject":{"ref":<number>},
2272  *    "namedInterceptor":<boolean>,
2273  *    "indexedInterceptor":<boolean>,
2274  *    "properties":[<properties>]}
2275  */
2276 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2277                                                              details) {
2278   // Add general object properties.
2279   content.className = mirror.className();
2280   content.constructorFunction =
2281       this.serializeReference(mirror.constructorFunction());
2282   content.protoObject = this.serializeReference(mirror.protoObject());
2283   content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2284
2285   var primitiveValue = mirror.primitiveValue();
2286   if (!IS_UNDEFINED(primitiveValue)) {
2287     content.primitiveValue = this.serializeReference(primitiveValue);
2288   }
2289
2290   // Add flags to indicate whether there are interceptors.
2291   if (mirror.hasNamedInterceptor()) {
2292     content.namedInterceptor = true;
2293   }
2294   if (mirror.hasIndexedInterceptor()) {
2295     content.indexedInterceptor = true;
2296   }
2297
2298   // Add function specific properties.
2299   if (mirror.isFunction()) {
2300     // Add function specific properties.
2301     content.name = mirror.name();
2302     if (!IS_UNDEFINED(mirror.inferredName())) {
2303       content.inferredName = mirror.inferredName();
2304     }
2305     content.resolved = mirror.resolved();
2306     if (mirror.resolved()) {
2307       content.source = mirror.source();
2308     }
2309     if (mirror.script()) {
2310       content.script = this.serializeReference(mirror.script());
2311       content.scriptId = mirror.script().id();
2312
2313       serializeLocationFields(mirror.sourceLocation(), content);
2314     }
2315
2316     content.scopes = [];
2317     for (var i = 0; i < mirror.scopeCount(); i++) {
2318       var scope = mirror.scope(i);
2319       content.scopes.push({
2320         type: scope.scopeType(),
2321         index: i
2322       });
2323     }
2324   }
2325
2326   // Add date specific properties.
2327   if (mirror.isDate()) {
2328     // Add date specific properties.
2329     content.value = mirror.value();
2330   }
2331
2332   // Add actual properties - named properties followed by indexed properties.
2333   var propertyNames = mirror.propertyNames(PropertyKind.Named);
2334   var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2335   var p = new Array(propertyNames.length + propertyIndexes.length);
2336   for (var i = 0; i < propertyNames.length; i++) {
2337     var propertyMirror = mirror.property(propertyNames[i]);
2338     p[i] = this.serializeProperty_(propertyMirror);
2339     if (details) {
2340       this.add_(propertyMirror.value());
2341     }
2342   }
2343   for (var i = 0; i < propertyIndexes.length; i++) {
2344     var propertyMirror = mirror.property(propertyIndexes[i]);
2345     p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2346     if (details) {
2347       this.add_(propertyMirror.value());
2348     }
2349   }
2350   content.properties = p;
2351 };
2352
2353
2354 /**
2355  * Serialize location information to the following JSON format:
2356  *
2357  *   "position":"<position>",
2358  *   "line":"<line>",
2359  *   "column":"<column>",
2360  *
2361  * @param {SourceLocation} location The location to serialize, may be undefined.
2362  */
2363 function serializeLocationFields (location, content) {
2364   if (!location) {
2365     return;
2366   }
2367   content.position = location.position;
2368   var line = location.line;
2369   if (!IS_UNDEFINED(line)) {
2370     content.line = line;
2371   }
2372   var column = location.column;
2373   if (!IS_UNDEFINED(column)) {
2374     content.column = column;
2375   }
2376 }
2377
2378
2379 /**
2380  * Serialize property information to the following JSON format for building the
2381  * array of properties.
2382  *
2383  *   {"name":"<property name>",
2384  *    "attributes":<number>,
2385  *    "propertyType":<number>,
2386  *    "ref":<number>}
2387  *
2388  * If the attribute for the property is PropertyAttribute.None it is not added.
2389  * If the propertyType for the property is PropertyType.Normal it is not added.
2390  * Here are a couple of examples.
2391  *
2392  *   {"name":"hello","ref":1}
2393  *   {"name":"length","attributes":7,"propertyType":3,"ref":2}
2394  *
2395  * @param {PropertyMirror} propertyMirror The property to serialize.
2396  * @returns {Object} Protocol object representing the property.
2397  */
2398 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2399   var result = {};
2400
2401   result.name = propertyMirror.name();
2402   var propertyValue = propertyMirror.value();
2403   if (this.inlineRefs_() && propertyValue.isValue()) {
2404     result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2405   } else {
2406     if (propertyMirror.attributes() != PropertyAttribute.None) {
2407       result.attributes = propertyMirror.attributes();
2408     }
2409     if (propertyMirror.propertyType() != PropertyType.Normal) {
2410       result.propertyType = propertyMirror.propertyType();
2411     }
2412     result.ref = propertyValue.handle();
2413   }
2414   return result;
2415 };
2416
2417
2418 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2419   content.index = mirror.index();
2420   content.receiver = this.serializeReference(mirror.receiver());
2421   var func = mirror.func();
2422   content.func = this.serializeReference(func);
2423   if (func.script()) {
2424     content.script = this.serializeReference(func.script());
2425   }
2426   content.constructCall = mirror.isConstructCall();
2427   content.atReturn = mirror.isAtReturn();
2428   if (mirror.isAtReturn()) {
2429     content.returnValue = this.serializeReference(mirror.returnValue());
2430   }
2431   content.debuggerFrame = mirror.isDebuggerFrame();
2432   var x = new Array(mirror.argumentCount());
2433   for (var i = 0; i < mirror.argumentCount(); i++) {
2434     var arg = {};
2435     var argument_name = mirror.argumentName(i);
2436     if (argument_name) {
2437       arg.name = argument_name;
2438     }
2439     arg.value = this.serializeReference(mirror.argumentValue(i));
2440     x[i] = arg;
2441   }
2442   content.arguments = x;
2443   var x = new Array(mirror.localCount());
2444   for (var i = 0; i < mirror.localCount(); i++) {
2445     var local = {};
2446     local.name = mirror.localName(i);
2447     local.value = this.serializeReference(mirror.localValue(i));
2448     x[i] = local;
2449   }
2450   content.locals = x;
2451   serializeLocationFields(mirror.sourceLocation(), content);
2452   var source_line_text = mirror.sourceLineText();
2453   if (!IS_UNDEFINED(source_line_text)) {
2454     content.sourceLineText = source_line_text;
2455   }
2456
2457   content.scopes = [];
2458   for (var i = 0; i < mirror.scopeCount(); i++) {
2459     var scope = mirror.scope(i);
2460     content.scopes.push({
2461       type: scope.scopeType(),
2462       index: i
2463     });
2464   }
2465 };
2466
2467
2468 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2469   content.index = mirror.scopeIndex();
2470   content.frameIndex = mirror.frameIndex();
2471   content.type = mirror.scopeType();
2472   content.object = this.inlineRefs_() ?
2473                    this.serializeValue(mirror.scopeObject()) :
2474                    this.serializeReference(mirror.scopeObject());
2475 };
2476
2477
2478 /**
2479  * Convert a number to a protocol value. For all finite numbers the number
2480  * itself is returned. For non finite numbers NaN, Infinite and
2481  * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
2482  * (not including the quotes) is returned.
2483  *
2484  * @param {number} value The number value to convert to a protocol value.
2485  * @returns {number|string} Protocol value.
2486  */
2487 function NumberToJSON_(value) {
2488   if (isNaN(value)) {
2489     return 'NaN';
2490   }
2491   if (!NUMBER_IS_FINITE(value)) {
2492     if (value > 0) {
2493       return 'Infinity';
2494     } else {
2495       return '-Infinity';
2496     }
2497   }
2498   return value;
2499 }