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