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