1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 // Handle id counters.
30 var next_transient_handle_ = -1;
33 var mirror_cache_ = [];
37 * Clear the mirror handle cache.
39 function ClearMirrorCache() {
46 * Returns the mirror for a specified value or object.
48 * @param {value or Object} value the value or object to retreive the mirror for
49 * @param {boolean} transient indicate whether this object is transient and
50 * should not be added to the mirror cache. The default is not transient.
51 * @returns {Mirror} the mirror reflects the passed value or object
53 function MakeMirror(value, opt_transient) {
56 // Look for non transient mirrors in the mirror cache.
58 for (id in mirror_cache_) {
59 mirror = mirror_cache_[id];
60 if (mirror.value() === value) {
63 // Special check for NaN as NaN == NaN is false.
64 if (mirror.isNumber() && isNaN(mirror.value()) &&
65 typeof value == 'number' && isNaN(value)) {
71 if (IS_UNDEFINED(value)) {
72 mirror = new UndefinedMirror();
73 } else if (IS_NULL(value)) {
74 mirror = new NullMirror();
75 } else if (IS_BOOLEAN(value)) {
76 mirror = new BooleanMirror(value);
77 } else if (IS_NUMBER(value)) {
78 mirror = new NumberMirror(value);
79 } else if (IS_STRING(value)) {
80 mirror = new StringMirror(value);
81 } else if (IS_ARRAY(value)) {
82 mirror = new ArrayMirror(value);
83 } else if (IS_DATE(value)) {
84 mirror = new DateMirror(value);
85 } else if (IS_FUNCTION(value)) {
86 mirror = new FunctionMirror(value);
87 } else if (IS_REGEXP(value)) {
88 mirror = new RegExpMirror(value);
89 } else if (IS_ERROR(value)) {
90 mirror = new ErrorMirror(value);
91 } else if (IS_SCRIPT(value)) {
92 mirror = new ScriptMirror(value);
94 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
97 mirror_cache_[mirror.handle()] = mirror;
103 * Returns the mirror for a specified mirror handle.
105 * @param {number} handle the handle to find the mirror for
106 * @returns {Mirror or undefiend} the mirror with the requested handle or
107 * undefined if no mirror with the requested handle was found
109 function LookupMirror(handle) {
110 return mirror_cache_[handle];
115 * Returns the mirror for the undefined value.
117 * @returns {Mirror} the mirror reflects the undefined value
119 function GetUndefinedMirror() {
120 return MakeMirror(void 0);
125 * Inherit the prototype methods from one constructor into another.
127 * The Function.prototype.inherits from lang.js rewritten as a standalone
128 * function (not on Function.prototype). NOTE: If this file is to be loaded
129 * during bootstrapping this function needs to be revritten using some native
130 * functions as prototype setup using normal JavaScript does not work as
131 * expected during bootstrapping (see mirror.js in r114903).
133 * @param {function} ctor Constructor function which needs to inherit the
135 * @param {function} superCtor Constructor function to inherit prototype from
137 function inherits(ctor, superCtor) {
138 var tempCtor = function(){};
139 tempCtor.prototype = superCtor.prototype;
140 ctor.super_ = superCtor.prototype;
141 ctor.prototype = new tempCtor();
142 ctor.prototype.constructor = ctor;
146 // Type names of the different mirrors.
147 var UNDEFINED_TYPE = 'undefined';
148 var NULL_TYPE = 'null';
149 var BOOLEAN_TYPE = 'boolean';
150 var NUMBER_TYPE = 'number';
151 var STRING_TYPE = 'string';
152 var OBJECT_TYPE = 'object';
153 var FUNCTION_TYPE = 'function';
154 var REGEXP_TYPE = 'regexp';
155 var ERROR_TYPE = 'error';
156 var PROPERTY_TYPE = 'property';
157 var FRAME_TYPE = 'frame';
158 var SCRIPT_TYPE = 'script';
159 var CONTEXT_TYPE = 'context';
160 var SCOPE_TYPE = 'scope';
162 // Maximum length when sending strings through the JSON protocol.
163 var kMaxProtocolStringLength = 80;
165 // Different kind of properties.
166 var PropertyKind = {};
167 PropertyKind.Named = 1;
168 PropertyKind.Indexed = 2;
171 // A copy of the PropertyType enum from global.h
172 var PropertyType = {};
173 PropertyType.Normal = 0;
174 PropertyType.Field = 1;
175 PropertyType.ConstantFunction = 2;
176 PropertyType.Callbacks = 3;
177 PropertyType.Handler = 4;
178 PropertyType.Interceptor = 5;
179 PropertyType.MapTransition = 6;
180 PropertyType.ExternalArrayTransition = 7;
181 PropertyType.ConstantTransition = 8;
182 PropertyType.NullDescriptor = 9;
185 // Different attributes for a property.
186 var PropertyAttribute = {};
187 PropertyAttribute.None = NONE;
188 PropertyAttribute.ReadOnly = READ_ONLY;
189 PropertyAttribute.DontEnum = DONT_ENUM;
190 PropertyAttribute.DontDelete = DONT_DELETE;
193 // A copy of the scope types from runtime.cc.
194 var ScopeType = { Global: 0,
211 // - UnresolvedFunctionMirror
222 * Base class for all mirror objects.
223 * @param {string} type The type of the mirror
226 function Mirror(type) {
231 Mirror.prototype.type = function() {
237 * Check whether the mirror reflects a value.
238 * @returns {boolean} True if the mirror reflects a value.
240 Mirror.prototype.isValue = function() {
241 return this instanceof ValueMirror;
246 * Check whether the mirror reflects the undefined value.
247 * @returns {boolean} True if the mirror reflects the undefined value.
249 Mirror.prototype.isUndefined = function() {
250 return this instanceof UndefinedMirror;
255 * Check whether the mirror reflects the null value.
256 * @returns {boolean} True if the mirror reflects the null value
258 Mirror.prototype.isNull = function() {
259 return this instanceof NullMirror;
264 * Check whether the mirror reflects a boolean value.
265 * @returns {boolean} True if the mirror reflects a boolean value
267 Mirror.prototype.isBoolean = function() {
268 return this instanceof BooleanMirror;
273 * Check whether the mirror reflects a number value.
274 * @returns {boolean} True if the mirror reflects a number value
276 Mirror.prototype.isNumber = function() {
277 return this instanceof NumberMirror;
282 * Check whether the mirror reflects a string value.
283 * @returns {boolean} True if the mirror reflects a string value
285 Mirror.prototype.isString = function() {
286 return this instanceof StringMirror;
291 * Check whether the mirror reflects an object.
292 * @returns {boolean} True if the mirror reflects an object
294 Mirror.prototype.isObject = function() {
295 return this instanceof ObjectMirror;
300 * Check whether the mirror reflects a function.
301 * @returns {boolean} True if the mirror reflects a function
303 Mirror.prototype.isFunction = function() {
304 return this instanceof FunctionMirror;
309 * Check whether the mirror reflects an unresolved function.
310 * @returns {boolean} True if the mirror reflects an unresolved function
312 Mirror.prototype.isUnresolvedFunction = function() {
313 return this instanceof UnresolvedFunctionMirror;
318 * Check whether the mirror reflects an array.
319 * @returns {boolean} True if the mirror reflects an array
321 Mirror.prototype.isArray = function() {
322 return this instanceof ArrayMirror;
327 * Check whether the mirror reflects a date.
328 * @returns {boolean} True if the mirror reflects a date
330 Mirror.prototype.isDate = function() {
331 return this instanceof DateMirror;
336 * Check whether the mirror reflects a regular expression.
337 * @returns {boolean} True if the mirror reflects a regular expression
339 Mirror.prototype.isRegExp = function() {
340 return this instanceof RegExpMirror;
345 * Check whether the mirror reflects an error.
346 * @returns {boolean} True if the mirror reflects an error
348 Mirror.prototype.isError = function() {
349 return this instanceof ErrorMirror;
354 * Check whether the mirror reflects a property.
355 * @returns {boolean} True if the mirror reflects a property
357 Mirror.prototype.isProperty = function() {
358 return this instanceof PropertyMirror;
363 * Check whether the mirror reflects a stack frame.
364 * @returns {boolean} True if the mirror reflects a stack frame
366 Mirror.prototype.isFrame = function() {
367 return this instanceof FrameMirror;
372 * Check whether the mirror reflects a script.
373 * @returns {boolean} True if the mirror reflects a script
375 Mirror.prototype.isScript = function() {
376 return this instanceof ScriptMirror;
381 * Check whether the mirror reflects a context.
382 * @returns {boolean} True if the mirror reflects a context
384 Mirror.prototype.isContext = function() {
385 return this instanceof ContextMirror;
390 * Check whether the mirror reflects a scope.
391 * @returns {boolean} True if the mirror reflects a scope
393 Mirror.prototype.isScope = function() {
394 return this instanceof ScopeMirror;
399 * Allocate a handle id for this object.
401 Mirror.prototype.allocateHandle_ = function() {
402 this.handle_ = next_handle_++;
407 * Allocate a transient handle id for this object. Transient handles are
410 Mirror.prototype.allocateTransientHandle_ = function() {
411 this.handle_ = next_transient_handle_--;
415 Mirror.prototype.toText = function() {
416 // Simpel to text which is used when on specialization in subclass.
417 return "#<" + this.constructor.name + ">";
422 * Base class for all value mirror objects.
423 * @param {string} type The type of the mirror
424 * @param {value} value The value reflected by this mirror
425 * @param {boolean} transient indicate whether this object is transient with a
430 function ValueMirror(type, value, transient) {
431 %_CallFunction(this, type, Mirror);
434 this.allocateHandle_();
436 this.allocateTransientHandle_();
439 inherits(ValueMirror, Mirror);
442 Mirror.prototype.handle = function() {
448 * Check whether this is a primitive value.
449 * @return {boolean} True if the mirror reflects a primitive value
451 ValueMirror.prototype.isPrimitive = function() {
452 var type = this.type();
453 return type === 'undefined' ||
455 type === 'boolean' ||
462 * Get the actual value reflected by this mirror.
463 * @return {value} The value reflected by this mirror
465 ValueMirror.prototype.value = function() {
471 * Mirror object for Undefined.
473 * @extends ValueMirror
475 function UndefinedMirror() {
476 %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror);
478 inherits(UndefinedMirror, ValueMirror);
481 UndefinedMirror.prototype.toText = function() {
487 * Mirror object for null.
489 * @extends ValueMirror
491 function NullMirror() {
492 %_CallFunction(this, NULL_TYPE, null, ValueMirror);
494 inherits(NullMirror, ValueMirror);
497 NullMirror.prototype.toText = function() {
503 * Mirror object for boolean values.
504 * @param {boolean} value The boolean value reflected by this mirror
506 * @extends ValueMirror
508 function BooleanMirror(value) {
509 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
511 inherits(BooleanMirror, ValueMirror);
514 BooleanMirror.prototype.toText = function() {
515 return this.value_ ? 'true' : 'false';
520 * Mirror object for number values.
521 * @param {number} value The number value reflected by this mirror
523 * @extends ValueMirror
525 function NumberMirror(value) {
526 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
528 inherits(NumberMirror, ValueMirror);
531 NumberMirror.prototype.toText = function() {
532 return %NumberToString(this.value_);
537 * Mirror object for string values.
538 * @param {string} value The string value reflected by this mirror
540 * @extends ValueMirror
542 function StringMirror(value) {
543 %_CallFunction(this, STRING_TYPE, value, ValueMirror);
545 inherits(StringMirror, ValueMirror);
548 StringMirror.prototype.length = function() {
549 return this.value_.length;
552 StringMirror.prototype.getTruncatedValue = function(maxLength) {
553 if (maxLength != -1 && this.length() > maxLength) {
554 return this.value_.substring(0, maxLength) +
555 '... (length: ' + this.length() + ')';
560 StringMirror.prototype.toText = function() {
561 return this.getTruncatedValue(kMaxProtocolStringLength);
566 * Mirror object for objects.
567 * @param {object} value The object reflected by this mirror
568 * @param {boolean} transient indicate whether this object is transient with a
571 * @extends ValueMirror
573 function ObjectMirror(value, type, transient) {
574 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
576 inherits(ObjectMirror, ValueMirror);
579 ObjectMirror.prototype.className = function() {
580 return %_ClassOf(this.value_);
584 ObjectMirror.prototype.constructorFunction = function() {
585 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
589 ObjectMirror.prototype.prototypeObject = function() {
590 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
594 ObjectMirror.prototype.protoObject = function() {
595 return MakeMirror(%DebugGetPrototype(this.value_));
600 * Return the primitive value if this is object of Boolean, Number or String
601 * type (but not Date). Otherwise return undefined.
603 ObjectMirror.prototype.primitiveValue = function() {
604 if (!IS_STRING_WRAPPER(this.value_) && !IS_NUMBER_WRAPPER(this.value_) &&
605 !IS_BOOLEAN_WRAPPER(this.value_)) {
608 var primitiveValue = %_ValueOf(this.value_);
609 if (IS_UNDEFINED(primitiveValue)) {
612 return MakeMirror(primitiveValue);
616 ObjectMirror.prototype.hasNamedInterceptor = function() {
617 // Get information on interceptors for this object.
618 var x = %GetInterceptorInfo(this.value_);
623 ObjectMirror.prototype.hasIndexedInterceptor = function() {
624 // Get information on interceptors for this object.
625 var x = %GetInterceptorInfo(this.value_);
631 * Return the property names for this object.
632 * @param {number} kind Indicate whether named, indexed or both kinds of
633 * properties are requested
634 * @param {number} limit Limit the number of names returend to the specified
636 * @return {Array} Property names for this object
638 ObjectMirror.prototype.propertyNames = function(kind, limit) {
639 // Find kind and limit and allocate array for the result
640 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
646 // Find all the named properties.
647 if (kind & PropertyKind.Named) {
648 // Get the local property names.
649 propertyNames = %GetLocalPropertyNames(this.value_);
650 total += propertyNames.length;
652 // Get names for named interceptor properties if any.
653 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
654 var namedInterceptorNames =
655 %GetNamedInterceptorPropertyNames(this.value_);
656 if (namedInterceptorNames) {
657 propertyNames = propertyNames.concat(namedInterceptorNames);
658 total += namedInterceptorNames.length;
663 // Find all the indexed properties.
664 if (kind & PropertyKind.Indexed) {
665 // Get the local element names.
666 elementNames = %GetLocalElementNames(this.value_);
667 total += elementNames.length;
669 // Get names for indexed interceptor properties.
670 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
671 var indexedInterceptorNames =
672 %GetIndexedInterceptorElementNames(this.value_);
673 if (indexedInterceptorNames) {
674 elementNames = elementNames.concat(indexedInterceptorNames);
675 total += indexedInterceptorNames.length;
679 limit = Math.min(limit || total, total);
681 var names = new Array(limit);
684 // Copy names for named properties.
685 if (kind & PropertyKind.Named) {
686 for (var i = 0; index < limit && i < propertyNames.length; i++) {
687 names[index++] = propertyNames[i];
691 // Copy names for indexed properties.
692 if (kind & PropertyKind.Indexed) {
693 for (var i = 0; index < limit && i < elementNames.length; i++) {
694 names[index++] = elementNames[i];
703 * Return the properties for this object as an array of PropertyMirror objects.
704 * @param {number} kind Indicate whether named, indexed or both kinds of
705 * properties are requested
706 * @param {number} limit Limit the number of properties returend to the
708 * @return {Array} Property mirrors for this object
710 ObjectMirror.prototype.properties = function(kind, limit) {
711 var names = this.propertyNames(kind, limit);
712 var properties = new Array(names.length);
713 for (var i = 0; i < names.length; i++) {
714 properties[i] = this.property(names[i]);
721 ObjectMirror.prototype.property = function(name) {
722 var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
724 return new PropertyMirror(this, name, details);
728 return GetUndefinedMirror();
734 * Try to find a property from its value.
735 * @param {Mirror} value The property value to look for
736 * @return {PropertyMirror} The property with the specified value. If no
737 * property was found with the specified value UndefinedMirror is returned
739 ObjectMirror.prototype.lookupProperty = function(value) {
740 var properties = this.properties();
742 // Look for property value in properties.
743 for (var i = 0; i < properties.length; i++) {
745 // Skip properties which are defined through assessors.
746 var property = properties[i];
747 if (property.propertyType() != PropertyType.Callbacks) {
748 if (%_ObjectEquals(property.value_, value.value_)) {
755 return GetUndefinedMirror();
760 * Returns objects which has direct references to this object
761 * @param {number} opt_max_objects Optional parameter specifying the maximum
762 * number of referencing objects to return.
763 * @return {Array} The objects which has direct references to this object.
765 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
766 // Find all objects with direct references to this object.
767 var result = %DebugReferencedBy(this.value_,
768 Mirror.prototype, opt_max_objects || 0);
770 // Make mirrors for all the references found.
771 for (var i = 0; i < result.length; i++) {
772 result[i] = MakeMirror(result[i]);
779 ObjectMirror.prototype.toText = function() {
781 var ctor = this.constructorFunction();
782 if (!ctor.isFunction()) {
783 name = this.className();
787 name = this.className();
790 return '#<' + name + '>';
795 * Mirror object for functions.
796 * @param {function} value The function object reflected by this mirror.
798 * @extends ObjectMirror
800 function FunctionMirror(value) {
801 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
802 this.resolved_ = true;
804 inherits(FunctionMirror, ObjectMirror);
808 * Returns whether the function is resolved.
809 * @return {boolean} True if the function is resolved. Unresolved functions can
810 * only originate as functions from stack frames
812 FunctionMirror.prototype.resolved = function() {
813 return this.resolved_;
818 * Returns the name of the function.
819 * @return {string} Name of the function
821 FunctionMirror.prototype.name = function() {
822 return %FunctionGetName(this.value_);
827 * Returns the inferred name of the function.
828 * @return {string} Name of the function
830 FunctionMirror.prototype.inferredName = function() {
831 return %FunctionGetInferredName(this.value_);
836 * Returns the source code for the function.
837 * @return {string or undefined} The source code for the function. If the
838 * function is not resolved undefined will be returned.
840 FunctionMirror.prototype.source = function() {
841 // Return source if function is resolved. Otherwise just fall through to
843 if (this.resolved()) {
844 return builtins.FunctionSourceString(this.value_);
850 * Returns the script object for the function.
851 * @return {ScriptMirror or undefined} Script object for the function or
852 * undefined if the function has no script
854 FunctionMirror.prototype.script = function() {
855 // Return script if function is resolved. Otherwise just fall through
856 // to return undefined.
857 if (this.resolved()) {
858 var script = %FunctionGetScript(this.value_);
860 return MakeMirror(script);
867 * Returns the script source position for the function. Only makes sense
868 * for functions which has a script defined.
869 * @return {Number or undefined} in-script position for the function
871 FunctionMirror.prototype.sourcePosition_ = function() {
872 // Return script if function is resolved. Otherwise just fall through
873 // to return undefined.
874 if (this.resolved()) {
875 return %FunctionGetScriptSourcePosition(this.value_);
881 * Returns the script source location object for the function. Only makes sense
882 * for functions which has a script defined.
883 * @return {Location or undefined} in-script location for the function begin
885 FunctionMirror.prototype.sourceLocation = function() {
886 if (this.resolved() && this.script()) {
887 return this.script().locationFromPosition(this.sourcePosition_(),
894 * Returns objects constructed by this function.
895 * @param {number} opt_max_instances Optional parameter specifying the maximum
896 * number of instances to return.
897 * @return {Array or undefined} The objects constructed by this function.
899 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
900 if (this.resolved()) {
901 // Find all objects constructed from this function.
902 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
904 // Make mirrors for all the instances found.
905 for (var i = 0; i < result.length; i++) {
906 result[i] = MakeMirror(result[i]);
916 FunctionMirror.prototype.scopeCount = function() {
917 if (this.resolved()) {
918 return %GetFunctionScopeCount(this.value());
925 FunctionMirror.prototype.scope = function(index) {
926 if (this.resolved()) {
927 return new ScopeMirror(void 0, this, index);
932 FunctionMirror.prototype.toText = function() {
933 return this.source();
938 * Mirror object for unresolved functions.
939 * @param {string} value The name for the unresolved function reflected by this
942 * @extends ObjectMirror
944 function UnresolvedFunctionMirror(value) {
945 // Construct this using the ValueMirror as an unresolved function is not a
946 // real object but just a string.
947 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
948 this.propertyCount_ = 0;
949 this.elementCount_ = 0;
950 this.resolved_ = false;
952 inherits(UnresolvedFunctionMirror, FunctionMirror);
955 UnresolvedFunctionMirror.prototype.className = function() {
960 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
961 return GetUndefinedMirror();
965 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
966 return GetUndefinedMirror();
970 UnresolvedFunctionMirror.prototype.protoObject = function() {
971 return GetUndefinedMirror();
975 UnresolvedFunctionMirror.prototype.name = function() {
980 UnresolvedFunctionMirror.prototype.inferredName = function() {
985 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
991 * Mirror object for arrays.
992 * @param {Array} value The Array object reflected by this mirror
994 * @extends ObjectMirror
996 function ArrayMirror(value) {
997 %_CallFunction(this, value, ObjectMirror);
999 inherits(ArrayMirror, ObjectMirror);
1002 ArrayMirror.prototype.length = function() {
1003 return this.value_.length;
1007 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
1009 var from_index = opt_from_index || 0;
1010 var to_index = opt_to_index || this.length() - 1;
1011 if (from_index > to_index) return new Array();
1012 var values = new Array(to_index - from_index + 1);
1013 for (var i = from_index; i <= to_index; i++) {
1014 var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
1017 value = new PropertyMirror(this, i, details);
1019 value = GetUndefinedMirror();
1021 values[i - from_index] = value;
1028 * Mirror object for dates.
1029 * @param {Date} value The Date object reflected by this mirror
1031 * @extends ObjectMirror
1033 function DateMirror(value) {
1034 %_CallFunction(this, value, ObjectMirror);
1036 inherits(DateMirror, ObjectMirror);
1039 DateMirror.prototype.toText = function() {
1040 var s = JSON.stringify(this.value_);
1041 return s.substring(1, s.length - 1); // cut quotes
1046 * Mirror object for regular expressions.
1047 * @param {RegExp} value The RegExp object reflected by this mirror
1049 * @extends ObjectMirror
1051 function RegExpMirror(value) {
1052 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
1054 inherits(RegExpMirror, ObjectMirror);
1058 * Returns the source to the regular expression.
1059 * @return {string or undefined} The source to the regular expression
1061 RegExpMirror.prototype.source = function() {
1062 return this.value_.source;
1067 * Returns whether this regular expression has the global (g) flag set.
1068 * @return {boolean} Value of the global flag
1070 RegExpMirror.prototype.global = function() {
1071 return this.value_.global;
1076 * Returns whether this regular expression has the ignore case (i) flag set.
1077 * @return {boolean} Value of the ignore case flag
1079 RegExpMirror.prototype.ignoreCase = function() {
1080 return this.value_.ignoreCase;
1085 * Returns whether this regular expression has the multiline (m) flag set.
1086 * @return {boolean} Value of the multiline flag
1088 RegExpMirror.prototype.multiline = function() {
1089 return this.value_.multiline;
1093 RegExpMirror.prototype.toText = function() {
1094 // Simpel to text which is used when on specialization in subclass.
1095 return "/" + this.source() + "/";
1100 * Mirror object for error objects.
1101 * @param {Error} value The error object reflected by this mirror
1103 * @extends ObjectMirror
1105 function ErrorMirror(value) {
1106 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
1108 inherits(ErrorMirror, ObjectMirror);
1112 * Returns the message for this eror object.
1113 * @return {string or undefined} The message for this eror object
1115 ErrorMirror.prototype.message = function() {
1116 return this.value_.message;
1120 ErrorMirror.prototype.toText = function() {
1121 // Use the same text representation as in messages.js.
1124 str = %_CallFunction(this.value_, builtins.ErrorToString);
1133 * Base mirror object for properties.
1134 * @param {ObjectMirror} mirror The mirror object having this property
1135 * @param {string} name The name of the property
1136 * @param {Array} details Details about the property
1140 function PropertyMirror(mirror, name, details) {
1141 %_CallFunction(this, PROPERTY_TYPE, Mirror);
1142 this.mirror_ = mirror;
1144 this.value_ = details[0];
1145 this.details_ = details[1];
1146 if (details.length > 2) {
1147 this.exception_ = details[2];
1148 this.getter_ = details[3];
1149 this.setter_ = details[4];
1152 inherits(PropertyMirror, Mirror);
1155 PropertyMirror.prototype.isReadOnly = function() {
1156 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1160 PropertyMirror.prototype.isEnum = function() {
1161 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1165 PropertyMirror.prototype.canDelete = function() {
1166 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1170 PropertyMirror.prototype.name = function() {
1175 PropertyMirror.prototype.isIndexed = function() {
1176 for (var i = 0; i < this.name_.length; i++) {
1177 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1185 PropertyMirror.prototype.value = function() {
1186 return MakeMirror(this.value_, false);
1191 * Returns whether this property value is an exception.
1192 * @return {booolean} True if this property value is an exception
1194 PropertyMirror.prototype.isException = function() {
1195 return this.exception_ ? true : false;
1199 PropertyMirror.prototype.attributes = function() {
1200 return %DebugPropertyAttributesFromDetails(this.details_);
1204 PropertyMirror.prototype.propertyType = function() {
1205 return %DebugPropertyTypeFromDetails(this.details_);
1209 PropertyMirror.prototype.insertionIndex = function() {
1210 return %DebugPropertyIndexFromDetails(this.details_);
1215 * Returns whether this property has a getter defined through __defineGetter__.
1216 * @return {booolean} True if this property has a getter
1218 PropertyMirror.prototype.hasGetter = function() {
1219 return this.getter_ ? true : false;
1224 * Returns whether this property has a setter defined through __defineSetter__.
1225 * @return {booolean} True if this property has a setter
1227 PropertyMirror.prototype.hasSetter = function() {
1228 return this.setter_ ? true : false;
1233 * Returns the getter for this property defined through __defineGetter__.
1234 * @return {Mirror} FunctionMirror reflecting the getter function or
1235 * UndefinedMirror if there is no getter for this property
1237 PropertyMirror.prototype.getter = function() {
1238 if (this.hasGetter()) {
1239 return MakeMirror(this.getter_);
1241 return GetUndefinedMirror();
1247 * Returns the setter for this property defined through __defineSetter__.
1248 * @return {Mirror} FunctionMirror reflecting the setter function or
1249 * UndefinedMirror if there is no setter for this property
1251 PropertyMirror.prototype.setter = function() {
1252 if (this.hasSetter()) {
1253 return MakeMirror(this.setter_);
1255 return GetUndefinedMirror();
1261 * Returns whether this property is natively implemented by the host or a set
1262 * through JavaScript code.
1263 * @return {boolean} True if the property is
1264 * UndefinedMirror if there is no setter for this property
1266 PropertyMirror.prototype.isNative = function() {
1267 return (this.propertyType() == PropertyType.Interceptor) ||
1268 ((this.propertyType() == PropertyType.Callbacks) &&
1269 !this.hasGetter() && !this.hasSetter());
1273 var kFrameDetailsFrameIdIndex = 0;
1274 var kFrameDetailsReceiverIndex = 1;
1275 var kFrameDetailsFunctionIndex = 2;
1276 var kFrameDetailsArgumentCountIndex = 3;
1277 var kFrameDetailsLocalCountIndex = 4;
1278 var kFrameDetailsSourcePositionIndex = 5;
1279 var kFrameDetailsConstructCallIndex = 6;
1280 var kFrameDetailsAtReturnIndex = 7;
1281 var kFrameDetailsFlagsIndex = 8;
1282 var kFrameDetailsFirstDynamicIndex = 9;
1284 var kFrameDetailsNameIndex = 0;
1285 var kFrameDetailsValueIndex = 1;
1286 var kFrameDetailsNameValueSize = 2;
1288 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1289 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1290 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
1293 * Wrapper for the frame details information retreived from the VM. The frame
1294 * details from the VM is an array with the following content. See runtime.cc
1295 * Runtime_GetFrameDetails.
1301 * 5: Source position
1304 * 8: Flags (debugger frame, optimized frame, inlined frame index)
1305 * Arguments name, value
1306 * Locals name, value
1307 * Return value if any
1308 * @param {number} break_id Current break id
1309 * @param {number} index Frame number
1312 function FrameDetails(break_id, index) {
1313 this.break_id_ = break_id;
1314 this.details_ = %GetFrameDetails(break_id, index);
1318 FrameDetails.prototype.frameId = function() {
1319 %CheckExecutionState(this.break_id_);
1320 return this.details_[kFrameDetailsFrameIdIndex];
1324 FrameDetails.prototype.receiver = function() {
1325 %CheckExecutionState(this.break_id_);
1326 return this.details_[kFrameDetailsReceiverIndex];
1330 FrameDetails.prototype.func = function() {
1331 %CheckExecutionState(this.break_id_);
1332 return this.details_[kFrameDetailsFunctionIndex];
1336 FrameDetails.prototype.isConstructCall = function() {
1337 %CheckExecutionState(this.break_id_);
1338 return this.details_[kFrameDetailsConstructCallIndex];
1342 FrameDetails.prototype.isAtReturn = function() {
1343 %CheckExecutionState(this.break_id_);
1344 return this.details_[kFrameDetailsAtReturnIndex];
1348 FrameDetails.prototype.isDebuggerFrame = function() {
1349 %CheckExecutionState(this.break_id_);
1350 var f = kFrameDetailsFlagDebuggerFrameMask;
1351 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1355 FrameDetails.prototype.isOptimizedFrame = function() {
1356 %CheckExecutionState(this.break_id_);
1357 var f = kFrameDetailsFlagOptimizedFrameMask;
1358 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1362 FrameDetails.prototype.isInlinedFrame = function() {
1363 return this.inlinedFrameIndex() > 0;
1367 FrameDetails.prototype.inlinedFrameIndex = function() {
1368 %CheckExecutionState(this.break_id_);
1369 var f = kFrameDetailsFlagInlinedFrameIndexMask;
1370 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
1374 FrameDetails.prototype.argumentCount = function() {
1375 %CheckExecutionState(this.break_id_);
1376 return this.details_[kFrameDetailsArgumentCountIndex];
1380 FrameDetails.prototype.argumentName = function(index) {
1381 %CheckExecutionState(this.break_id_);
1382 if (index >= 0 && index < this.argumentCount()) {
1383 return this.details_[kFrameDetailsFirstDynamicIndex +
1384 index * kFrameDetailsNameValueSize +
1385 kFrameDetailsNameIndex];
1390 FrameDetails.prototype.argumentValue = function(index) {
1391 %CheckExecutionState(this.break_id_);
1392 if (index >= 0 && index < this.argumentCount()) {
1393 return this.details_[kFrameDetailsFirstDynamicIndex +
1394 index * kFrameDetailsNameValueSize +
1395 kFrameDetailsValueIndex];
1400 FrameDetails.prototype.localCount = function() {
1401 %CheckExecutionState(this.break_id_);
1402 return this.details_[kFrameDetailsLocalCountIndex];
1406 FrameDetails.prototype.sourcePosition = function() {
1407 %CheckExecutionState(this.break_id_);
1408 return this.details_[kFrameDetailsSourcePositionIndex];
1412 FrameDetails.prototype.localName = function(index) {
1413 %CheckExecutionState(this.break_id_);
1414 if (index >= 0 && index < this.localCount()) {
1415 var locals_offset = kFrameDetailsFirstDynamicIndex +
1416 this.argumentCount() * kFrameDetailsNameValueSize;
1417 return this.details_[locals_offset +
1418 index * kFrameDetailsNameValueSize +
1419 kFrameDetailsNameIndex];
1424 FrameDetails.prototype.localValue = function(index) {
1425 %CheckExecutionState(this.break_id_);
1426 if (index >= 0 && index < this.localCount()) {
1427 var locals_offset = kFrameDetailsFirstDynamicIndex +
1428 this.argumentCount() * kFrameDetailsNameValueSize;
1429 return this.details_[locals_offset +
1430 index * kFrameDetailsNameValueSize +
1431 kFrameDetailsValueIndex];
1436 FrameDetails.prototype.returnValue = function() {
1437 %CheckExecutionState(this.break_id_);
1438 var return_value_offset =
1439 kFrameDetailsFirstDynamicIndex +
1440 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1441 if (this.details_[kFrameDetailsAtReturnIndex]) {
1442 return this.details_[return_value_offset];
1447 FrameDetails.prototype.scopeCount = function() {
1448 return %GetScopeCount(this.break_id_, this.frameId());
1453 * Mirror object for stack frames.
1454 * @param {number} break_id The break id in the VM for which this frame is
1456 * @param {number} index The frame index (top frame is index 0)
1460 function FrameMirror(break_id, index) {
1461 %_CallFunction(this, FRAME_TYPE, Mirror);
1462 this.break_id_ = break_id;
1463 this.index_ = index;
1464 this.details_ = new FrameDetails(break_id, index);
1466 inherits(FrameMirror, Mirror);
1469 FrameMirror.prototype.index = function() {
1474 FrameMirror.prototype.func = function() {
1475 // Get the function for this frame from the VM.
1476 var f = this.details_.func();
1478 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1479 // value returned from the VM might be a string if the function for the
1480 // frame is unresolved.
1481 if (IS_FUNCTION(f)) {
1482 return MakeMirror(f);
1484 return new UnresolvedFunctionMirror(f);
1489 FrameMirror.prototype.receiver = function() {
1490 return MakeMirror(this.details_.receiver());
1494 FrameMirror.prototype.isConstructCall = function() {
1495 return this.details_.isConstructCall();
1499 FrameMirror.prototype.isAtReturn = function() {
1500 return this.details_.isAtReturn();
1504 FrameMirror.prototype.isDebuggerFrame = function() {
1505 return this.details_.isDebuggerFrame();
1509 FrameMirror.prototype.isOptimizedFrame = function() {
1510 return this.details_.isOptimizedFrame();
1514 FrameMirror.prototype.isInlinedFrame = function() {
1515 return this.details_.isInlinedFrame();
1519 FrameMirror.prototype.inlinedFrameIndex = function() {
1520 return this.details_.inlinedFrameIndex();
1524 FrameMirror.prototype.argumentCount = function() {
1525 return this.details_.argumentCount();
1529 FrameMirror.prototype.argumentName = function(index) {
1530 return this.details_.argumentName(index);
1534 FrameMirror.prototype.argumentValue = function(index) {
1535 return MakeMirror(this.details_.argumentValue(index));
1539 FrameMirror.prototype.localCount = function() {
1540 return this.details_.localCount();
1544 FrameMirror.prototype.localName = function(index) {
1545 return this.details_.localName(index);
1549 FrameMirror.prototype.localValue = function(index) {
1550 return MakeMirror(this.details_.localValue(index));
1554 FrameMirror.prototype.returnValue = function() {
1555 return MakeMirror(this.details_.returnValue());
1559 FrameMirror.prototype.sourcePosition = function() {
1560 return this.details_.sourcePosition();
1564 FrameMirror.prototype.sourceLocation = function() {
1565 if (this.func().resolved() && this.func().script()) {
1566 return this.func().script().locationFromPosition(this.sourcePosition(),
1572 FrameMirror.prototype.sourceLine = function() {
1573 if (this.func().resolved()) {
1574 var location = this.sourceLocation();
1576 return location.line;
1582 FrameMirror.prototype.sourceColumn = function() {
1583 if (this.func().resolved()) {
1584 var location = this.sourceLocation();
1586 return location.column;
1592 FrameMirror.prototype.sourceLineText = function() {
1593 if (this.func().resolved()) {
1594 var location = this.sourceLocation();
1596 return location.sourceText();
1602 FrameMirror.prototype.scopeCount = function() {
1603 return this.details_.scopeCount();
1607 FrameMirror.prototype.scope = function(index) {
1608 return new ScopeMirror(this, void 0, index);
1612 FrameMirror.prototype.evaluate = function(source, disable_break,
1613 opt_context_object) {
1614 var result = %DebugEvaluate(this.break_id_,
1615 this.details_.frameId(),
1616 this.details_.inlinedFrameIndex(),
1618 Boolean(disable_break),
1619 opt_context_object);
1620 return MakeMirror(result);
1624 FrameMirror.prototype.invocationText = function() {
1625 // Format frame invoaction (receiver, function and arguments).
1627 var func = this.func();
1628 var receiver = this.receiver();
1629 if (this.isConstructCall()) {
1630 // For constructor frames display new followed by the function name.
1632 result += func.name() ? func.name() : '[anonymous]';
1633 } else if (this.isDebuggerFrame()) {
1634 result += '[debugger]';
1636 // If the receiver has a className which is 'global' don't display it.
1637 var display_receiver =
1638 !receiver.className || (receiver.className() != 'global');
1639 if (display_receiver) {
1640 result += receiver.toText();
1642 // Try to find the function as a property in the receiver. Include the
1643 // prototype chain in the lookup.
1644 var property = GetUndefinedMirror();
1645 if (receiver.isObject()) {
1646 for (var r = receiver;
1647 !r.isNull() && property.isUndefined();
1648 r = r.protoObject()) {
1649 property = r.lookupProperty(func);
1652 if (!property.isUndefined()) {
1653 // The function invoked was found on the receiver. Use the property name
1654 // for the backtrace.
1655 if (!property.isIndexed()) {
1656 if (display_receiver) {
1659 result += property.name();
1662 result += property.name();
1665 // Also known as - if the name in the function doesn't match the name
1666 // under which it was looked up.
1667 if (func.name() && func.name() != property.name()) {
1668 result += '(aka ' + func.name() + ')';
1671 // The function invoked was not found on the receiver. Use the function
1672 // name if available for the backtrace.
1673 if (display_receiver) {
1676 result += func.name() ? func.name() : '[anonymous]';
1680 // Render arguments for normal frames.
1681 if (!this.isDebuggerFrame()) {
1683 for (var i = 0; i < this.argumentCount(); i++) {
1684 if (i != 0) result += ', ';
1685 if (this.argumentName(i)) {
1686 result += this.argumentName(i);
1689 result += this.argumentValue(i).toText();
1694 if (this.isAtReturn()) {
1695 result += ' returning ';
1696 result += this.returnValue().toText();
1703 FrameMirror.prototype.sourceAndPositionText = function() {
1704 // Format source and position.
1706 var func = this.func();
1707 if (func.resolved()) {
1708 if (func.script()) {
1709 if (func.script().name()) {
1710 result += func.script().name();
1712 result += '[unnamed]';
1714 if (!this.isDebuggerFrame()) {
1715 var location = this.sourceLocation();
1717 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1718 result += ' column ';
1719 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1720 if (!IS_UNDEFINED(this.sourcePosition())) {
1721 result += ' (position ' + (this.sourcePosition() + 1) + ')';
1725 result += '[no source]';
1728 result += '[unresolved]';
1735 FrameMirror.prototype.localsText = function() {
1736 // Format local variables.
1738 var locals_count = this.localCount();
1739 if (locals_count > 0) {
1740 for (var i = 0; i < locals_count; ++i) {
1742 result += this.localName(i);
1744 result += this.localValue(i).toText();
1745 if (i < locals_count - 1) result += '\n';
1753 FrameMirror.prototype.toText = function(opt_locals) {
1755 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1757 result += this.invocationText();
1759 result += this.sourceAndPositionText();
1762 result += this.localsText();
1768 var kScopeDetailsTypeIndex = 0;
1769 var kScopeDetailsObjectIndex = 1;
1771 function ScopeDetails(frame, fun, index) {
1773 this.break_id_ = frame.break_id_;
1774 this.details_ = %GetScopeDetails(frame.break_id_,
1775 frame.details_.frameId(),
1776 frame.details_.inlinedFrameIndex(),
1779 this.details_ = %GetFunctionScopeDetails(fun.value(), index);
1780 this.break_id_ = undefined;
1785 ScopeDetails.prototype.type = function() {
1786 if (!IS_UNDEFINED(this.break_id_)) {
1787 %CheckExecutionState(this.break_id_);
1789 return this.details_[kScopeDetailsTypeIndex];
1793 ScopeDetails.prototype.object = function() {
1794 if (!IS_UNDEFINED(this.break_id_)) {
1795 %CheckExecutionState(this.break_id_);
1797 return this.details_[kScopeDetailsObjectIndex];
1802 * Mirror object for scope of frame or function. Either frame or function must
1804 * @param {FrameMirror} frame The frame this scope is a part of
1805 * @param {FunctionMirror} function The function this scope is a part of
1806 * @param {number} index The scope index in the frame
1810 function ScopeMirror(frame, function, index) {
1811 %_CallFunction(this, SCOPE_TYPE, Mirror);
1813 this.frame_index_ = frame.index_;
1815 this.frame_index_ = undefined;
1817 this.scope_index_ = index;
1818 this.details_ = new ScopeDetails(frame, function, index);
1820 inherits(ScopeMirror, Mirror);
1823 ScopeMirror.prototype.frameIndex = function() {
1824 return this.frame_index_;
1828 ScopeMirror.prototype.scopeIndex = function() {
1829 return this.scope_index_;
1833 ScopeMirror.prototype.scopeType = function() {
1834 return this.details_.type();
1838 ScopeMirror.prototype.scopeObject = function() {
1839 // For local and closure scopes create a transient mirror as these objects are
1840 // created on the fly materializing the local or closure scopes and
1841 // therefore will not preserve identity.
1842 var transient = this.scopeType() == ScopeType.Local ||
1843 this.scopeType() == ScopeType.Closure;
1844 return MakeMirror(this.details_.object(), transient);
1849 * Mirror object for script source.
1850 * @param {Script} script The script object
1854 function ScriptMirror(script) {
1855 %_CallFunction(this, SCRIPT_TYPE, Mirror);
1856 this.script_ = script;
1857 this.context_ = new ContextMirror(script.context_data);
1858 this.allocateHandle_();
1860 inherits(ScriptMirror, Mirror);
1863 ScriptMirror.prototype.value = function() {
1864 return this.script_;
1868 ScriptMirror.prototype.name = function() {
1869 return this.script_.name || this.script_.nameOrSourceURL();
1873 ScriptMirror.prototype.id = function() {
1874 return this.script_.id;
1878 ScriptMirror.prototype.source = function() {
1879 return this.script_.source;
1883 ScriptMirror.prototype.setSource = function(source) {
1884 %DebugSetScriptSource(this.script_, source);
1888 ScriptMirror.prototype.lineOffset = function() {
1889 return this.script_.line_offset;
1893 ScriptMirror.prototype.columnOffset = function() {
1894 return this.script_.column_offset;
1898 ScriptMirror.prototype.data = function() {
1899 return this.script_.data;
1903 ScriptMirror.prototype.scriptType = function() {
1904 return this.script_.type;
1908 ScriptMirror.prototype.compilationType = function() {
1909 return this.script_.compilation_type;
1913 ScriptMirror.prototype.lineCount = function() {
1914 return this.script_.lineCount();
1918 ScriptMirror.prototype.locationFromPosition = function(
1919 position, include_resource_offset) {
1920 return this.script_.locationFromPosition(position, include_resource_offset);
1924 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
1925 return this.script_.sourceSlice(opt_from_line, opt_to_line);
1929 ScriptMirror.prototype.context = function() {
1930 return this.context_;
1934 ScriptMirror.prototype.evalFromScript = function() {
1935 return MakeMirror(this.script_.eval_from_script);
1939 ScriptMirror.prototype.evalFromFunctionName = function() {
1940 return MakeMirror(this.script_.eval_from_function_name);
1944 ScriptMirror.prototype.evalFromLocation = function() {
1945 var eval_from_script = this.evalFromScript();
1946 if (!eval_from_script.isUndefined()) {
1947 var position = this.script_.eval_from_script_position;
1948 return eval_from_script.locationFromPosition(position, true);
1953 ScriptMirror.prototype.toText = function() {
1955 result += this.name();
1956 result += ' (lines: ';
1957 if (this.lineOffset() > 0) {
1958 result += this.lineOffset();
1960 result += this.lineOffset() + this.lineCount() - 1;
1962 result += this.lineCount();
1970 * Mirror object for context.
1971 * @param {Object} data The context data
1975 function ContextMirror(data) {
1976 %_CallFunction(this, CONTEXT_TYPE, Mirror);
1978 this.allocateHandle_();
1980 inherits(ContextMirror, Mirror);
1983 ContextMirror.prototype.data = function() {
1989 * Returns a mirror serializer
1991 * @param {boolean} details Set to true to include details
1992 * @param {Object} options Options comtrolling the serialization
1993 * The following options can be set:
1994 * includeSource: include ths full source of scripts
1995 * @returns {MirrorSerializer} mirror serializer
1997 function MakeMirrorSerializer(details, options) {
1998 return new JSONProtocolSerializer(details, options);
2003 * Object for serializing a mirror objects and its direct references.
2004 * @param {boolean} details Indicates whether to include details for the mirror
2008 function JSONProtocolSerializer(details, options) {
2009 this.details_ = details;
2010 this.options_ = options;
2011 this.mirrors_ = [ ];
2016 * Returns a serialization of an object reference. The referenced object are
2017 * added to the serialization state.
2019 * @param {Mirror} mirror The mirror to serialize
2020 * @returns {String} JSON serialization
2022 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
2023 return this.serialize_(mirror, true, true);
2028 * Returns a serialization of an object value. The referenced objects are
2029 * added to the serialization state.
2031 * @param {Mirror} mirror The mirror to serialize
2032 * @returns {String} JSON serialization
2034 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
2035 var json = this.serialize_(mirror, false, true);
2041 * Returns a serialization of all the objects referenced.
2043 * @param {Mirror} mirror The mirror to serialize.
2044 * @returns {Array.<Object>} Array of the referenced objects converted to
2047 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
2048 // Collect the protocol representation of the referenced objects in an array.
2051 // Get the number of referenced objects.
2052 var count = this.mirrors_.length;
2054 for (var i = 0; i < count; i++) {
2055 content.push(this.serialize_(this.mirrors_[i], false, false));
2062 JSONProtocolSerializer.prototype.includeSource_ = function() {
2063 return this.options_ && this.options_.includeSource;
2067 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2068 return this.options_ && this.options_.inlineRefs;
2072 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2073 if (IS_UNDEFINED(this.options_) ||
2074 IS_UNDEFINED(this.options_.maxStringLength)) {
2075 return kMaxProtocolStringLength;
2077 return this.options_.maxStringLength;
2081 JSONProtocolSerializer.prototype.add_ = function(mirror) {
2082 // If this mirror is already in the list just return.
2083 for (var i = 0; i < this.mirrors_.length; i++) {
2084 if (this.mirrors_[i] === mirror) {
2089 // Add the mirror to the list of mirrors to be serialized.
2090 this.mirrors_.push(mirror);
2095 * Formats mirror object to protocol reference object with some data that can
2096 * be used to display the value in debugger.
2097 * @param {Mirror} mirror Mirror to serialize.
2098 * @return {Object} Protocol reference object.
2100 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
2103 o.ref = mirror.handle();
2104 o.type = mirror.type();
2105 switch (mirror.type()) {
2106 case UNDEFINED_TYPE:
2110 o.value = mirror.value();
2113 o.value = mirror.getTruncatedValue(this.maxStringLength_());
2116 o.name = mirror.name();
2117 o.inferredName = mirror.inferredName();
2118 if (mirror.script()) {
2119 o.scriptId = mirror.script().id();
2124 o.value = mirror.toText();
2127 o.className = mirror.className();
2134 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2136 // If serializing a reference to a mirror just return the reference and add
2137 // the mirror to the referenced mirrors.
2139 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
2140 if (this.inlineRefs_() && mirror.isValue()) {
2141 return this.serializeReferenceWithDisplayData_(mirror);
2144 return {'ref' : mirror.handle()};
2148 // Collect the JSON property/value pairs.
2151 // Add the mirror handle.
2152 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2153 content.handle = mirror.handle();
2156 // Always add the type.
2157 content.type = mirror.type();
2159 switch (mirror.type()) {
2160 case UNDEFINED_TYPE:
2162 // Undefined and null are represented just by their type.
2166 // Boolean values are simply represented by their value.
2167 content.value = mirror.value();
2171 // Number values are simply represented by their value.
2172 content.value = NumberToJSON_(mirror.value());
2176 // String values might have their value cropped to keep down size.
2177 if (this.maxStringLength_() != -1 &&
2178 mirror.length() > this.maxStringLength_()) {
2179 var str = mirror.getTruncatedValue(this.maxStringLength_());
2180 content.value = str;
2181 content.fromIndex = 0;
2182 content.toIndex = this.maxStringLength_();
2184 content.value = mirror.value();
2186 content.length = mirror.length();
2193 // Add object representation.
2194 this.serializeObject_(mirror, content, details);
2198 throw new Error('PropertyMirror cannot be serialized independeltly');
2202 // Add object representation.
2203 this.serializeFrame_(mirror, content);
2207 // Add object representation.
2208 this.serializeScope_(mirror, content);
2212 // Script is represented by id, name and source attributes.
2213 if (mirror.name()) {
2214 content.name = mirror.name();
2216 content.id = mirror.id();
2217 content.lineOffset = mirror.lineOffset();
2218 content.columnOffset = mirror.columnOffset();
2219 content.lineCount = mirror.lineCount();
2220 if (mirror.data()) {
2221 content.data = mirror.data();
2223 if (this.includeSource_()) {
2224 content.source = mirror.source();
2226 var sourceStart = mirror.source().substring(0, 80);
2227 content.sourceStart = sourceStart;
2229 content.sourceLength = mirror.source().length;
2230 content.scriptType = mirror.scriptType();
2231 content.compilationType = mirror.compilationType();
2232 // For compilation type eval emit information on the script from which
2233 // eval was called if a script is present.
2234 if (mirror.compilationType() == 1 &&
2235 mirror.evalFromScript()) {
2236 content.evalFromScript =
2237 this.serializeReference(mirror.evalFromScript());
2238 var evalFromLocation = mirror.evalFromLocation();
2239 if (evalFromLocation) {
2240 content.evalFromLocation = { line: evalFromLocation.line,
2241 column: evalFromLocation.column };
2243 if (mirror.evalFromFunctionName()) {
2244 content.evalFromFunctionName = mirror.evalFromFunctionName();
2247 if (mirror.context()) {
2248 content.context = this.serializeReference(mirror.context());
2253 content.data = mirror.data();
2257 // Always add the text representation.
2258 content.text = mirror.toText();
2260 // Create and return the JSON string.
2266 * Serialize object information to the following JSON format.
2268 * {"className":"<class name>",
2269 * "constructorFunction":{"ref":<number>},
2270 * "protoObject":{"ref":<number>},
2271 * "prototypeObject":{"ref":<number>},
2272 * "namedInterceptor":<boolean>,
2273 * "indexedInterceptor":<boolean>,
2274 * "properties":[<properties>]}
2276 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2278 // Add general object properties.
2279 content.className = mirror.className();
2280 content.constructorFunction =
2281 this.serializeReference(mirror.constructorFunction());
2282 content.protoObject = this.serializeReference(mirror.protoObject());
2283 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2285 var primitiveValue = mirror.primitiveValue();
2286 if (!IS_UNDEFINED(primitiveValue)) {
2287 content.primitiveValue = this.serializeReference(primitiveValue);
2290 // Add flags to indicate whether there are interceptors.
2291 if (mirror.hasNamedInterceptor()) {
2292 content.namedInterceptor = true;
2294 if (mirror.hasIndexedInterceptor()) {
2295 content.indexedInterceptor = true;
2298 // Add function specific properties.
2299 if (mirror.isFunction()) {
2300 // Add function specific properties.
2301 content.name = mirror.name();
2302 if (!IS_UNDEFINED(mirror.inferredName())) {
2303 content.inferredName = mirror.inferredName();
2305 content.resolved = mirror.resolved();
2306 if (mirror.resolved()) {
2307 content.source = mirror.source();
2309 if (mirror.script()) {
2310 content.script = this.serializeReference(mirror.script());
2311 content.scriptId = mirror.script().id();
2313 serializeLocationFields(mirror.sourceLocation(), content);
2316 content.scopes = [];
2317 for (var i = 0; i < mirror.scopeCount(); i++) {
2318 var scope = mirror.scope(i);
2319 content.scopes.push({
2320 type: scope.scopeType(),
2326 // Add date specific properties.
2327 if (mirror.isDate()) {
2328 // Add date specific properties.
2329 content.value = mirror.value();
2332 // Add actual properties - named properties followed by indexed properties.
2333 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2334 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2335 var p = new Array(propertyNames.length + propertyIndexes.length);
2336 for (var i = 0; i < propertyNames.length; i++) {
2337 var propertyMirror = mirror.property(propertyNames[i]);
2338 p[i] = this.serializeProperty_(propertyMirror);
2340 this.add_(propertyMirror.value());
2343 for (var i = 0; i < propertyIndexes.length; i++) {
2344 var propertyMirror = mirror.property(propertyIndexes[i]);
2345 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2347 this.add_(propertyMirror.value());
2350 content.properties = p;
2355 * Serialize location information to the following JSON format:
2357 * "position":"<position>",
2359 * "column":"<column>",
2361 * @param {SourceLocation} location The location to serialize, may be undefined.
2363 function serializeLocationFields (location, content) {
2367 content.position = location.position;
2368 var line = location.line;
2369 if (!IS_UNDEFINED(line)) {
2370 content.line = line;
2372 var column = location.column;
2373 if (!IS_UNDEFINED(column)) {
2374 content.column = column;
2380 * Serialize property information to the following JSON format for building the
2381 * array of properties.
2383 * {"name":"<property name>",
2384 * "attributes":<number>,
2385 * "propertyType":<number>,
2388 * If the attribute for the property is PropertyAttribute.None it is not added.
2389 * If the propertyType for the property is PropertyType.Normal it is not added.
2390 * Here are a couple of examples.
2392 * {"name":"hello","ref":1}
2393 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2395 * @param {PropertyMirror} propertyMirror The property to serialize.
2396 * @returns {Object} Protocol object representing the property.
2398 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2401 result.name = propertyMirror.name();
2402 var propertyValue = propertyMirror.value();
2403 if (this.inlineRefs_() && propertyValue.isValue()) {
2404 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2406 if (propertyMirror.attributes() != PropertyAttribute.None) {
2407 result.attributes = propertyMirror.attributes();
2409 if (propertyMirror.propertyType() != PropertyType.Normal) {
2410 result.propertyType = propertyMirror.propertyType();
2412 result.ref = propertyValue.handle();
2418 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2419 content.index = mirror.index();
2420 content.receiver = this.serializeReference(mirror.receiver());
2421 var func = mirror.func();
2422 content.func = this.serializeReference(func);
2423 if (func.script()) {
2424 content.script = this.serializeReference(func.script());
2426 content.constructCall = mirror.isConstructCall();
2427 content.atReturn = mirror.isAtReturn();
2428 if (mirror.isAtReturn()) {
2429 content.returnValue = this.serializeReference(mirror.returnValue());
2431 content.debuggerFrame = mirror.isDebuggerFrame();
2432 var x = new Array(mirror.argumentCount());
2433 for (var i = 0; i < mirror.argumentCount(); i++) {
2435 var argument_name = mirror.argumentName(i);
2436 if (argument_name) {
2437 arg.name = argument_name;
2439 arg.value = this.serializeReference(mirror.argumentValue(i));
2442 content.arguments = x;
2443 var x = new Array(mirror.localCount());
2444 for (var i = 0; i < mirror.localCount(); i++) {
2446 local.name = mirror.localName(i);
2447 local.value = this.serializeReference(mirror.localValue(i));
2451 serializeLocationFields(mirror.sourceLocation(), content);
2452 var source_line_text = mirror.sourceLineText();
2453 if (!IS_UNDEFINED(source_line_text)) {
2454 content.sourceLineText = source_line_text;
2457 content.scopes = [];
2458 for (var i = 0; i < mirror.scopeCount(); i++) {
2459 var scope = mirror.scope(i);
2460 content.scopes.push({
2461 type: scope.scopeType(),
2468 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2469 content.index = mirror.scopeIndex();
2470 content.frameIndex = mirror.frameIndex();
2471 content.type = mirror.scopeType();
2472 content.object = this.inlineRefs_() ?
2473 this.serializeValue(mirror.scopeObject()) :
2474 this.serializeReference(mirror.scopeObject());
2479 * Convert a number to a protocol value. For all finite numbers the number
2480 * itself is returned. For non finite numbers NaN, Infinite and
2481 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
2482 * (not including the quotes) is returned.
2484 * @param {number} value The number value to convert to a protocol value.
2485 * @returns {number|string} Protocol value.
2487 function NumberToJSON_(value) {
2491 if (!NUMBER_IS_FINITE(value)) {