Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: src/mirror-delay.js

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

Powered by Google App Engine
This is Rietveld 408576698