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