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.
7 var next_transient_handle_ = -1;
10 var mirror_cache_ = [];
11 var mirror_cache_enabled_ = true;
14 function ToggleMirrorCache(value) {
15 mirror_cache_enabled_ = value;
21 // Wrapper to check whether an object is a Promise. The call may not work
22 // if promises are not enabled.
23 // TODO(yangguo): remove try-catch once promises are enabled by default.
24 function ObjectIsPromise(value) {
26 return IS_SPEC_OBJECT(value) &&
27 !IS_UNDEFINED(%DebugGetProperty(value, builtins.promiseStatus));
35 * Returns the mirror for a specified value or object.
37 * @param {value or Object} value the value or object to retreive the mirror for
38 * @param {boolean} transient indicate whether this object is transient and
39 * should not be added to the mirror cache. The default is not transient.
40 * @returns {Mirror} the mirror reflects the passed value or object
42 function MakeMirror(value, opt_transient) {
45 // Look for non transient mirrors in the mirror cache.
46 if (!opt_transient && mirror_cache_enabled_) {
47 for (id in mirror_cache_) {
48 mirror = mirror_cache_[id];
49 if (mirror.value() === value) {
52 // Special check for NaN as NaN == NaN is false.
53 if (mirror.isNumber() && isNaN(mirror.value()) &&
54 typeof value == 'number' && isNaN(value)) {
60 if (IS_UNDEFINED(value)) {
61 mirror = new UndefinedMirror();
62 } else if (IS_NULL(value)) {
63 mirror = new NullMirror();
64 } else if (IS_BOOLEAN(value)) {
65 mirror = new BooleanMirror(value);
66 } else if (IS_NUMBER(value)) {
67 mirror = new NumberMirror(value);
68 } else if (IS_STRING(value)) {
69 mirror = new StringMirror(value);
70 } else if (IS_SYMBOL(value)) {
71 mirror = new SymbolMirror(value);
72 } else if (IS_ARRAY(value)) {
73 mirror = new ArrayMirror(value);
74 } else if (IS_DATE(value)) {
75 mirror = new DateMirror(value);
76 } else if (IS_FUNCTION(value)) {
77 mirror = new FunctionMirror(value);
78 } else if (IS_REGEXP(value)) {
79 mirror = new RegExpMirror(value);
80 } else if (IS_ERROR(value)) {
81 mirror = new ErrorMirror(value);
82 } else if (IS_SCRIPT(value)) {
83 mirror = new ScriptMirror(value);
84 } else if (ObjectIsPromise(value)) {
85 mirror = new PromiseMirror(value);
87 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
90 if (mirror_cache_enabled_) mirror_cache_[mirror.handle()] = mirror;
96 * Returns the mirror for a specified mirror handle.
98 * @param {number} handle the handle to find the mirror for
99 * @returns {Mirror or undefiend} the mirror with the requested handle or
100 * undefined if no mirror with the requested handle was found
102 function LookupMirror(handle) {
103 if (!mirror_cache_enabled_) throw new Error("Mirror cache is disabled");
104 return mirror_cache_[handle];
109 * Returns the mirror for the undefined value.
111 * @returns {Mirror} the mirror reflects the undefined value
113 function GetUndefinedMirror() {
114 return MakeMirror(UNDEFINED);
119 * Inherit the prototype methods from one constructor into another.
121 * The Function.prototype.inherits from lang.js rewritten as a standalone
122 * function (not on Function.prototype). NOTE: If this file is to be loaded
123 * during bootstrapping this function needs to be revritten using some native
124 * functions as prototype setup using normal JavaScript does not work as
125 * expected during bootstrapping (see mirror.js in r114903).
127 * @param {function} ctor Constructor function which needs to inherit the
129 * @param {function} superCtor Constructor function to inherit prototype from
131 function inherits(ctor, superCtor) {
132 var tempCtor = function(){};
133 tempCtor.prototype = superCtor.prototype;
134 ctor.super_ = superCtor.prototype;
135 ctor.prototype = new tempCtor();
136 ctor.prototype.constructor = ctor;
140 // Type names of the different mirrors.
141 var UNDEFINED_TYPE = 'undefined';
142 var NULL_TYPE = 'null';
143 var BOOLEAN_TYPE = 'boolean';
144 var NUMBER_TYPE = 'number';
145 var STRING_TYPE = 'string';
146 var SYMBOL_TYPE = 'symbol';
147 var OBJECT_TYPE = 'object';
148 var FUNCTION_TYPE = 'function';
149 var REGEXP_TYPE = 'regexp';
150 var ERROR_TYPE = 'error';
151 var PROPERTY_TYPE = 'property';
152 var INTERNAL_PROPERTY_TYPE = 'internalProperty';
153 var FRAME_TYPE = 'frame';
154 var SCRIPT_TYPE = 'script';
155 var CONTEXT_TYPE = 'context';
156 var SCOPE_TYPE = 'scope';
157 var PROMISE_TYPE = 'promise';
159 // Maximum length when sending strings through the JSON protocol.
160 var kMaxProtocolStringLength = 80;
162 // Different kind of properties.
163 var PropertyKind = {};
164 PropertyKind.Named = 1;
165 PropertyKind.Indexed = 2;
168 // A copy of the PropertyType enum from global.h
169 var PropertyType = {};
170 PropertyType.Normal = 0;
171 PropertyType.Field = 1;
172 PropertyType.Constant = 2;
173 PropertyType.Callbacks = 3;
174 PropertyType.Handler = 4;
175 PropertyType.Interceptor = 5;
176 PropertyType.Transition = 6;
177 PropertyType.Nonexistent = 7;
180 // Different attributes for a property.
181 var PropertyAttribute = {};
182 PropertyAttribute.None = NONE;
183 PropertyAttribute.ReadOnly = READ_ONLY;
184 PropertyAttribute.DontEnum = DONT_ENUM;
185 PropertyAttribute.DontDelete = DONT_DELETE;
188 // A copy of the scope types from runtime.cc.
189 var ScopeType = { Global: 0,
207 // - UnresolvedFunctionMirror
214 // - InternalPropertyMirror
220 * Base class for all mirror objects.
221 * @param {string} type The type of the mirror
224 function Mirror(type) {
229 Mirror.prototype.type = function() {
235 * Check whether the mirror reflects a value.
236 * @returns {boolean} True if the mirror reflects a value.
238 Mirror.prototype.isValue = function() {
239 return this instanceof ValueMirror;
244 * Check whether the mirror reflects the undefined value.
245 * @returns {boolean} True if the mirror reflects the undefined value.
247 Mirror.prototype.isUndefined = function() {
248 return this instanceof UndefinedMirror;
253 * Check whether the mirror reflects the null value.
254 * @returns {boolean} True if the mirror reflects the null value
256 Mirror.prototype.isNull = function() {
257 return this instanceof NullMirror;
262 * Check whether the mirror reflects a boolean value.
263 * @returns {boolean} True if the mirror reflects a boolean value
265 Mirror.prototype.isBoolean = function() {
266 return this instanceof BooleanMirror;
271 * Check whether the mirror reflects a number value.
272 * @returns {boolean} True if the mirror reflects a number value
274 Mirror.prototype.isNumber = function() {
275 return this instanceof NumberMirror;
280 * Check whether the mirror reflects a string value.
281 * @returns {boolean} True if the mirror reflects a string value
283 Mirror.prototype.isString = function() {
284 return this instanceof StringMirror;
289 * Check whether the mirror reflects a symbol.
290 * @returns {boolean} True if the mirror reflects a symbol
292 Mirror.prototype.isSymbol = function() {
293 return this instanceof SymbolMirror;
298 * Check whether the mirror reflects an object.
299 * @returns {boolean} True if the mirror reflects an object
301 Mirror.prototype.isObject = function() {
302 return this instanceof ObjectMirror;
307 * Check whether the mirror reflects a function.
308 * @returns {boolean} True if the mirror reflects a function
310 Mirror.prototype.isFunction = function() {
311 return this instanceof FunctionMirror;
316 * Check whether the mirror reflects an unresolved function.
317 * @returns {boolean} True if the mirror reflects an unresolved function
319 Mirror.prototype.isUnresolvedFunction = function() {
320 return this instanceof UnresolvedFunctionMirror;
325 * Check whether the mirror reflects an array.
326 * @returns {boolean} True if the mirror reflects an array
328 Mirror.prototype.isArray = function() {
329 return this instanceof ArrayMirror;
334 * Check whether the mirror reflects a date.
335 * @returns {boolean} True if the mirror reflects a date
337 Mirror.prototype.isDate = function() {
338 return this instanceof DateMirror;
343 * Check whether the mirror reflects a regular expression.
344 * @returns {boolean} True if the mirror reflects a regular expression
346 Mirror.prototype.isRegExp = function() {
347 return this instanceof RegExpMirror;
352 * Check whether the mirror reflects an error.
353 * @returns {boolean} True if the mirror reflects an error
355 Mirror.prototype.isError = function() {
356 return this instanceof ErrorMirror;
361 * Check whether the mirror reflects a promise.
362 * @returns {boolean} True if the mirror reflects a promise
364 Mirror.prototype.isPromise = function() {
365 return this instanceof PromiseMirror;
370 * Check whether the mirror reflects a property.
371 * @returns {boolean} True if the mirror reflects a property
373 Mirror.prototype.isProperty = function() {
374 return this instanceof PropertyMirror;
379 * Check whether the mirror reflects an internal property.
380 * @returns {boolean} True if the mirror reflects an internal property
382 Mirror.prototype.isInternalProperty = function() {
383 return this instanceof InternalPropertyMirror;
388 * Check whether the mirror reflects a stack frame.
389 * @returns {boolean} True if the mirror reflects a stack frame
391 Mirror.prototype.isFrame = function() {
392 return this instanceof FrameMirror;
397 * Check whether the mirror reflects a script.
398 * @returns {boolean} True if the mirror reflects a script
400 Mirror.prototype.isScript = function() {
401 return this instanceof ScriptMirror;
406 * Check whether the mirror reflects a context.
407 * @returns {boolean} True if the mirror reflects a context
409 Mirror.prototype.isContext = function() {
410 return this instanceof ContextMirror;
415 * Check whether the mirror reflects a scope.
416 * @returns {boolean} True if the mirror reflects a scope
418 Mirror.prototype.isScope = function() {
419 return this instanceof ScopeMirror;
424 * Allocate a handle id for this object.
426 Mirror.prototype.allocateHandle_ = function() {
427 if (mirror_cache_enabled_) this.handle_ = next_handle_++;
432 * Allocate a transient handle id for this object. Transient handles are
435 Mirror.prototype.allocateTransientHandle_ = function() {
436 this.handle_ = next_transient_handle_--;
440 Mirror.prototype.toText = function() {
441 // Simpel to text which is used when on specialization in subclass.
442 return "#<" + this.constructor.name + ">";
447 * Base class for all value mirror objects.
448 * @param {string} type The type of the mirror
449 * @param {value} value The value reflected by this mirror
450 * @param {boolean} transient indicate whether this object is transient with a
455 function ValueMirror(type, value, transient) {
456 %_CallFunction(this, type, Mirror);
459 this.allocateHandle_();
461 this.allocateTransientHandle_();
464 inherits(ValueMirror, Mirror);
467 Mirror.prototype.handle = function() {
473 * Check whether this is a primitive value.
474 * @return {boolean} True if the mirror reflects a primitive value
476 ValueMirror.prototype.isPrimitive = function() {
477 var type = this.type();
478 return type === 'undefined' ||
480 type === 'boolean' ||
488 * Get the actual value reflected by this mirror.
489 * @return {value} The value reflected by this mirror
491 ValueMirror.prototype.value = function() {
497 * Mirror object for Undefined.
499 * @extends ValueMirror
501 function UndefinedMirror() {
502 %_CallFunction(this, UNDEFINED_TYPE, UNDEFINED, ValueMirror);
504 inherits(UndefinedMirror, ValueMirror);
507 UndefinedMirror.prototype.toText = function() {
513 * Mirror object for null.
515 * @extends ValueMirror
517 function NullMirror() {
518 %_CallFunction(this, NULL_TYPE, null, ValueMirror);
520 inherits(NullMirror, ValueMirror);
523 NullMirror.prototype.toText = function() {
529 * Mirror object for boolean values.
530 * @param {boolean} value The boolean value reflected by this mirror
532 * @extends ValueMirror
534 function BooleanMirror(value) {
535 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
537 inherits(BooleanMirror, ValueMirror);
540 BooleanMirror.prototype.toText = function() {
541 return this.value_ ? 'true' : 'false';
546 * Mirror object for number values.
547 * @param {number} value The number value reflected by this mirror
549 * @extends ValueMirror
551 function NumberMirror(value) {
552 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
554 inherits(NumberMirror, ValueMirror);
557 NumberMirror.prototype.toText = function() {
558 return %_NumberToString(this.value_);
563 * Mirror object for string values.
564 * @param {string} value The string value reflected by this mirror
566 * @extends ValueMirror
568 function StringMirror(value) {
569 %_CallFunction(this, STRING_TYPE, value, ValueMirror);
571 inherits(StringMirror, ValueMirror);
574 StringMirror.prototype.length = function() {
575 return this.value_.length;
578 StringMirror.prototype.getTruncatedValue = function(maxLength) {
579 if (maxLength != -1 && this.length() > maxLength) {
580 return this.value_.substring(0, maxLength) +
581 '... (length: ' + this.length() + ')';
586 StringMirror.prototype.toText = function() {
587 return this.getTruncatedValue(kMaxProtocolStringLength);
592 * Mirror object for a Symbol
593 * @param {Object} value The Symbol
597 function SymbolMirror(value) {
598 %_CallFunction(this, SYMBOL_TYPE, value, ValueMirror);
600 inherits(SymbolMirror, ValueMirror);
603 SymbolMirror.prototype.description = function() {
604 return %SymbolDescription(%_ValueOf(this.value_));
608 SymbolMirror.prototype.toText = function() {
609 return %_CallFunction(this.value_, builtins.SymbolToString);
614 * Mirror object for objects.
615 * @param {object} value The object reflected by this mirror
616 * @param {boolean} transient indicate whether this object is transient with a
619 * @extends ValueMirror
621 function ObjectMirror(value, type, transient) {
622 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
624 inherits(ObjectMirror, ValueMirror);
627 ObjectMirror.prototype.className = function() {
628 return %_ClassOf(this.value_);
632 ObjectMirror.prototype.constructorFunction = function() {
633 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
637 ObjectMirror.prototype.prototypeObject = function() {
638 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
642 ObjectMirror.prototype.protoObject = function() {
643 return MakeMirror(%DebugGetPrototype(this.value_));
647 ObjectMirror.prototype.hasNamedInterceptor = function() {
648 // Get information on interceptors for this object.
649 var x = %GetInterceptorInfo(this.value_);
654 ObjectMirror.prototype.hasIndexedInterceptor = function() {
655 // Get information on interceptors for this object.
656 var x = %GetInterceptorInfo(this.value_);
662 * Return the property names for this object.
663 * @param {number} kind Indicate whether named, indexed or both kinds of
664 * properties are requested
665 * @param {number} limit Limit the number of names returend to the specified
667 * @return {Array} Property names for this object
669 ObjectMirror.prototype.propertyNames = function(kind, limit) {
670 // Find kind and limit and allocate array for the result
671 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
677 // Find all the named properties.
678 if (kind & PropertyKind.Named) {
679 // Get all own property names except for private symbols.
681 %GetOwnPropertyNames(this.value_, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
682 total += propertyNames.length;
684 // Get names for named interceptor properties if any.
685 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
686 var namedInterceptorNames =
687 %GetNamedInterceptorPropertyNames(this.value_);
688 if (namedInterceptorNames) {
689 propertyNames = propertyNames.concat(namedInterceptorNames);
690 total += namedInterceptorNames.length;
695 // Find all the indexed properties.
696 if (kind & PropertyKind.Indexed) {
697 // Get own element names.
698 elementNames = %GetOwnElementNames(this.value_);
699 total += elementNames.length;
701 // Get names for indexed interceptor properties.
702 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
703 var indexedInterceptorNames =
704 %GetIndexedInterceptorElementNames(this.value_);
705 if (indexedInterceptorNames) {
706 elementNames = elementNames.concat(indexedInterceptorNames);
707 total += indexedInterceptorNames.length;
711 limit = Math.min(limit || total, total);
713 var names = new Array(limit);
716 // Copy names for named properties.
717 if (kind & PropertyKind.Named) {
718 for (var i = 0; index < limit && i < propertyNames.length; i++) {
719 names[index++] = propertyNames[i];
723 // Copy names for indexed properties.
724 if (kind & PropertyKind.Indexed) {
725 for (var i = 0; index < limit && i < elementNames.length; i++) {
726 names[index++] = elementNames[i];
735 * Return the properties for this object as an array of PropertyMirror objects.
736 * @param {number} kind Indicate whether named, indexed or both kinds of
737 * properties are requested
738 * @param {number} limit Limit the number of properties returned to the
740 * @return {Array} Property mirrors for this object
742 ObjectMirror.prototype.properties = function(kind, limit) {
743 var names = this.propertyNames(kind, limit);
744 var properties = new Array(names.length);
745 for (var i = 0; i < names.length; i++) {
746 properties[i] = this.property(names[i]);
754 * Return the internal properties for this object as an array of
755 * InternalPropertyMirror objects.
756 * @return {Array} Property mirrors for this object
758 ObjectMirror.prototype.internalProperties = function() {
759 return ObjectMirror.GetInternalProperties(this.value_);
763 ObjectMirror.prototype.property = function(name) {
764 var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
766 return new PropertyMirror(this, name, details);
770 return GetUndefinedMirror();
776 * Try to find a property from its value.
777 * @param {Mirror} value The property value to look for
778 * @return {PropertyMirror} The property with the specified value. If no
779 * property was found with the specified value UndefinedMirror is returned
781 ObjectMirror.prototype.lookupProperty = function(value) {
782 var properties = this.properties();
784 // Look for property value in properties.
785 for (var i = 0; i < properties.length; i++) {
787 // Skip properties which are defined through assessors.
788 var property = properties[i];
789 if (property.propertyType() != PropertyType.Callbacks) {
790 if (%_ObjectEquals(property.value_, value.value_)) {
797 return GetUndefinedMirror();
802 * Returns objects which has direct references to this object
803 * @param {number} opt_max_objects Optional parameter specifying the maximum
804 * number of referencing objects to return.
805 * @return {Array} The objects which has direct references to this object.
807 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
808 // Find all objects with direct references to this object.
809 var result = %DebugReferencedBy(this.value_,
810 Mirror.prototype, opt_max_objects || 0);
812 // Make mirrors for all the references found.
813 for (var i = 0; i < result.length; i++) {
814 result[i] = MakeMirror(result[i]);
821 ObjectMirror.prototype.toText = function() {
823 var ctor = this.constructorFunction();
824 if (!ctor.isFunction()) {
825 name = this.className();
829 name = this.className();
832 return '#<' + name + '>';
837 * Return the internal properties of the value, such as [[PrimitiveValue]] of
838 * scalar wrapper objects, properties of the bound function and properties of
840 * This method is done static to be accessible from Debug API with the bare
841 * values without mirrors.
842 * @return {Array} array (possibly empty) of InternalProperty instances
844 ObjectMirror.GetInternalProperties = function(value) {
845 if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) ||
846 IS_BOOLEAN_WRAPPER(value)) {
847 var primitiveValue = %_ValueOf(value);
848 return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)];
849 } else if (IS_FUNCTION(value)) {
850 var bindings = %BoundFunctionGetBindings(value);
852 if (bindings && IS_ARRAY(bindings)) {
853 result.push(new InternalPropertyMirror("[[TargetFunction]]",
855 result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1]));
857 for (var i = 2; i < bindings.length; i++) {
858 boundArgs.push(bindings[i]);
860 result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs));
863 } else if (ObjectIsPromise(value)) {
865 result.push(new InternalPropertyMirror("[[PromiseStatus]]",
866 PromiseGetStatus_(value)));
867 result.push(new InternalPropertyMirror("[[PromiseValue]]",
868 PromiseGetValue_(value)));
876 * Mirror object for functions.
877 * @param {function} value The function object reflected by this mirror.
879 * @extends ObjectMirror
881 function FunctionMirror(value) {
882 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
883 this.resolved_ = true;
885 inherits(FunctionMirror, ObjectMirror);
889 * Returns whether the function is resolved.
890 * @return {boolean} True if the function is resolved. Unresolved functions can
891 * only originate as functions from stack frames
893 FunctionMirror.prototype.resolved = function() {
894 return this.resolved_;
899 * Returns the name of the function.
900 * @return {string} Name of the function
902 FunctionMirror.prototype.name = function() {
903 return %FunctionGetName(this.value_);
908 * Returns the inferred name of the function.
909 * @return {string} Name of the function
911 FunctionMirror.prototype.inferredName = function() {
912 return %FunctionGetInferredName(this.value_);
917 * Returns the source code for the function.
918 * @return {string or undefined} The source code for the function. If the
919 * function is not resolved undefined will be returned.
921 FunctionMirror.prototype.source = function() {
922 // Return source if function is resolved. Otherwise just fall through to
924 if (this.resolved()) {
925 return builtins.FunctionSourceString(this.value_);
931 * Returns the script object for the function.
932 * @return {ScriptMirror or undefined} Script object for the function or
933 * undefined if the function has no script
935 FunctionMirror.prototype.script = function() {
936 // Return script if function is resolved. Otherwise just fall through
937 // to return undefined.
938 if (this.resolved()) {
942 var script = %FunctionGetScript(this.value_);
944 return this.script_ = MakeMirror(script);
951 * Returns the script source position for the function. Only makes sense
952 * for functions which has a script defined.
953 * @return {Number or undefined} in-script position for the function
955 FunctionMirror.prototype.sourcePosition_ = function() {
956 // Return script if function is resolved. Otherwise just fall through
957 // to return undefined.
958 if (this.resolved()) {
959 return %FunctionGetScriptSourcePosition(this.value_);
965 * Returns the script source location object for the function. Only makes sense
966 * for functions which has a script defined.
967 * @return {Location or undefined} in-script location for the function begin
969 FunctionMirror.prototype.sourceLocation = function() {
970 if (this.resolved()) {
971 var script = this.script();
973 return script.locationFromPosition(this.sourcePosition_(), true);
980 * Returns objects constructed by this function.
981 * @param {number} opt_max_instances Optional parameter specifying the maximum
982 * number of instances to return.
983 * @return {Array or undefined} The objects constructed by this function.
985 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
986 if (this.resolved()) {
987 // Find all objects constructed from this function.
988 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
990 // Make mirrors for all the instances found.
991 for (var i = 0; i < result.length; i++) {
992 result[i] = MakeMirror(result[i]);
1002 FunctionMirror.prototype.scopeCount = function() {
1003 if (this.resolved()) {
1004 if (IS_UNDEFINED(this.scopeCount_)) {
1005 this.scopeCount_ = %GetFunctionScopeCount(this.value());
1007 return this.scopeCount_;
1014 FunctionMirror.prototype.scope = function(index) {
1015 if (this.resolved()) {
1016 return new ScopeMirror(UNDEFINED, this, index);
1021 FunctionMirror.prototype.toText = function() {
1022 return this.source();
1027 * Mirror object for unresolved functions.
1028 * @param {string} value The name for the unresolved function reflected by this
1031 * @extends ObjectMirror
1033 function UnresolvedFunctionMirror(value) {
1034 // Construct this using the ValueMirror as an unresolved function is not a
1035 // real object but just a string.
1036 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
1037 this.propertyCount_ = 0;
1038 this.elementCount_ = 0;
1039 this.resolved_ = false;
1041 inherits(UnresolvedFunctionMirror, FunctionMirror);
1044 UnresolvedFunctionMirror.prototype.className = function() {
1049 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
1050 return GetUndefinedMirror();
1054 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
1055 return GetUndefinedMirror();
1059 UnresolvedFunctionMirror.prototype.protoObject = function() {
1060 return GetUndefinedMirror();
1064 UnresolvedFunctionMirror.prototype.name = function() {
1069 UnresolvedFunctionMirror.prototype.inferredName = function() {
1074 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
1080 * Mirror object for arrays.
1081 * @param {Array} value The Array object reflected by this mirror
1083 * @extends ObjectMirror
1085 function ArrayMirror(value) {
1086 %_CallFunction(this, value, ObjectMirror);
1088 inherits(ArrayMirror, ObjectMirror);
1091 ArrayMirror.prototype.length = function() {
1092 return this.value_.length;
1096 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
1098 var from_index = opt_from_index || 0;
1099 var to_index = opt_to_index || this.length() - 1;
1100 if (from_index > to_index) return new Array();
1101 var values = new Array(to_index - from_index + 1);
1102 for (var i = from_index; i <= to_index; i++) {
1103 var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
1106 value = new PropertyMirror(this, i, details);
1108 value = GetUndefinedMirror();
1110 values[i - from_index] = value;
1117 * Mirror object for dates.
1118 * @param {Date} value The Date object reflected by this mirror
1120 * @extends ObjectMirror
1122 function DateMirror(value) {
1123 %_CallFunction(this, value, ObjectMirror);
1125 inherits(DateMirror, ObjectMirror);
1128 DateMirror.prototype.toText = function() {
1129 var s = JSON.stringify(this.value_);
1130 return s.substring(1, s.length - 1); // cut quotes
1135 * Mirror object for regular expressions.
1136 * @param {RegExp} value The RegExp object reflected by this mirror
1138 * @extends ObjectMirror
1140 function RegExpMirror(value) {
1141 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
1143 inherits(RegExpMirror, ObjectMirror);
1147 * Returns the source to the regular expression.
1148 * @return {string or undefined} The source to the regular expression
1150 RegExpMirror.prototype.source = function() {
1151 return this.value_.source;
1156 * Returns whether this regular expression has the global (g) flag set.
1157 * @return {boolean} Value of the global flag
1159 RegExpMirror.prototype.global = function() {
1160 return this.value_.global;
1165 * Returns whether this regular expression has the ignore case (i) flag set.
1166 * @return {boolean} Value of the ignore case flag
1168 RegExpMirror.prototype.ignoreCase = function() {
1169 return this.value_.ignoreCase;
1174 * Returns whether this regular expression has the multiline (m) flag set.
1175 * @return {boolean} Value of the multiline flag
1177 RegExpMirror.prototype.multiline = function() {
1178 return this.value_.multiline;
1182 RegExpMirror.prototype.toText = function() {
1183 // Simpel to text which is used when on specialization in subclass.
1184 return "/" + this.source() + "/";
1189 * Mirror object for error objects.
1190 * @param {Error} value The error object reflected by this mirror
1192 * @extends ObjectMirror
1194 function ErrorMirror(value) {
1195 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
1197 inherits(ErrorMirror, ObjectMirror);
1201 * Returns the message for this eror object.
1202 * @return {string or undefined} The message for this eror object
1204 ErrorMirror.prototype.message = function() {
1205 return this.value_.message;
1209 ErrorMirror.prototype.toText = function() {
1210 // Use the same text representation as in messages.js.
1213 str = %_CallFunction(this.value_, builtins.ErrorToString);
1222 * Mirror object for a Promise object.
1223 * @param {Object} value The Promise object
1225 * @extends ObjectMirror
1227 function PromiseMirror(value) {
1228 %_CallFunction(this, value, PROMISE_TYPE, ObjectMirror);
1230 inherits(PromiseMirror, ObjectMirror);
1233 function PromiseGetStatus_(value) {
1234 var status = %DebugGetProperty(value, builtins.promiseStatus);
1235 if (status == 0) return "pending";
1236 if (status == 1) return "resolved";
1241 function PromiseGetValue_(value) {
1242 return %DebugGetProperty(value, builtins.promiseValue);
1246 PromiseMirror.prototype.status = function() {
1247 return PromiseGetStatus_(this.value_);
1251 PromiseMirror.prototype.promiseValue = function() {
1252 return MakeMirror(PromiseGetValue_(this.value_));
1257 * Base mirror object for properties.
1258 * @param {ObjectMirror} mirror The mirror object having this property
1259 * @param {string} name The name of the property
1260 * @param {Array} details Details about the property
1264 function PropertyMirror(mirror, name, details) {
1265 %_CallFunction(this, PROPERTY_TYPE, Mirror);
1266 this.mirror_ = mirror;
1268 this.value_ = details[0];
1269 this.details_ = details[1];
1270 if (details.length > 2) {
1271 this.exception_ = details[2];
1272 this.getter_ = details[3];
1273 this.setter_ = details[4];
1276 inherits(PropertyMirror, Mirror);
1279 PropertyMirror.prototype.isReadOnly = function() {
1280 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1284 PropertyMirror.prototype.isEnum = function() {
1285 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1289 PropertyMirror.prototype.canDelete = function() {
1290 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1294 PropertyMirror.prototype.name = function() {
1299 PropertyMirror.prototype.isIndexed = function() {
1300 for (var i = 0; i < this.name_.length; i++) {
1301 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1309 PropertyMirror.prototype.value = function() {
1310 return MakeMirror(this.value_, false);
1315 * Returns whether this property value is an exception.
1316 * @return {booolean} True if this property value is an exception
1318 PropertyMirror.prototype.isException = function() {
1319 return this.exception_ ? true : false;
1323 PropertyMirror.prototype.attributes = function() {
1324 return %DebugPropertyAttributesFromDetails(this.details_);
1328 PropertyMirror.prototype.propertyType = function() {
1329 return %DebugPropertyTypeFromDetails(this.details_);
1333 PropertyMirror.prototype.insertionIndex = function() {
1334 return %DebugPropertyIndexFromDetails(this.details_);
1339 * Returns whether this property has a getter defined through __defineGetter__.
1340 * @return {booolean} True if this property has a getter
1342 PropertyMirror.prototype.hasGetter = function() {
1343 return this.getter_ ? true : false;
1348 * Returns whether this property has a setter defined through __defineSetter__.
1349 * @return {booolean} True if this property has a setter
1351 PropertyMirror.prototype.hasSetter = function() {
1352 return this.setter_ ? true : false;
1357 * Returns the getter for this property defined through __defineGetter__.
1358 * @return {Mirror} FunctionMirror reflecting the getter function or
1359 * UndefinedMirror if there is no getter for this property
1361 PropertyMirror.prototype.getter = function() {
1362 if (this.hasGetter()) {
1363 return MakeMirror(this.getter_);
1365 return GetUndefinedMirror();
1371 * Returns the setter for this property defined through __defineSetter__.
1372 * @return {Mirror} FunctionMirror reflecting the setter function or
1373 * UndefinedMirror if there is no setter for this property
1375 PropertyMirror.prototype.setter = function() {
1376 if (this.hasSetter()) {
1377 return MakeMirror(this.setter_);
1379 return GetUndefinedMirror();
1385 * Returns whether this property is natively implemented by the host or a set
1386 * through JavaScript code.
1387 * @return {boolean} True if the property is
1388 * UndefinedMirror if there is no setter for this property
1390 PropertyMirror.prototype.isNative = function() {
1391 return (this.propertyType() == PropertyType.Interceptor) ||
1392 ((this.propertyType() == PropertyType.Callbacks) &&
1393 !this.hasGetter() && !this.hasSetter());
1398 * Mirror object for internal properties. Internal property reflects properties
1399 * not accessible from user code such as [[BoundThis]] in bound function.
1400 * Their names are merely symbolic.
1401 * @param {string} name The name of the property
1402 * @param {value} property value
1406 function InternalPropertyMirror(name, value) {
1407 %_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror);
1409 this.value_ = value;
1411 inherits(InternalPropertyMirror, Mirror);
1414 InternalPropertyMirror.prototype.name = function() {
1419 InternalPropertyMirror.prototype.value = function() {
1420 return MakeMirror(this.value_, false);
1424 var kFrameDetailsFrameIdIndex = 0;
1425 var kFrameDetailsReceiverIndex = 1;
1426 var kFrameDetailsFunctionIndex = 2;
1427 var kFrameDetailsArgumentCountIndex = 3;
1428 var kFrameDetailsLocalCountIndex = 4;
1429 var kFrameDetailsSourcePositionIndex = 5;
1430 var kFrameDetailsConstructCallIndex = 6;
1431 var kFrameDetailsAtReturnIndex = 7;
1432 var kFrameDetailsFlagsIndex = 8;
1433 var kFrameDetailsFirstDynamicIndex = 9;
1435 var kFrameDetailsNameIndex = 0;
1436 var kFrameDetailsValueIndex = 1;
1437 var kFrameDetailsNameValueSize = 2;
1439 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1440 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1441 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
1444 * Wrapper for the frame details information retreived from the VM. The frame
1445 * details from the VM is an array with the following content. See runtime.cc
1446 * Runtime_GetFrameDetails.
1452 * 5: Source position
1455 * 8: Flags (debugger frame, optimized frame, inlined frame index)
1456 * Arguments name, value
1457 * Locals name, value
1458 * Return value if any
1459 * @param {number} break_id Current break id
1460 * @param {number} index Frame number
1463 function FrameDetails(break_id, index) {
1464 this.break_id_ = break_id;
1465 this.details_ = %GetFrameDetails(break_id, index);
1469 FrameDetails.prototype.frameId = function() {
1470 %CheckExecutionState(this.break_id_);
1471 return this.details_[kFrameDetailsFrameIdIndex];
1475 FrameDetails.prototype.receiver = function() {
1476 %CheckExecutionState(this.break_id_);
1477 return this.details_[kFrameDetailsReceiverIndex];
1481 FrameDetails.prototype.func = function() {
1482 %CheckExecutionState(this.break_id_);
1483 return this.details_[kFrameDetailsFunctionIndex];
1487 FrameDetails.prototype.isConstructCall = function() {
1488 %CheckExecutionState(this.break_id_);
1489 return this.details_[kFrameDetailsConstructCallIndex];
1493 FrameDetails.prototype.isAtReturn = function() {
1494 %CheckExecutionState(this.break_id_);
1495 return this.details_[kFrameDetailsAtReturnIndex];
1499 FrameDetails.prototype.isDebuggerFrame = function() {
1500 %CheckExecutionState(this.break_id_);
1501 var f = kFrameDetailsFlagDebuggerFrameMask;
1502 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1506 FrameDetails.prototype.isOptimizedFrame = function() {
1507 %CheckExecutionState(this.break_id_);
1508 var f = kFrameDetailsFlagOptimizedFrameMask;
1509 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1513 FrameDetails.prototype.isInlinedFrame = function() {
1514 return this.inlinedFrameIndex() > 0;
1518 FrameDetails.prototype.inlinedFrameIndex = function() {
1519 %CheckExecutionState(this.break_id_);
1520 var f = kFrameDetailsFlagInlinedFrameIndexMask;
1521 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
1525 FrameDetails.prototype.argumentCount = function() {
1526 %CheckExecutionState(this.break_id_);
1527 return this.details_[kFrameDetailsArgumentCountIndex];
1531 FrameDetails.prototype.argumentName = function(index) {
1532 %CheckExecutionState(this.break_id_);
1533 if (index >= 0 && index < this.argumentCount()) {
1534 return this.details_[kFrameDetailsFirstDynamicIndex +
1535 index * kFrameDetailsNameValueSize +
1536 kFrameDetailsNameIndex];
1541 FrameDetails.prototype.argumentValue = function(index) {
1542 %CheckExecutionState(this.break_id_);
1543 if (index >= 0 && index < this.argumentCount()) {
1544 return this.details_[kFrameDetailsFirstDynamicIndex +
1545 index * kFrameDetailsNameValueSize +
1546 kFrameDetailsValueIndex];
1551 FrameDetails.prototype.localCount = function() {
1552 %CheckExecutionState(this.break_id_);
1553 return this.details_[kFrameDetailsLocalCountIndex];
1557 FrameDetails.prototype.sourcePosition = function() {
1558 %CheckExecutionState(this.break_id_);
1559 return this.details_[kFrameDetailsSourcePositionIndex];
1563 FrameDetails.prototype.localName = function(index) {
1564 %CheckExecutionState(this.break_id_);
1565 if (index >= 0 && index < this.localCount()) {
1566 var locals_offset = kFrameDetailsFirstDynamicIndex +
1567 this.argumentCount() * kFrameDetailsNameValueSize;
1568 return this.details_[locals_offset +
1569 index * kFrameDetailsNameValueSize +
1570 kFrameDetailsNameIndex];
1575 FrameDetails.prototype.localValue = function(index) {
1576 %CheckExecutionState(this.break_id_);
1577 if (index >= 0 && index < this.localCount()) {
1578 var locals_offset = kFrameDetailsFirstDynamicIndex +
1579 this.argumentCount() * kFrameDetailsNameValueSize;
1580 return this.details_[locals_offset +
1581 index * kFrameDetailsNameValueSize +
1582 kFrameDetailsValueIndex];
1587 FrameDetails.prototype.returnValue = function() {
1588 %CheckExecutionState(this.break_id_);
1589 var return_value_offset =
1590 kFrameDetailsFirstDynamicIndex +
1591 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1592 if (this.details_[kFrameDetailsAtReturnIndex]) {
1593 return this.details_[return_value_offset];
1598 FrameDetails.prototype.scopeCount = function() {
1599 if (IS_UNDEFINED(this.scopeCount_)) {
1600 this.scopeCount_ = %GetScopeCount(this.break_id_, this.frameId());
1602 return this.scopeCount_;
1606 FrameDetails.prototype.stepInPositionsImpl = function() {
1607 return %GetStepInPositions(this.break_id_, this.frameId());
1612 * Mirror object for stack frames.
1613 * @param {number} break_id The break id in the VM for which this frame is
1615 * @param {number} index The frame index (top frame is index 0)
1619 function FrameMirror(break_id, index) {
1620 %_CallFunction(this, FRAME_TYPE, Mirror);
1621 this.break_id_ = break_id;
1622 this.index_ = index;
1623 this.details_ = new FrameDetails(break_id, index);
1625 inherits(FrameMirror, Mirror);
1628 FrameMirror.prototype.details = function() {
1629 return this.details_;
1633 FrameMirror.prototype.index = function() {
1638 FrameMirror.prototype.func = function() {
1643 // Get the function for this frame from the VM.
1644 var f = this.details_.func();
1646 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1647 // value returned from the VM might be a string if the function for the
1648 // frame is unresolved.
1649 if (IS_FUNCTION(f)) {
1650 return this.func_ = MakeMirror(f);
1652 return new UnresolvedFunctionMirror(f);
1657 FrameMirror.prototype.receiver = function() {
1658 return MakeMirror(this.details_.receiver());
1662 FrameMirror.prototype.isConstructCall = function() {
1663 return this.details_.isConstructCall();
1667 FrameMirror.prototype.isAtReturn = function() {
1668 return this.details_.isAtReturn();
1672 FrameMirror.prototype.isDebuggerFrame = function() {
1673 return this.details_.isDebuggerFrame();
1677 FrameMirror.prototype.isOptimizedFrame = function() {
1678 return this.details_.isOptimizedFrame();
1682 FrameMirror.prototype.isInlinedFrame = function() {
1683 return this.details_.isInlinedFrame();
1687 FrameMirror.prototype.inlinedFrameIndex = function() {
1688 return this.details_.inlinedFrameIndex();
1692 FrameMirror.prototype.argumentCount = function() {
1693 return this.details_.argumentCount();
1697 FrameMirror.prototype.argumentName = function(index) {
1698 return this.details_.argumentName(index);
1702 FrameMirror.prototype.argumentValue = function(index) {
1703 return MakeMirror(this.details_.argumentValue(index));
1707 FrameMirror.prototype.localCount = function() {
1708 return this.details_.localCount();
1712 FrameMirror.prototype.localName = function(index) {
1713 return this.details_.localName(index);
1717 FrameMirror.prototype.localValue = function(index) {
1718 return MakeMirror(this.details_.localValue(index));
1722 FrameMirror.prototype.returnValue = function() {
1723 return MakeMirror(this.details_.returnValue());
1727 FrameMirror.prototype.sourcePosition = function() {
1728 return this.details_.sourcePosition();
1732 FrameMirror.prototype.sourceLocation = function() {
1733 var func = this.func();
1734 if (func.resolved()) {
1735 var script = func.script();
1737 return script.locationFromPosition(this.sourcePosition(), true);
1743 FrameMirror.prototype.sourceLine = function() {
1744 var location = this.sourceLocation();
1746 return location.line;
1751 FrameMirror.prototype.sourceColumn = function() {
1752 var location = this.sourceLocation();
1754 return location.column;
1759 FrameMirror.prototype.sourceLineText = function() {
1760 var location = this.sourceLocation();
1762 return location.sourceText();
1767 FrameMirror.prototype.scopeCount = function() {
1768 return this.details_.scopeCount();
1772 FrameMirror.prototype.scope = function(index) {
1773 return new ScopeMirror(this, UNDEFINED, index);
1777 FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) {
1778 var scopeDetails = %GetAllScopesDetails(this.break_id_,
1779 this.details_.frameId(),
1780 this.details_.inlinedFrameIndex(),
1781 !!opt_ignore_nested_scopes);
1783 for (var i = 0; i < scopeDetails.length; ++i) {
1784 result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
1790 FrameMirror.prototype.stepInPositions = function() {
1791 var script = this.func().script();
1792 var funcOffset = this.func().sourcePosition_();
1794 var stepInRaw = this.details_.stepInPositionsImpl();
1797 for (var i = 0; i < stepInRaw.length; i++) {
1799 var offset = script.locationFromPosition(funcOffset + stepInRaw[i],
1801 serializeLocationFields(offset, posStruct);
1813 FrameMirror.prototype.evaluate = function(source, disable_break,
1814 opt_context_object) {
1815 return MakeMirror(%DebugEvaluate(this.break_id_,
1816 this.details_.frameId(),
1817 this.details_.inlinedFrameIndex(),
1819 Boolean(disable_break),
1820 opt_context_object));
1824 FrameMirror.prototype.invocationText = function() {
1825 // Format frame invoaction (receiver, function and arguments).
1827 var func = this.func();
1828 var receiver = this.receiver();
1829 if (this.isConstructCall()) {
1830 // For constructor frames display new followed by the function name.
1832 result += func.name() ? func.name() : '[anonymous]';
1833 } else if (this.isDebuggerFrame()) {
1834 result += '[debugger]';
1836 // If the receiver has a className which is 'global' don't display it.
1837 var display_receiver =
1838 !receiver.className || (receiver.className() != 'global');
1839 if (display_receiver) {
1840 result += receiver.toText();
1842 // Try to find the function as a property in the receiver. Include the
1843 // prototype chain in the lookup.
1844 var property = GetUndefinedMirror();
1845 if (receiver.isObject()) {
1846 for (var r = receiver;
1847 !r.isNull() && property.isUndefined();
1848 r = r.protoObject()) {
1849 property = r.lookupProperty(func);
1852 if (!property.isUndefined()) {
1853 // The function invoked was found on the receiver. Use the property name
1854 // for the backtrace.
1855 if (!property.isIndexed()) {
1856 if (display_receiver) {
1859 result += property.name();
1862 result += property.name();
1865 // Also known as - if the name in the function doesn't match the name
1866 // under which it was looked up.
1867 if (func.name() && func.name() != property.name()) {
1868 result += '(aka ' + func.name() + ')';
1871 // The function invoked was not found on the receiver. Use the function
1872 // name if available for the backtrace.
1873 if (display_receiver) {
1876 result += func.name() ? func.name() : '[anonymous]';
1880 // Render arguments for normal frames.
1881 if (!this.isDebuggerFrame()) {
1883 for (var i = 0; i < this.argumentCount(); i++) {
1884 if (i != 0) result += ', ';
1885 if (this.argumentName(i)) {
1886 result += this.argumentName(i);
1889 result += this.argumentValue(i).toText();
1894 if (this.isAtReturn()) {
1895 result += ' returning ';
1896 result += this.returnValue().toText();
1903 FrameMirror.prototype.sourceAndPositionText = function() {
1904 // Format source and position.
1906 var func = this.func();
1907 if (func.resolved()) {
1908 var script = func.script();
1910 if (script.name()) {
1911 result += script.name();
1913 result += '[unnamed]';
1915 if (!this.isDebuggerFrame()) {
1916 var location = this.sourceLocation();
1918 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1919 result += ' column ';
1920 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1921 if (!IS_UNDEFINED(this.sourcePosition())) {
1922 result += ' (position ' + (this.sourcePosition() + 1) + ')';
1926 result += '[no source]';
1929 result += '[unresolved]';
1936 FrameMirror.prototype.localsText = function() {
1937 // Format local variables.
1939 var locals_count = this.localCount();
1940 if (locals_count > 0) {
1941 for (var i = 0; i < locals_count; ++i) {
1943 result += this.localName(i);
1945 result += this.localValue(i).toText();
1946 if (i < locals_count - 1) result += '\n';
1954 FrameMirror.prototype.restart = function() {
1955 var result = %LiveEditRestartFrame(this.break_id_, this.index_);
1956 if (IS_UNDEFINED(result)) {
1957 result = "Failed to find requested frame";
1963 FrameMirror.prototype.toText = function(opt_locals) {
1965 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1967 result += this.invocationText();
1969 result += this.sourceAndPositionText();
1972 result += this.localsText();
1978 var kScopeDetailsTypeIndex = 0;
1979 var kScopeDetailsObjectIndex = 1;
1981 function ScopeDetails(frame, fun, index, opt_details) {
1983 this.break_id_ = frame.break_id_;
1984 this.details_ = opt_details ||
1985 %GetScopeDetails(frame.break_id_,
1986 frame.details_.frameId(),
1987 frame.details_.inlinedFrameIndex(),
1989 this.frame_id_ = frame.details_.frameId();
1990 this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
1992 this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index);
1993 this.fun_value_ = fun.value();
1994 this.break_id_ = undefined;
1996 this.index_ = index;
2000 ScopeDetails.prototype.type = function() {
2001 if (!IS_UNDEFINED(this.break_id_)) {
2002 %CheckExecutionState(this.break_id_);
2004 return this.details_[kScopeDetailsTypeIndex];
2008 ScopeDetails.prototype.object = function() {
2009 if (!IS_UNDEFINED(this.break_id_)) {
2010 %CheckExecutionState(this.break_id_);
2012 return this.details_[kScopeDetailsObjectIndex];
2016 ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
2018 if (!IS_UNDEFINED(this.break_id_)) {
2019 %CheckExecutionState(this.break_id_);
2020 raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_,
2021 this.inlined_frame_id_, this.index_, name, new_value);
2023 raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_,
2027 throw new Error("Failed to set variable value");
2033 * Mirror object for scope of frame or function. Either frame or function must
2035 * @param {FrameMirror} frame The frame this scope is a part of
2036 * @param {FunctionMirror} function The function this scope is a part of
2037 * @param {number} index The scope index in the frame
2038 * @param {Array=} opt_details Raw scope details data
2042 function ScopeMirror(frame, function, index, opt_details) {
2043 %_CallFunction(this, SCOPE_TYPE, Mirror);
2045 this.frame_index_ = frame.index_;
2047 this.frame_index_ = undefined;
2049 this.scope_index_ = index;
2050 this.details_ = new ScopeDetails(frame, function, index, opt_details);
2052 inherits(ScopeMirror, Mirror);
2055 ScopeMirror.prototype.details = function() {
2056 return this.details_;
2060 ScopeMirror.prototype.frameIndex = function() {
2061 return this.frame_index_;
2065 ScopeMirror.prototype.scopeIndex = function() {
2066 return this.scope_index_;
2070 ScopeMirror.prototype.scopeType = function() {
2071 return this.details_.type();
2075 ScopeMirror.prototype.scopeObject = function() {
2076 // For local and closure scopes create a transient mirror as these objects are
2077 // created on the fly materializing the local or closure scopes and
2078 // therefore will not preserve identity.
2079 var transient = this.scopeType() == ScopeType.Local ||
2080 this.scopeType() == ScopeType.Closure;
2081 return MakeMirror(this.details_.object(), transient);
2085 ScopeMirror.prototype.setVariableValue = function(name, new_value) {
2086 this.details_.setVariableValueImpl(name, new_value);
2091 * Mirror object for script source.
2092 * @param {Script} script The script object
2096 function ScriptMirror(script) {
2097 %_CallFunction(this, SCRIPT_TYPE, Mirror);
2098 this.script_ = script;
2099 this.context_ = new ContextMirror(script.context_data);
2100 this.allocateHandle_();
2102 inherits(ScriptMirror, Mirror);
2105 ScriptMirror.prototype.value = function() {
2106 return this.script_;
2110 ScriptMirror.prototype.name = function() {
2111 return this.script_.name || this.script_.nameOrSourceURL();
2115 ScriptMirror.prototype.id = function() {
2116 return this.script_.id;
2120 ScriptMirror.prototype.source = function() {
2121 return this.script_.source;
2125 ScriptMirror.prototype.setSource = function(source) {
2126 %DebugSetScriptSource(this.script_, source);
2130 ScriptMirror.prototype.lineOffset = function() {
2131 return this.script_.line_offset;
2135 ScriptMirror.prototype.columnOffset = function() {
2136 return this.script_.column_offset;
2140 ScriptMirror.prototype.data = function() {
2141 return this.script_.data;
2145 ScriptMirror.prototype.scriptType = function() {
2146 return this.script_.type;
2150 ScriptMirror.prototype.compilationType = function() {
2151 return this.script_.compilation_type;
2155 ScriptMirror.prototype.lineCount = function() {
2156 return this.script_.lineCount();
2160 ScriptMirror.prototype.locationFromPosition = function(
2161 position, include_resource_offset) {
2162 return this.script_.locationFromPosition(position, include_resource_offset);
2166 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
2167 return this.script_.sourceSlice(opt_from_line, opt_to_line);
2171 ScriptMirror.prototype.context = function() {
2172 return this.context_;
2176 ScriptMirror.prototype.evalFromScript = function() {
2177 return MakeMirror(this.script_.eval_from_script);
2181 ScriptMirror.prototype.evalFromFunctionName = function() {
2182 return MakeMirror(this.script_.eval_from_function_name);
2186 ScriptMirror.prototype.evalFromLocation = function() {
2187 var eval_from_script = this.evalFromScript();
2188 if (!eval_from_script.isUndefined()) {
2189 var position = this.script_.eval_from_script_position;
2190 return eval_from_script.locationFromPosition(position, true);
2195 ScriptMirror.prototype.toText = function() {
2197 result += this.name();
2198 result += ' (lines: ';
2199 if (this.lineOffset() > 0) {
2200 result += this.lineOffset();
2202 result += this.lineOffset() + this.lineCount() - 1;
2204 result += this.lineCount();
2212 * Mirror object for context.
2213 * @param {Object} data The context data
2217 function ContextMirror(data) {
2218 %_CallFunction(this, CONTEXT_TYPE, Mirror);
2220 this.allocateHandle_();
2222 inherits(ContextMirror, Mirror);
2225 ContextMirror.prototype.data = function() {
2231 * Returns a mirror serializer
2233 * @param {boolean} details Set to true to include details
2234 * @param {Object} options Options comtrolling the serialization
2235 * The following options can be set:
2236 * includeSource: include ths full source of scripts
2237 * @returns {MirrorSerializer} mirror serializer
2239 function MakeMirrorSerializer(details, options) {
2240 return new JSONProtocolSerializer(details, options);
2245 * Object for serializing a mirror objects and its direct references.
2246 * @param {boolean} details Indicates whether to include details for the mirror
2250 function JSONProtocolSerializer(details, options) {
2251 this.details_ = details;
2252 this.options_ = options;
2253 this.mirrors_ = [ ];
2258 * Returns a serialization of an object reference. The referenced object are
2259 * added to the serialization state.
2261 * @param {Mirror} mirror The mirror to serialize
2262 * @returns {String} JSON serialization
2264 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
2265 return this.serialize_(mirror, true, true);
2270 * Returns a serialization of an object value. The referenced objects are
2271 * added to the serialization state.
2273 * @param {Mirror} mirror The mirror to serialize
2274 * @returns {String} JSON serialization
2276 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
2277 var json = this.serialize_(mirror, false, true);
2283 * Returns a serialization of all the objects referenced.
2285 * @param {Mirror} mirror The mirror to serialize.
2286 * @returns {Array.<Object>} Array of the referenced objects converted to
2289 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
2290 // Collect the protocol representation of the referenced objects in an array.
2293 // Get the number of referenced objects.
2294 var count = this.mirrors_.length;
2296 for (var i = 0; i < count; i++) {
2297 content.push(this.serialize_(this.mirrors_[i], false, false));
2304 JSONProtocolSerializer.prototype.includeSource_ = function() {
2305 return this.options_ && this.options_.includeSource;
2309 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2310 return this.options_ && this.options_.inlineRefs;
2314 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2315 if (IS_UNDEFINED(this.options_) ||
2316 IS_UNDEFINED(this.options_.maxStringLength)) {
2317 return kMaxProtocolStringLength;
2319 return this.options_.maxStringLength;
2323 JSONProtocolSerializer.prototype.add_ = function(mirror) {
2324 // If this mirror is already in the list just return.
2325 for (var i = 0; i < this.mirrors_.length; i++) {
2326 if (this.mirrors_[i] === mirror) {
2331 // Add the mirror to the list of mirrors to be serialized.
2332 this.mirrors_.push(mirror);
2337 * Formats mirror object to protocol reference object with some data that can
2338 * be used to display the value in debugger.
2339 * @param {Mirror} mirror Mirror to serialize.
2340 * @return {Object} Protocol reference object.
2342 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
2345 o.ref = mirror.handle();
2346 o.type = mirror.type();
2347 switch (mirror.type()) {
2348 case UNDEFINED_TYPE:
2352 o.value = mirror.value();
2355 o.value = mirror.getTruncatedValue(this.maxStringLength_());
2358 o.description = mirror.description();
2361 o.name = mirror.name();
2362 o.inferredName = mirror.inferredName();
2363 if (mirror.script()) {
2364 o.scriptId = mirror.script().id();
2369 o.value = mirror.toText();
2372 o.className = mirror.className();
2379 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2381 // If serializing a reference to a mirror just return the reference and add
2382 // the mirror to the referenced mirrors.
2384 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
2385 if (this.inlineRefs_() && mirror.isValue()) {
2386 return this.serializeReferenceWithDisplayData_(mirror);
2389 return {'ref' : mirror.handle()};
2393 // Collect the JSON property/value pairs.
2396 // Add the mirror handle.
2397 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2398 content.handle = mirror.handle();
2401 // Always add the type.
2402 content.type = mirror.type();
2404 switch (mirror.type()) {
2405 case UNDEFINED_TYPE:
2407 // Undefined and null are represented just by their type.
2411 // Boolean values are simply represented by their value.
2412 content.value = mirror.value();
2416 // Number values are simply represented by their value.
2417 content.value = NumberToJSON_(mirror.value());
2421 // String values might have their value cropped to keep down size.
2422 if (this.maxStringLength_() != -1 &&
2423 mirror.length() > this.maxStringLength_()) {
2424 var str = mirror.getTruncatedValue(this.maxStringLength_());
2425 content.value = str;
2426 content.fromIndex = 0;
2427 content.toIndex = this.maxStringLength_();
2429 content.value = mirror.value();
2431 content.length = mirror.length();
2435 content.description = mirror.description();
2443 // Add object representation.
2444 this.serializeObject_(mirror, content, details);
2448 case INTERNAL_PROPERTY_TYPE:
2449 throw new Error('PropertyMirror cannot be serialized independently');
2453 // Add object representation.
2454 this.serializeFrame_(mirror, content);
2458 // Add object representation.
2459 this.serializeScope_(mirror, content);
2463 // Script is represented by id, name and source attributes.
2464 if (mirror.name()) {
2465 content.name = mirror.name();
2467 content.id = mirror.id();
2468 content.lineOffset = mirror.lineOffset();
2469 content.columnOffset = mirror.columnOffset();
2470 content.lineCount = mirror.lineCount();
2471 if (mirror.data()) {
2472 content.data = mirror.data();
2474 if (this.includeSource_()) {
2475 content.source = mirror.source();
2477 var sourceStart = mirror.source().substring(0, 80);
2478 content.sourceStart = sourceStart;
2480 content.sourceLength = mirror.source().length;
2481 content.scriptType = mirror.scriptType();
2482 content.compilationType = mirror.compilationType();
2483 // For compilation type eval emit information on the script from which
2484 // eval was called if a script is present.
2485 if (mirror.compilationType() == 1 &&
2486 mirror.evalFromScript()) {
2487 content.evalFromScript =
2488 this.serializeReference(mirror.evalFromScript());
2489 var evalFromLocation = mirror.evalFromLocation();
2490 if (evalFromLocation) {
2491 content.evalFromLocation = { line: evalFromLocation.line,
2492 column: evalFromLocation.column };
2494 if (mirror.evalFromFunctionName()) {
2495 content.evalFromFunctionName = mirror.evalFromFunctionName();
2498 if (mirror.context()) {
2499 content.context = this.serializeReference(mirror.context());
2504 content.data = mirror.data();
2508 // Always add the text representation.
2509 content.text = mirror.toText();
2511 // Create and return the JSON string.
2517 * Serialize object information to the following JSON format.
2519 * {"className":"<class name>",
2520 * "constructorFunction":{"ref":<number>},
2521 * "protoObject":{"ref":<number>},
2522 * "prototypeObject":{"ref":<number>},
2523 * "namedInterceptor":<boolean>,
2524 * "indexedInterceptor":<boolean>,
2525 * "properties":[<properties>],
2526 * "internalProperties":[<internal properties>]}
2528 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2530 // Add general object properties.
2531 content.className = mirror.className();
2532 content.constructorFunction =
2533 this.serializeReference(mirror.constructorFunction());
2534 content.protoObject = this.serializeReference(mirror.protoObject());
2535 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2537 // Add flags to indicate whether there are interceptors.
2538 if (mirror.hasNamedInterceptor()) {
2539 content.namedInterceptor = true;
2541 if (mirror.hasIndexedInterceptor()) {
2542 content.indexedInterceptor = true;
2545 if (mirror.isFunction()) {
2546 // Add function specific properties.
2547 content.name = mirror.name();
2548 if (!IS_UNDEFINED(mirror.inferredName())) {
2549 content.inferredName = mirror.inferredName();
2551 content.resolved = mirror.resolved();
2552 if (mirror.resolved()) {
2553 content.source = mirror.source();
2555 if (mirror.script()) {
2556 content.script = this.serializeReference(mirror.script());
2557 content.scriptId = mirror.script().id();
2559 serializeLocationFields(mirror.sourceLocation(), content);
2562 content.scopes = [];
2563 for (var i = 0; i < mirror.scopeCount(); i++) {
2564 var scope = mirror.scope(i);
2565 content.scopes.push({
2566 type: scope.scopeType(),
2572 if (mirror.isDate()) {
2573 // Add date specific properties.
2574 content.value = mirror.value();
2577 if (mirror.isPromise()) {
2578 // Add promise specific properties.
2579 content.status = mirror.status();
2580 content.promiseValue = this.serializeReference(mirror.promiseValue());
2583 // Add actual properties - named properties followed by indexed properties.
2584 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2585 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2586 var p = new Array(propertyNames.length + propertyIndexes.length);
2587 for (var i = 0; i < propertyNames.length; i++) {
2588 var propertyMirror = mirror.property(propertyNames[i]);
2589 p[i] = this.serializeProperty_(propertyMirror);
2591 this.add_(propertyMirror.value());
2594 for (var i = 0; i < propertyIndexes.length; i++) {
2595 var propertyMirror = mirror.property(propertyIndexes[i]);
2596 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2598 this.add_(propertyMirror.value());
2601 content.properties = p;
2603 var internalProperties = mirror.internalProperties();
2604 if (internalProperties.length > 0) {
2606 for (var i = 0; i < internalProperties.length; i++) {
2607 ip.push(this.serializeInternalProperty_(internalProperties[i]));
2609 content.internalProperties = ip;
2615 * Serialize location information to the following JSON format:
2617 * "position":"<position>",
2619 * "column":"<column>",
2621 * @param {SourceLocation} location The location to serialize, may be undefined.
2623 function serializeLocationFields (location, content) {
2627 content.position = location.position;
2628 var line = location.line;
2629 if (!IS_UNDEFINED(line)) {
2630 content.line = line;
2632 var column = location.column;
2633 if (!IS_UNDEFINED(column)) {
2634 content.column = column;
2640 * Serialize property information to the following JSON format for building the
2641 * array of properties.
2643 * {"name":"<property name>",
2644 * "attributes":<number>,
2645 * "propertyType":<number>,
2648 * If the attribute for the property is PropertyAttribute.None it is not added.
2649 * If the propertyType for the property is PropertyType.Normal it is not added.
2650 * Here are a couple of examples.
2652 * {"name":"hello","ref":1}
2653 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2655 * @param {PropertyMirror} propertyMirror The property to serialize.
2656 * @returns {Object} Protocol object representing the property.
2658 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2661 result.name = propertyMirror.name();
2662 var propertyValue = propertyMirror.value();
2663 if (this.inlineRefs_() && propertyValue.isValue()) {
2664 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2666 if (propertyMirror.attributes() != PropertyAttribute.None) {
2667 result.attributes = propertyMirror.attributes();
2669 if (propertyMirror.propertyType() != PropertyType.Normal) {
2670 result.propertyType = propertyMirror.propertyType();
2672 result.ref = propertyValue.handle();
2679 * Serialize internal property information to the following JSON format for
2680 * building the array of properties.
2682 * {"name":"<property name>",
2685 * {"name":"[[BoundThis]]","ref":117}
2687 * @param {InternalPropertyMirror} propertyMirror The property to serialize.
2688 * @returns {Object} Protocol object representing the property.
2690 JSONProtocolSerializer.prototype.serializeInternalProperty_ =
2691 function(propertyMirror) {
2694 result.name = propertyMirror.name();
2695 var propertyValue = propertyMirror.value();
2696 if (this.inlineRefs_() && propertyValue.isValue()) {
2697 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2699 result.ref = propertyValue.handle();
2705 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2706 content.index = mirror.index();
2707 content.receiver = this.serializeReference(mirror.receiver());
2708 var func = mirror.func();
2709 content.func = this.serializeReference(func);
2710 var script = func.script();
2712 content.script = this.serializeReference(script);
2714 content.constructCall = mirror.isConstructCall();
2715 content.atReturn = mirror.isAtReturn();
2716 if (mirror.isAtReturn()) {
2717 content.returnValue = this.serializeReference(mirror.returnValue());
2719 content.debuggerFrame = mirror.isDebuggerFrame();
2720 var x = new Array(mirror.argumentCount());
2721 for (var i = 0; i < mirror.argumentCount(); i++) {
2723 var argument_name = mirror.argumentName(i);
2724 if (argument_name) {
2725 arg.name = argument_name;
2727 arg.value = this.serializeReference(mirror.argumentValue(i));
2730 content.arguments = x;
2731 var x = new Array(mirror.localCount());
2732 for (var i = 0; i < mirror.localCount(); i++) {
2734 local.name = mirror.localName(i);
2735 local.value = this.serializeReference(mirror.localValue(i));
2739 serializeLocationFields(mirror.sourceLocation(), content);
2740 var source_line_text = mirror.sourceLineText();
2741 if (!IS_UNDEFINED(source_line_text)) {
2742 content.sourceLineText = source_line_text;
2745 content.scopes = [];
2746 for (var i = 0; i < mirror.scopeCount(); i++) {
2747 var scope = mirror.scope(i);
2748 content.scopes.push({
2749 type: scope.scopeType(),
2756 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2757 content.index = mirror.scopeIndex();
2758 content.frameIndex = mirror.frameIndex();
2759 content.type = mirror.scopeType();
2760 content.object = this.inlineRefs_() ?
2761 this.serializeValue(mirror.scopeObject()) :
2762 this.serializeReference(mirror.scopeObject());
2767 * Convert a number to a protocol value. For all finite numbers the number
2768 * itself is returned. For non finite numbers NaN, Infinite and
2769 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
2770 * (not including the quotes) is returned.
2772 * @param {number} value The number value to convert to a protocol value.
2773 * @returns {number|string} Protocol value.
2775 function NumberToJSON_(value) {
2779 if (!NUMBER_IS_FINITE(value)) {