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

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

Issue 564035: Remove lazy loading of natives files and the natives cache.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 10 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
« no previous file with comments | « src/mirror-debugger.js ('k') | src/mksnapshot.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
557 StringMirror.prototype.toText = function() {
558 if (this.length() > kMaxProtocolStringLength) {
559 return this.value_.substring(0, kMaxProtocolStringLength) +
560 '... (length: ' + this.length() + ')';
561 } else {
562 return this.value_;
563 }
564 }
565
566
567 /**
568 * Mirror object for objects.
569 * @param {object} value The object reflected by this mirror
570 * @param {boolean} transient indicate whether this object is transient with a
571 * transient handle
572 * @constructor
573 * @extends ValueMirror
574 */
575 function ObjectMirror(value, type, transient) {
576 ValueMirror.call(this, type || OBJECT_TYPE, value, transient);
577 }
578 inherits(ObjectMirror, ValueMirror);
579
580
581 ObjectMirror.prototype.className = function() {
582 return %_ClassOf(this.value_);
583 };
584
585
586 ObjectMirror.prototype.constructorFunction = function() {
587 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
588 };
589
590
591 ObjectMirror.prototype.prototypeObject = function() {
592 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
593 };
594
595
596 ObjectMirror.prototype.protoObject = function() {
597 return MakeMirror(%DebugGetPrototype(this.value_));
598 };
599
600
601 ObjectMirror.prototype.hasNamedInterceptor = function() {
602 // Get information on interceptors for this object.
603 var x = %GetInterceptorInfo(this.value_);
604 return (x & 2) != 0;
605 };
606
607
608 ObjectMirror.prototype.hasIndexedInterceptor = function() {
609 // Get information on interceptors for this object.
610 var x = %GetInterceptorInfo(this.value_);
611 return (x & 1) != 0;
612 };
613
614
615 /**
616 * Return the property names for this object.
617 * @param {number} kind Indicate whether named, indexed or both kinds of
618 * properties are requested
619 * @param {number} limit Limit the number of names returend to the specified
620 value
621 * @return {Array} Property names for this object
622 */
623 ObjectMirror.prototype.propertyNames = function(kind, limit) {
624 // Find kind and limit and allocate array for the result
625 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
626
627 var propertyNames;
628 var elementNames;
629 var total = 0;
630
631 // Find all the named properties.
632 if (kind & PropertyKind.Named) {
633 // Get the local property names.
634 propertyNames = %GetLocalPropertyNames(this.value_);
635 total += propertyNames.length;
636
637 // Get names for named interceptor properties if any.
638 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
639 var namedInterceptorNames =
640 %GetNamedInterceptorPropertyNames(this.value_);
641 if (namedInterceptorNames) {
642 propertyNames = propertyNames.concat(namedInterceptorNames);
643 total += namedInterceptorNames.length;
644 }
645 }
646 }
647
648 // Find all the indexed properties.
649 if (kind & PropertyKind.Indexed) {
650 // Get the local element names.
651 elementNames = %GetLocalElementNames(this.value_);
652 total += elementNames.length;
653
654 // Get names for indexed interceptor properties.
655 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
656 var indexedInterceptorNames =
657 %GetIndexedInterceptorElementNames(this.value_);
658 if (indexedInterceptorNames) {
659 elementNames = elementNames.concat(indexedInterceptorNames);
660 total += indexedInterceptorNames.length;
661 }
662 }
663 }
664 limit = Math.min(limit || total, total);
665
666 var names = new Array(limit);
667 var index = 0;
668
669 // Copy names for named properties.
670 if (kind & PropertyKind.Named) {
671 for (var i = 0; index < limit && i < propertyNames.length; i++) {
672 names[index++] = propertyNames[i];
673 }
674 }
675
676 // Copy names for indexed properties.
677 if (kind & PropertyKind.Indexed) {
678 for (var i = 0; index < limit && i < elementNames.length; i++) {
679 names[index++] = elementNames[i];
680 }
681 }
682
683 return names;
684 };
685
686
687 /**
688 * Return the properties for this object as an array of PropertyMirror objects.
689 * @param {number} kind Indicate whether named, indexed or both kinds of
690 * properties are requested
691 * @param {number} limit Limit the number of properties returend to the
692 specified value
693 * @return {Array} Property mirrors for this object
694 */
695 ObjectMirror.prototype.properties = function(kind, limit) {
696 var names = this.propertyNames(kind, limit);
697 var properties = new Array(names.length);
698 for (var i = 0; i < names.length; i++) {
699 properties[i] = this.property(names[i]);
700 }
701
702 return properties;
703 };
704
705
706 ObjectMirror.prototype.property = function(name) {
707 var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
708 if (details) {
709 return new PropertyMirror(this, name, details);
710 }
711
712 // Nothing found.
713 return GetUndefinedMirror();
714 };
715
716
717
718 /**
719 * Try to find a property from its value.
720 * @param {Mirror} value The property value to look for
721 * @return {PropertyMirror} The property with the specified value. If no
722 * property was found with the specified value UndefinedMirror is returned
723 */
724 ObjectMirror.prototype.lookupProperty = function(value) {
725 var properties = this.properties();
726
727 // Look for property value in properties.
728 for (var i = 0; i < properties.length; i++) {
729
730 // Skip properties which are defined through assessors.
731 var property = properties[i];
732 if (property.propertyType() != PropertyType.Callbacks) {
733 if (%_ObjectEquals(property.value_, value.value_)) {
734 return property;
735 }
736 }
737 }
738
739 // Nothing found.
740 return GetUndefinedMirror();
741 };
742
743
744 /**
745 * Returns objects which has direct references to this object
746 * @param {number} opt_max_objects Optional parameter specifying the maximum
747 * number of referencing objects to return.
748 * @return {Array} The objects which has direct references to this object.
749 */
750 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
751 // Find all objects with direct references to this object.
752 var result = %DebugReferencedBy(this.value_,
753 Mirror.prototype, opt_max_objects || 0);
754
755 // Make mirrors for all the references found.
756 for (var i = 0; i < result.length; i++) {
757 result[i] = MakeMirror(result[i]);
758 }
759
760 return result;
761 };
762
763
764 ObjectMirror.prototype.toText = function() {
765 var name;
766 var ctor = this.constructorFunction();
767 if (!ctor.isFunction()) {
768 name = this.className();
769 } else {
770 name = ctor.name();
771 if (!name) {
772 name = this.className();
773 }
774 }
775 return '#<' + builtins.GetInstanceName(name) + '>';
776 };
777
778
779 /**
780 * Mirror object for functions.
781 * @param {function} value The function object reflected by this mirror.
782 * @constructor
783 * @extends ObjectMirror
784 */
785 function FunctionMirror(value) {
786 ObjectMirror.call(this, value, FUNCTION_TYPE);
787 this.resolved_ = true;
788 }
789 inherits(FunctionMirror, ObjectMirror);
790
791
792 /**
793 * Returns whether the function is resolved.
794 * @return {boolean} True if the function is resolved. Unresolved functions can
795 * only originate as functions from stack frames
796 */
797 FunctionMirror.prototype.resolved = function() {
798 return this.resolved_;
799 };
800
801
802 /**
803 * Returns the name of the function.
804 * @return {string} Name of the function
805 */
806 FunctionMirror.prototype.name = function() {
807 return %FunctionGetName(this.value_);
808 };
809
810
811 /**
812 * Returns the inferred name of the function.
813 * @return {string} Name of the function
814 */
815 FunctionMirror.prototype.inferredName = function() {
816 return %FunctionGetInferredName(this.value_);
817 };
818
819
820 /**
821 * Returns the source code for the function.
822 * @return {string or undefined} The source code for the function. If the
823 * function is not resolved undefined will be returned.
824 */
825 FunctionMirror.prototype.source = function() {
826 // Return source if function is resolved. Otherwise just fall through to
827 // return undefined.
828 if (this.resolved()) {
829 return builtins.FunctionSourceString(this.value_);
830 }
831 };
832
833
834 /**
835 * Returns the script object for the function.
836 * @return {ScriptMirror or undefined} Script object for the function or
837 * undefined if the function has no script
838 */
839 FunctionMirror.prototype.script = function() {
840 // Return script if function is resolved. Otherwise just fall through
841 // to return undefined.
842 if (this.resolved()) {
843 var script = %FunctionGetScript(this.value_);
844 if (script) {
845 return MakeMirror(script);
846 }
847 }
848 };
849
850
851 /**
852 * Returns the script source position for the function. Only makes sense
853 * for functions which has a script defined.
854 * @return {Number or undefined} in-script position for the function
855 */
856 FunctionMirror.prototype.sourcePosition_ = function() {
857 // Return script if function is resolved. Otherwise just fall through
858 // to return undefined.
859 if (this.resolved()) {
860 return %FunctionGetScriptSourcePosition(this.value_);
861 }
862 };
863
864
865 /**
866 * Returns the script source location object for the function. Only makes sense
867 * for functions which has a script defined.
868 * @return {Location or undefined} in-script location for the function begin
869 */
870 FunctionMirror.prototype.sourceLocation = function() {
871 if (this.resolved() && this.script()) {
872 return this.script().locationFromPosition(this.sourcePosition_(),
873 true);
874 }
875 };
876
877
878 /**
879 * Returns objects constructed by this function.
880 * @param {number} opt_max_instances Optional parameter specifying the maximum
881 * number of instances to return.
882 * @return {Array or undefined} The objects constructed by this function.
883 */
884 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
885 if (this.resolved()) {
886 // Find all objects constructed from this function.
887 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
888
889 // Make mirrors for all the instances found.
890 for (var i = 0; i < result.length; i++) {
891 result[i] = MakeMirror(result[i]);
892 }
893
894 return result;
895 } else {
896 return [];
897 }
898 };
899
900
901 FunctionMirror.prototype.toText = function() {
902 return this.source();
903 }
904
905
906 /**
907 * Mirror object for unresolved functions.
908 * @param {string} value The name for the unresolved function reflected by this
909 * mirror.
910 * @constructor
911 * @extends ObjectMirror
912 */
913 function UnresolvedFunctionMirror(value) {
914 // Construct this using the ValueMirror as an unresolved function is not a
915 // real object but just a string.
916 ValueMirror.call(this, FUNCTION_TYPE, value);
917 this.propertyCount_ = 0;
918 this.elementCount_ = 0;
919 this.resolved_ = false;
920 }
921 inherits(UnresolvedFunctionMirror, FunctionMirror);
922
923
924 UnresolvedFunctionMirror.prototype.className = function() {
925 return 'Function';
926 };
927
928
929 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
930 return GetUndefinedMirror();
931 };
932
933
934 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
935 return GetUndefinedMirror();
936 };
937
938
939 UnresolvedFunctionMirror.prototype.protoObject = function() {
940 return GetUndefinedMirror();
941 };
942
943
944 UnresolvedFunctionMirror.prototype.name = function() {
945 return this.value_;
946 };
947
948
949 UnresolvedFunctionMirror.prototype.inferredName = function() {
950 return undefined;
951 };
952
953
954 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
955 return [];
956 }
957
958
959 /**
960 * Mirror object for arrays.
961 * @param {Array} value The Array object reflected by this mirror
962 * @constructor
963 * @extends ObjectMirror
964 */
965 function ArrayMirror(value) {
966 ObjectMirror.call(this, value);
967 }
968 inherits(ArrayMirror, ObjectMirror);
969
970
971 ArrayMirror.prototype.length = function() {
972 return this.value_.length;
973 };
974
975
976 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_ to_index) {
977 var from_index = opt_from_index || 0;
978 var to_index = opt_to_index || this.length() - 1;
979 if (from_index > to_index) return new Array();
980 var values = new Array(to_index - from_index + 1);
981 for (var i = from_index; i <= to_index; i++) {
982 var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
983 var value;
984 if (details) {
985 value = new PropertyMirror(this, i, details);
986 } else {
987 value = GetUndefinedMirror();
988 }
989 values[i - from_index] = value;
990 }
991 return values;
992 }
993
994
995 /**
996 * Mirror object for dates.
997 * @param {Date} value The Date object reflected by this mirror
998 * @constructor
999 * @extends ObjectMirror
1000 */
1001 function DateMirror(value) {
1002 ObjectMirror.call(this, value);
1003 }
1004 inherits(DateMirror, ObjectMirror);
1005
1006
1007 DateMirror.prototype.toText = function() {
1008 var s = JSON.stringify(this.value_);
1009 return s.substring(1, s.length - 1); // cut quotes
1010 }
1011
1012
1013 /**
1014 * Mirror object for regular expressions.
1015 * @param {RegExp} value The RegExp object reflected by this mirror
1016 * @constructor
1017 * @extends ObjectMirror
1018 */
1019 function RegExpMirror(value) {
1020 ObjectMirror.call(this, value, REGEXP_TYPE);
1021 }
1022 inherits(RegExpMirror, ObjectMirror);
1023
1024
1025 /**
1026 * Returns the source to the regular expression.
1027 * @return {string or undefined} The source to the regular expression
1028 */
1029 RegExpMirror.prototype.source = function() {
1030 return this.value_.source;
1031 };
1032
1033
1034 /**
1035 * Returns whether this regular expression has the global (g) flag set.
1036 * @return {boolean} Value of the global flag
1037 */
1038 RegExpMirror.prototype.global = function() {
1039 return this.value_.global;
1040 };
1041
1042
1043 /**
1044 * Returns whether this regular expression has the ignore case (i) flag set.
1045 * @return {boolean} Value of the ignore case flag
1046 */
1047 RegExpMirror.prototype.ignoreCase = function() {
1048 return this.value_.ignoreCase;
1049 };
1050
1051
1052 /**
1053 * Returns whether this regular expression has the multiline (m) flag set.
1054 * @return {boolean} Value of the multiline flag
1055 */
1056 RegExpMirror.prototype.multiline = function() {
1057 return this.value_.multiline;
1058 };
1059
1060
1061 RegExpMirror.prototype.toText = function() {
1062 // Simpel to text which is used when on specialization in subclass.
1063 return "/" + this.source() + "/";
1064 }
1065
1066
1067 /**
1068 * Mirror object for error objects.
1069 * @param {Error} value The error object reflected by this mirror
1070 * @constructor
1071 * @extends ObjectMirror
1072 */
1073 function ErrorMirror(value) {
1074 ObjectMirror.call(this, value, ERROR_TYPE);
1075 }
1076 inherits(ErrorMirror, ObjectMirror);
1077
1078
1079 /**
1080 * Returns the message for this eror object.
1081 * @return {string or undefined} The message for this eror object
1082 */
1083 ErrorMirror.prototype.message = function() {
1084 return this.value_.message;
1085 };
1086
1087
1088 ErrorMirror.prototype.toText = function() {
1089 // Use the same text representation as in messages.js.
1090 var text;
1091 try {
1092 str = builtins.ToDetailString(this.value_);
1093 } catch (e) {
1094 str = '#<an Error>';
1095 }
1096 return str;
1097 }
1098
1099
1100 /**
1101 * Base mirror object for properties.
1102 * @param {ObjectMirror} mirror The mirror object having this property
1103 * @param {string} name The name of the property
1104 * @param {Array} details Details about the property
1105 * @constructor
1106 * @extends Mirror
1107 */
1108 function PropertyMirror(mirror, name, details) {
1109 Mirror.call(this, PROPERTY_TYPE);
1110 this.mirror_ = mirror;
1111 this.name_ = name;
1112 this.value_ = details[0];
1113 this.details_ = details[1];
1114 if (details.length > 2) {
1115 this.exception_ = details[2]
1116 this.getter_ = details[3];
1117 this.setter_ = details[4];
1118 }
1119 }
1120 inherits(PropertyMirror, Mirror);
1121
1122
1123 PropertyMirror.prototype.isReadOnly = function() {
1124 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1125 }
1126
1127
1128 PropertyMirror.prototype.isEnum = function() {
1129 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1130 }
1131
1132
1133 PropertyMirror.prototype.canDelete = function() {
1134 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1135 }
1136
1137
1138 PropertyMirror.prototype.name = function() {
1139 return this.name_;
1140 }
1141
1142
1143 PropertyMirror.prototype.isIndexed = function() {
1144 for (var i = 0; i < this.name_.length; i++) {
1145 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1146 return false;
1147 }
1148 }
1149 return true;
1150 }
1151
1152
1153 PropertyMirror.prototype.value = function() {
1154 return MakeMirror(this.value_, false);
1155 }
1156
1157
1158 /**
1159 * Returns whether this property value is an exception.
1160 * @return {booolean} True if this property value is an exception
1161 */
1162 PropertyMirror.prototype.isException = function() {
1163 return this.exception_ ? true : false;
1164 }
1165
1166
1167 PropertyMirror.prototype.attributes = function() {
1168 return %DebugPropertyAttributesFromDetails(this.details_);
1169 }
1170
1171
1172 PropertyMirror.prototype.propertyType = function() {
1173 return %DebugPropertyTypeFromDetails(this.details_);
1174 }
1175
1176
1177 PropertyMirror.prototype.insertionIndex = function() {
1178 return %DebugPropertyIndexFromDetails(this.details_);
1179 }
1180
1181
1182 /**
1183 * Returns whether this property has a getter defined through __defineGetter__.
1184 * @return {booolean} True if this property has a getter
1185 */
1186 PropertyMirror.prototype.hasGetter = function() {
1187 return this.getter_ ? true : false;
1188 }
1189
1190
1191 /**
1192 * Returns whether this property has a setter defined through __defineSetter__.
1193 * @return {booolean} True if this property has a setter
1194 */
1195 PropertyMirror.prototype.hasSetter = function() {
1196 return this.setter_ ? true : false;
1197 }
1198
1199
1200 /**
1201 * Returns the getter for this property defined through __defineGetter__.
1202 * @return {Mirror} FunctionMirror reflecting the getter function or
1203 * UndefinedMirror if there is no getter for this property
1204 */
1205 PropertyMirror.prototype.getter = function() {
1206 if (this.hasGetter()) {
1207 return MakeMirror(this.getter_);
1208 } else {
1209 return GetUndefinedMirror();
1210 }
1211 }
1212
1213
1214 /**
1215 * Returns the setter for this property defined through __defineSetter__.
1216 * @return {Mirror} FunctionMirror reflecting the setter function or
1217 * UndefinedMirror if there is no setter for this property
1218 */
1219 PropertyMirror.prototype.setter = function() {
1220 if (this.hasSetter()) {
1221 return MakeMirror(this.setter_);
1222 } else {
1223 return GetUndefinedMirror();
1224 }
1225 }
1226
1227
1228 /**
1229 * Returns whether this property is natively implemented by the host or a set
1230 * through JavaScript code.
1231 * @return {boolean} True if the property is
1232 * UndefinedMirror if there is no setter for this property
1233 */
1234 PropertyMirror.prototype.isNative = function() {
1235 return (this.propertyType() == PropertyType.Interceptor) ||
1236 ((this.propertyType() == PropertyType.Callbacks) &&
1237 !this.hasGetter() && !this.hasSetter());
1238 }
1239
1240
1241 const kFrameDetailsFrameIdIndex = 0;
1242 const kFrameDetailsReceiverIndex = 1;
1243 const kFrameDetailsFunctionIndex = 2;
1244 const kFrameDetailsArgumentCountIndex = 3;
1245 const kFrameDetailsLocalCountIndex = 4;
1246 const kFrameDetailsSourcePositionIndex = 5;
1247 const kFrameDetailsConstructCallIndex = 6;
1248 const kFrameDetailsDebuggerFrameIndex = 7;
1249 const kFrameDetailsFirstDynamicIndex = 8;
1250
1251 const kFrameDetailsNameIndex = 0;
1252 const kFrameDetailsValueIndex = 1;
1253 const kFrameDetailsNameValueSize = 2;
1254
1255 /**
1256 * Wrapper for the frame details information retreived from the VM. The frame
1257 * details from the VM is an array with the following content. See runtime.cc
1258 * Runtime_GetFrameDetails.
1259 * 0: Id
1260 * 1: Receiver
1261 * 2: Function
1262 * 3: Argument count
1263 * 4: Local count
1264 * 5: Source position
1265 * 6: Construct call
1266 * Arguments name, value
1267 * Locals name, value
1268 * @param {number} break_id Current break id
1269 * @param {number} index Frame number
1270 * @constructor
1271 */
1272 function FrameDetails(break_id, index) {
1273 this.break_id_ = break_id;
1274 this.details_ = %GetFrameDetails(break_id, index);
1275 }
1276
1277
1278 FrameDetails.prototype.frameId = function() {
1279 %CheckExecutionState(this.break_id_);
1280 return this.details_[kFrameDetailsFrameIdIndex];
1281 }
1282
1283
1284 FrameDetails.prototype.receiver = function() {
1285 %CheckExecutionState(this.break_id_);
1286 return this.details_[kFrameDetailsReceiverIndex];
1287 }
1288
1289
1290 FrameDetails.prototype.func = function() {
1291 %CheckExecutionState(this.break_id_);
1292 return this.details_[kFrameDetailsFunctionIndex];
1293 }
1294
1295
1296 FrameDetails.prototype.isConstructCall = function() {
1297 %CheckExecutionState(this.break_id_);
1298 return this.details_[kFrameDetailsConstructCallIndex];
1299 }
1300
1301
1302 FrameDetails.prototype.isDebuggerFrame = function() {
1303 %CheckExecutionState(this.break_id_);
1304 return this.details_[kFrameDetailsDebuggerFrameIndex];
1305 }
1306
1307
1308 FrameDetails.prototype.argumentCount = function() {
1309 %CheckExecutionState(this.break_id_);
1310 return this.details_[kFrameDetailsArgumentCountIndex];
1311 }
1312
1313
1314 FrameDetails.prototype.argumentName = function(index) {
1315 %CheckExecutionState(this.break_id_);
1316 if (index >= 0 && index < this.argumentCount()) {
1317 return this.details_[kFrameDetailsFirstDynamicIndex +
1318 index * kFrameDetailsNameValueSize +
1319 kFrameDetailsNameIndex]
1320 }
1321 }
1322
1323
1324 FrameDetails.prototype.argumentValue = function(index) {
1325 %CheckExecutionState(this.break_id_);
1326 if (index >= 0 && index < this.argumentCount()) {
1327 return this.details_[kFrameDetailsFirstDynamicIndex +
1328 index * kFrameDetailsNameValueSize +
1329 kFrameDetailsValueIndex]
1330 }
1331 }
1332
1333
1334 FrameDetails.prototype.localCount = function() {
1335 %CheckExecutionState(this.break_id_);
1336 return this.details_[kFrameDetailsLocalCountIndex];
1337 }
1338
1339
1340 FrameDetails.prototype.sourcePosition = function() {
1341 %CheckExecutionState(this.break_id_);
1342 return this.details_[kFrameDetailsSourcePositionIndex];
1343 }
1344
1345
1346 FrameDetails.prototype.localName = function(index) {
1347 %CheckExecutionState(this.break_id_);
1348 if (index >= 0 && index < this.localCount()) {
1349 var locals_offset = kFrameDetailsFirstDynamicIndex + this.argumentCount() * kFrameDetailsNameValueSize
1350 return this.details_[locals_offset +
1351 index * kFrameDetailsNameValueSize +
1352 kFrameDetailsNameIndex]
1353 }
1354 }
1355
1356
1357 FrameDetails.prototype.localValue = function(index) {
1358 %CheckExecutionState(this.break_id_);
1359 if (index >= 0 && index < this.localCount()) {
1360 var locals_offset = kFrameDetailsFirstDynamicIndex + this.argumentCount() * kFrameDetailsNameValueSize
1361 return this.details_[locals_offset +
1362 index * kFrameDetailsNameValueSize +
1363 kFrameDetailsValueIndex]
1364 }
1365 }
1366
1367
1368 FrameDetails.prototype.scopeCount = function() {
1369 return %GetScopeCount(this.break_id_, this.frameId());
1370 }
1371
1372
1373 /**
1374 * Mirror object for stack frames.
1375 * @param {number} break_id The break id in the VM for which this frame is
1376 valid
1377 * @param {number} index The frame index (top frame is index 0)
1378 * @constructor
1379 * @extends Mirror
1380 */
1381 function FrameMirror(break_id, index) {
1382 Mirror.call(this, FRAME_TYPE);
1383 this.break_id_ = break_id;
1384 this.index_ = index;
1385 this.details_ = new FrameDetails(break_id, index);
1386 }
1387 inherits(FrameMirror, Mirror);
1388
1389
1390 FrameMirror.prototype.index = function() {
1391 return this.index_;
1392 };
1393
1394
1395 FrameMirror.prototype.func = function() {
1396 // Get the function for this frame from the VM.
1397 var f = this.details_.func();
1398
1399 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1400 // value returned from the VM might be a string if the function for the
1401 // frame is unresolved.
1402 if (IS_FUNCTION(f)) {
1403 return MakeMirror(f);
1404 } else {
1405 return new UnresolvedFunctionMirror(f);
1406 }
1407 };
1408
1409
1410 FrameMirror.prototype.receiver = function() {
1411 return MakeMirror(this.details_.receiver());
1412 };
1413
1414
1415 FrameMirror.prototype.isConstructCall = function() {
1416 return this.details_.isConstructCall();
1417 };
1418
1419
1420 FrameMirror.prototype.isDebuggerFrame = function() {
1421 return this.details_.isDebuggerFrame();
1422 };
1423
1424
1425 FrameMirror.prototype.argumentCount = function() {
1426 return this.details_.argumentCount();
1427 };
1428
1429
1430 FrameMirror.prototype.argumentName = function(index) {
1431 return this.details_.argumentName(index);
1432 };
1433
1434
1435 FrameMirror.prototype.argumentValue = function(index) {
1436 return MakeMirror(this.details_.argumentValue(index));
1437 };
1438
1439
1440 FrameMirror.prototype.localCount = function() {
1441 return this.details_.localCount();
1442 };
1443
1444
1445 FrameMirror.prototype.localName = function(index) {
1446 return this.details_.localName(index);
1447 };
1448
1449
1450 FrameMirror.prototype.localValue = function(index) {
1451 return MakeMirror(this.details_.localValue(index));
1452 };
1453
1454
1455 FrameMirror.prototype.sourcePosition = function() {
1456 return this.details_.sourcePosition();
1457 };
1458
1459
1460 FrameMirror.prototype.sourceLocation = function() {
1461 if (this.func().resolved() && this.func().script()) {
1462 return this.func().script().locationFromPosition(this.sourcePosition(),
1463 true);
1464 }
1465 };
1466
1467
1468 FrameMirror.prototype.sourceLine = function() {
1469 if (this.func().resolved()) {
1470 var location = this.sourceLocation();
1471 if (location) {
1472 return location.line;
1473 }
1474 }
1475 };
1476
1477
1478 FrameMirror.prototype.sourceColumn = function() {
1479 if (this.func().resolved()) {
1480 var location = this.sourceLocation();
1481 if (location) {
1482 return location.column;
1483 }
1484 }
1485 };
1486
1487
1488 FrameMirror.prototype.sourceLineText = function() {
1489 if (this.func().resolved()) {
1490 var location = this.sourceLocation();
1491 if (location) {
1492 return location.sourceText();
1493 }
1494 }
1495 };
1496
1497
1498 FrameMirror.prototype.scopeCount = function() {
1499 return this.details_.scopeCount();
1500 };
1501
1502
1503 FrameMirror.prototype.scope = function(index) {
1504 return new ScopeMirror(this, index);
1505 };
1506
1507
1508 FrameMirror.prototype.evaluate = function(source, disable_break) {
1509 var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
1510 source, Boolean(disable_break));
1511 return MakeMirror(result);
1512 };
1513
1514
1515 FrameMirror.prototype.invocationText = function() {
1516 // Format frame invoaction (receiver, function and arguments).
1517 var result = '';
1518 var func = this.func();
1519 var receiver = this.receiver();
1520 if (this.isConstructCall()) {
1521 // For constructor frames display new followed by the function name.
1522 result += 'new ';
1523 result += func.name() ? func.name() : '[anonymous]';
1524 } else if (this.isDebuggerFrame()) {
1525 result += '[debugger]';
1526 } else {
1527 // If the receiver has a className which is 'global' don't display it.
1528 var display_receiver = !receiver.className || receiver.className() != 'globa l';
1529 if (display_receiver) {
1530 result += receiver.toText();
1531 }
1532 // Try to find the function as a property in the receiver. Include the
1533 // prototype chain in the lookup.
1534 var property = GetUndefinedMirror();
1535 if (!receiver.isUndefined()) {
1536 for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoO bject()) {
1537 property = r.lookupProperty(func);
1538 }
1539 }
1540 if (!property.isUndefined()) {
1541 // The function invoked was found on the receiver. Use the property name
1542 // for the backtrace.
1543 if (!property.isIndexed()) {
1544 if (display_receiver) {
1545 result += '.';
1546 }
1547 result += property.name();
1548 } else {
1549 result += '[';
1550 result += property.name();
1551 result += ']';
1552 }
1553 // Also known as - if the name in the function doesn't match the name
1554 // under which it was looked up.
1555 if (func.name() && func.name() != property.name()) {
1556 result += '(aka ' + func.name() + ')';
1557 }
1558 } else {
1559 // The function invoked was not found on the receiver. Use the function
1560 // name if available for the backtrace.
1561 if (display_receiver) {
1562 result += '.';
1563 }
1564 result += func.name() ? func.name() : '[anonymous]';
1565 }
1566 }
1567
1568 // Render arguments for normal frames.
1569 if (!this.isDebuggerFrame()) {
1570 result += '(';
1571 for (var i = 0; i < this.argumentCount(); i++) {
1572 if (i != 0) result += ', ';
1573 if (this.argumentName(i)) {
1574 result += this.argumentName(i);
1575 result += '=';
1576 }
1577 result += this.argumentValue(i).toText();
1578 }
1579 result += ')';
1580 }
1581
1582 return result;
1583 }
1584
1585
1586 FrameMirror.prototype.sourceAndPositionText = function() {
1587 // Format source and position.
1588 var result = '';
1589 var func = this.func();
1590 if (func.resolved()) {
1591 if (func.script()) {
1592 if (func.script().name()) {
1593 result += func.script().name();
1594 } else {
1595 result += '[unnamed]';
1596 }
1597 if (!this.isDebuggerFrame()) {
1598 var location = this.sourceLocation();
1599 result += ' line ';
1600 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1601 result += ' column ';
1602 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1603 if (!IS_UNDEFINED(this.sourcePosition())) {
1604 result += ' (position ' + (this.sourcePosition() + 1) + ')';
1605 }
1606 }
1607 } else {
1608 result += '[no source]';
1609 }
1610 } else {
1611 result += '[unresolved]';
1612 }
1613
1614 return result;
1615 }
1616
1617
1618 FrameMirror.prototype.localsText = function() {
1619 // Format local variables.
1620 var result = '';
1621 var locals_count = this.localCount()
1622 if (locals_count > 0) {
1623 for (var i = 0; i < locals_count; ++i) {
1624 result += ' var ';
1625 result += this.localName(i);
1626 result += ' = ';
1627 result += this.localValue(i).toText();
1628 if (i < locals_count - 1) result += '\n';
1629 }
1630 }
1631
1632 return result;
1633 }
1634
1635
1636 FrameMirror.prototype.toText = function(opt_locals) {
1637 var result = '';
1638 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1639 result += ' ';
1640 result += this.invocationText();
1641 result += ' ';
1642 result += this.sourceAndPositionText();
1643 if (opt_locals) {
1644 result += '\n';
1645 result += this.localsText();
1646 }
1647 return result;
1648 }
1649
1650
1651 const kScopeDetailsTypeIndex = 0;
1652 const kScopeDetailsObjectIndex = 1;
1653
1654 function ScopeDetails(frame, index) {
1655 this.break_id_ = frame.break_id_;
1656 this.details_ = %GetScopeDetails(frame.break_id_,
1657 frame.details_.frameId(),
1658 index);
1659 }
1660
1661
1662 ScopeDetails.prototype.type = function() {
1663 %CheckExecutionState(this.break_id_);
1664 return this.details_[kScopeDetailsTypeIndex];
1665 }
1666
1667
1668 ScopeDetails.prototype.object = function() {
1669 %CheckExecutionState(this.break_id_);
1670 return this.details_[kScopeDetailsObjectIndex];
1671 }
1672
1673
1674 /**
1675 * Mirror object for scope.
1676 * @param {FrameMirror} frame The frame this scope is a part of
1677 * @param {number} index The scope index in the frame
1678 * @constructor
1679 * @extends Mirror
1680 */
1681 function ScopeMirror(frame, index) {
1682 Mirror.call(this, SCOPE_TYPE);
1683 this.frame_index_ = frame.index_;
1684 this.scope_index_ = index;
1685 this.details_ = new ScopeDetails(frame, index);
1686 }
1687 inherits(ScopeMirror, Mirror);
1688
1689
1690 ScopeMirror.prototype.frameIndex = function() {
1691 return this.frame_index_;
1692 };
1693
1694
1695 ScopeMirror.prototype.scopeIndex = function() {
1696 return this.scope_index_;
1697 };
1698
1699
1700 ScopeMirror.prototype.scopeType = function() {
1701 return this.details_.type();
1702 };
1703
1704
1705 ScopeMirror.prototype.scopeObject = function() {
1706 // For local and closure scopes create a transient mirror as these objects are
1707 // created on the fly materializing the local or closure scopes and
1708 // therefore will not preserve identity.
1709 var transient = this.scopeType() == ScopeType.Local ||
1710 this.scopeType() == ScopeType.Closure;
1711 return MakeMirror(this.details_.object(), transient);
1712 };
1713
1714
1715 /**
1716 * Mirror object for script source.
1717 * @param {Script} script The script object
1718 * @constructor
1719 * @extends Mirror
1720 */
1721 function ScriptMirror(script) {
1722 Mirror.call(this, SCRIPT_TYPE);
1723 this.script_ = script;
1724 this.context_ = new ContextMirror(script.context_data);
1725 this.allocateHandle_();
1726 }
1727 inherits(ScriptMirror, Mirror);
1728
1729
1730 ScriptMirror.prototype.value = function() {
1731 return this.script_;
1732 };
1733
1734
1735 ScriptMirror.prototype.name = function() {
1736 return this.script_.name;
1737 };
1738
1739
1740 ScriptMirror.prototype.id = function() {
1741 return this.script_.id;
1742 };
1743
1744
1745 ScriptMirror.prototype.source = function() {
1746 return this.script_.source;
1747 };
1748
1749
1750 ScriptMirror.prototype.lineOffset = function() {
1751 return this.script_.line_offset;
1752 };
1753
1754
1755 ScriptMirror.prototype.columnOffset = function() {
1756 return this.script_.column_offset;
1757 };
1758
1759
1760 ScriptMirror.prototype.data = function() {
1761 return this.script_.data;
1762 };
1763
1764
1765 ScriptMirror.prototype.scriptType = function() {
1766 return this.script_.type;
1767 };
1768
1769
1770 ScriptMirror.prototype.compilationType = function() {
1771 return this.script_.compilation_type;
1772 };
1773
1774
1775 ScriptMirror.prototype.lineCount = function() {
1776 return this.script_.lineCount();
1777 };
1778
1779
1780 ScriptMirror.prototype.locationFromPosition = function(
1781 position, include_resource_offset) {
1782 return this.script_.locationFromPosition(position, include_resource_offset);
1783 }
1784
1785
1786 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
1787 return this.script_.sourceSlice(opt_from_line, opt_to_line);
1788 }
1789
1790
1791 ScriptMirror.prototype.context = function() {
1792 return this.context_;
1793 };
1794
1795
1796 ScriptMirror.prototype.evalFromScript = function() {
1797 return MakeMirror(this.script_.eval_from_script);
1798 };
1799
1800
1801 ScriptMirror.prototype.evalFromFunctionName = function() {
1802 return MakeMirror(this.script_.eval_from_function_name);
1803 };
1804
1805
1806 ScriptMirror.prototype.evalFromLocation = function() {
1807 var eval_from_script = this.evalFromScript();
1808 if (!eval_from_script.isUndefined()) {
1809 var position = this.script_.eval_from_script_position;
1810 return eval_from_script.locationFromPosition(position, true);
1811 }
1812 };
1813
1814
1815 ScriptMirror.prototype.toText = function() {
1816 var result = '';
1817 result += this.name();
1818 result += ' (lines: ';
1819 if (this.lineOffset() > 0) {
1820 result += this.lineOffset();
1821 result += '-';
1822 result += this.lineOffset() + this.lineCount() - 1;
1823 } else {
1824 result += this.lineCount();
1825 }
1826 result += ')';
1827 return result;
1828 }
1829
1830
1831 /**
1832 * Mirror object for context.
1833 * @param {Object} data The context data
1834 * @constructor
1835 * @extends Mirror
1836 */
1837 function ContextMirror(data) {
1838 Mirror.call(this, CONTEXT_TYPE);
1839 this.data_ = data;
1840 this.allocateHandle_();
1841 }
1842 inherits(ContextMirror, Mirror);
1843
1844
1845 ContextMirror.prototype.data = function() {
1846 return this.data_;
1847 };
1848
1849
1850 /**
1851 * Returns a mirror serializer
1852 *
1853 * @param {boolean} details Set to true to include details
1854 * @param {Object} options Options comtrolling the serialization
1855 * The following options can be set:
1856 * includeSource: include ths full source of scripts
1857 * @returns {MirrorSerializer} mirror serializer
1858 */
1859 function MakeMirrorSerializer(details, options) {
1860 return new JSONProtocolSerializer(details, options);
1861 }
1862
1863
1864 /**
1865 * Object for serializing a mirror objects and its direct references.
1866 * @param {boolean} details Indicates whether to include details for the mirror
1867 * serialized
1868 * @constructor
1869 */
1870 function JSONProtocolSerializer(details, options) {
1871 this.details_ = details;
1872 this.options_ = options;
1873 this.mirrors_ = [ ];
1874 }
1875
1876
1877 /**
1878 * Returns a serialization of an object reference. The referenced object are
1879 * added to the serialization state.
1880 *
1881 * @param {Mirror} mirror The mirror to serialize
1882 * @returns {String} JSON serialization
1883 */
1884 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
1885 return this.serialize_(mirror, true, true);
1886 }
1887
1888
1889 /**
1890 * Returns a serialization of an object value. The referenced objects are
1891 * added to the serialization state.
1892 *
1893 * @param {Mirror} mirror The mirror to serialize
1894 * @returns {String} JSON serialization
1895 */
1896 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
1897 var json = this.serialize_(mirror, false, true);
1898 return json;
1899 }
1900
1901
1902 /**
1903 * Returns a serialization of all the objects referenced.
1904 *
1905 * @param {Mirror} mirror The mirror to serialize.
1906 * @returns {Array.<Object>} Array of the referenced objects converted to
1907 * protcol objects.
1908 */
1909 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
1910 // Collect the protocol representation of the referenced objects in an array.
1911 var content = [];
1912
1913 // Get the number of referenced objects.
1914 var count = this.mirrors_.length;
1915
1916 for (var i = 0; i < count; i++) {
1917 content.push(this.serialize_(this.mirrors_[i], false, false));
1918 }
1919
1920 return content;
1921 }
1922
1923
1924 JSONProtocolSerializer.prototype.includeSource_ = function() {
1925 return this.options_ && this.options_.includeSource;
1926 }
1927
1928
1929 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
1930 return this.options_ && this.options_.inlineRefs;
1931 }
1932
1933
1934 JSONProtocolSerializer.prototype.add_ = function(mirror) {
1935 // If this mirror is already in the list just return.
1936 for (var i = 0; i < this.mirrors_.length; i++) {
1937 if (this.mirrors_[i] === mirror) {
1938 return;
1939 }
1940 }
1941
1942 // Add the mirror to the list of mirrors to be serialized.
1943 this.mirrors_.push(mirror);
1944 }
1945
1946
1947 /**
1948 * Formats mirror object to protocol reference object with some data that can
1949 * be used to display the value in debugger.
1950 * @param {Mirror} mirror Mirror to serialize.
1951 * @return {Object} Protocol reference object.
1952 */
1953 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
1954 function(mirror) {
1955 var o = {};
1956 o.ref = mirror.handle();
1957 o.type = mirror.type();
1958 switch (mirror.type()) {
1959 case UNDEFINED_TYPE:
1960 case NULL_TYPE:
1961 case BOOLEAN_TYPE:
1962 case NUMBER_TYPE:
1963 o.value = mirror.value();
1964 break;
1965 case STRING_TYPE:
1966 // Limit string length.
1967 o.value = mirror.toText();
1968 break;
1969 case FUNCTION_TYPE:
1970 o.name = mirror.name();
1971 o.inferredName = mirror.inferredName();
1972 if (mirror.script()) {
1973 o.scriptId = mirror.script().id();
1974 }
1975 break;
1976 case ERROR_TYPE:
1977 case REGEXP_TYPE:
1978 o.value = mirror.toText();
1979 break;
1980 case OBJECT_TYPE:
1981 o.className = mirror.className();
1982 break;
1983 }
1984 return o;
1985 };
1986
1987
1988 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
1989 details) {
1990 // If serializing a reference to a mirror just return the reference and add
1991 // the mirror to the referenced mirrors.
1992 if (reference &&
1993 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
1994 if (this.inlineRefs_() && mirror.isValue()) {
1995 return this.serializeReferenceWithDisplayData_(mirror);
1996 } else {
1997 this.add_(mirror);
1998 return {'ref' : mirror.handle()};
1999 }
2000 }
2001
2002 // Collect the JSON property/value pairs.
2003 var content = {};
2004
2005 // Add the mirror handle.
2006 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2007 content.handle = mirror.handle();
2008 }
2009
2010 // Always add the type.
2011 content.type = mirror.type();
2012
2013 switch (mirror.type()) {
2014 case UNDEFINED_TYPE:
2015 case NULL_TYPE:
2016 // Undefined and null are represented just by their type.
2017 break;
2018
2019 case BOOLEAN_TYPE:
2020 // Boolean values are simply represented by their value.
2021 content.value = mirror.value();
2022 break;
2023
2024 case NUMBER_TYPE:
2025 // Number values are simply represented by their value.
2026 content.value = NumberToJSON_(mirror.value());
2027 break;
2028
2029 case STRING_TYPE:
2030 // String values might have their value cropped to keep down size.
2031 if (mirror.length() > kMaxProtocolStringLength) {
2032 var str = mirror.value().substring(0, kMaxProtocolStringLength);
2033 content.value = str;
2034 content.fromIndex = 0;
2035 content.toIndex = kMaxProtocolStringLength;
2036 } else {
2037 content.value = mirror.value();
2038 }
2039 content.length = mirror.length();
2040 break;
2041
2042 case OBJECT_TYPE:
2043 case FUNCTION_TYPE:
2044 case ERROR_TYPE:
2045 case REGEXP_TYPE:
2046 // Add object representation.
2047 this.serializeObject_(mirror, content, details);
2048 break;
2049
2050 case PROPERTY_TYPE:
2051 throw new Error('PropertyMirror cannot be serialized independeltly')
2052 break;
2053
2054 case FRAME_TYPE:
2055 // Add object representation.
2056 this.serializeFrame_(mirror, content);
2057 break;
2058
2059 case SCOPE_TYPE:
2060 // Add object representation.
2061 this.serializeScope_(mirror, content);
2062 break;
2063
2064 case SCRIPT_TYPE:
2065 // Script is represented by id, name and source attributes.
2066 if (mirror.name()) {
2067 content.name = mirror.name();
2068 }
2069 content.id = mirror.id();
2070 content.lineOffset = mirror.lineOffset();
2071 content.columnOffset = mirror.columnOffset();
2072 content.lineCount = mirror.lineCount();
2073 if (mirror.data()) {
2074 content.data = mirror.data();
2075 }
2076 if (this.includeSource_()) {
2077 content.source = mirror.source();
2078 } else {
2079 var sourceStart = mirror.source().substring(0, 80);
2080 content.sourceStart = sourceStart;
2081 }
2082 content.sourceLength = mirror.source().length;
2083 content.scriptType = mirror.scriptType();
2084 content.compilationType = mirror.compilationType();
2085 // For compilation type eval emit information on the script from which
2086 // eval was called if a script is present.
2087 if (mirror.compilationType() == 1 &&
2088 mirror.evalFromScript()) {
2089 content.evalFromScript =
2090 this.serializeReference(mirror.evalFromScript());
2091 var evalFromLocation = mirror.evalFromLocation()
2092 if (evalFromLocation) {
2093 content.evalFromLocation = { line: evalFromLocation.line,
2094 column: evalFromLocation.column };
2095 }
2096 if (mirror.evalFromFunctionName()) {
2097 content.evalFromFunctionName = mirror.evalFromFunctionName();
2098 }
2099 }
2100 if (mirror.context()) {
2101 content.context = this.serializeReference(mirror.context());
2102 }
2103 break;
2104
2105 case CONTEXT_TYPE:
2106 content.data = mirror.data();
2107 break;
2108 }
2109
2110 // Always add the text representation.
2111 content.text = mirror.toText();
2112
2113 // Create and return the JSON string.
2114 return content;
2115 }
2116
2117
2118 /**
2119 * Serialize object information to the following JSON format.
2120 *
2121 * {"className":"<class name>",
2122 * "constructorFunction":{"ref":<number>},
2123 * "protoObject":{"ref":<number>},
2124 * "prototypeObject":{"ref":<number>},
2125 * "namedInterceptor":<boolean>,
2126 * "indexedInterceptor":<boolean>,
2127 * "properties":[<properties>]}
2128 */
2129 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2130 details) {
2131 // Add general object properties.
2132 content.className = mirror.className();
2133 content.constructorFunction =
2134 this.serializeReference(mirror.constructorFunction());
2135 content.protoObject = this.serializeReference(mirror.protoObject());
2136 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2137
2138 // Add flags to indicate whether there are interceptors.
2139 if (mirror.hasNamedInterceptor()) {
2140 content.namedInterceptor = true;
2141 }
2142 if (mirror.hasIndexedInterceptor()) {
2143 content.indexedInterceptor = true;
2144 }
2145
2146 // Add function specific properties.
2147 if (mirror.isFunction()) {
2148 // Add function specific properties.
2149 content.name = mirror.name();
2150 if (!IS_UNDEFINED(mirror.inferredName())) {
2151 content.inferredName = mirror.inferredName();
2152 }
2153 content.resolved = mirror.resolved();
2154 if (mirror.resolved()) {
2155 content.source = mirror.source();
2156 }
2157 if (mirror.script()) {
2158 content.script = this.serializeReference(mirror.script());
2159 content.scriptId = mirror.script().id();
2160
2161 serializeLocationFields(mirror.sourceLocation(), content);
2162 }
2163 }
2164
2165 // Add date specific properties.
2166 if (mirror.isDate()) {
2167 // Add date specific properties.
2168 content.value = mirror.value();
2169 }
2170
2171 // Add actual properties - named properties followed by indexed properties.
2172 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2173 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2174 var p = new Array(propertyNames.length + propertyIndexes.length);
2175 for (var i = 0; i < propertyNames.length; i++) {
2176 var propertyMirror = mirror.property(propertyNames[i]);
2177 p[i] = this.serializeProperty_(propertyMirror);
2178 if (details) {
2179 this.add_(propertyMirror.value());
2180 }
2181 }
2182 for (var i = 0; i < propertyIndexes.length; i++) {
2183 var propertyMirror = mirror.property(propertyIndexes[i]);
2184 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2185 if (details) {
2186 this.add_(propertyMirror.value());
2187 }
2188 }
2189 content.properties = p;
2190 }
2191
2192
2193 /**
2194 * Serialize location information to the following JSON format:
2195 *
2196 * "position":"<position>",
2197 * "line":"<line>",
2198 * "column":"<column>",
2199 *
2200 * @param {SourceLocation} location The location to serialize, may be undefined.
2201 */
2202 function serializeLocationFields (location, content) {
2203 if (!location) {
2204 return;
2205 }
2206 content.position = location.position;
2207 var line = location.line;
2208 if (!IS_UNDEFINED(line)) {
2209 content.line = line;
2210 }
2211 var column = location.column;
2212 if (!IS_UNDEFINED(column)) {
2213 content.column = column;
2214 }
2215 }
2216
2217
2218 /**
2219 * Serialize property information to the following JSON format for building the
2220 * array of properties.
2221 *
2222 * {"name":"<property name>",
2223 * "attributes":<number>,
2224 * "propertyType":<number>,
2225 * "ref":<number>}
2226 *
2227 * If the attribute for the property is PropertyAttribute.None it is not added.
2228 * If the propertyType for the property is PropertyType.Normal it is not added.
2229 * Here are a couple of examples.
2230 *
2231 * {"name":"hello","ref":1}
2232 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2233 *
2234 * @param {PropertyMirror} propertyMirror The property to serialize.
2235 * @returns {Object} Protocol object representing the property.
2236 */
2237 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2238 var result = {};
2239
2240 result.name = propertyMirror.name();
2241 var propertyValue = propertyMirror.value();
2242 if (this.inlineRefs_() && propertyValue.isValue()) {
2243 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2244 } else {
2245 if (propertyMirror.attributes() != PropertyAttribute.None) {
2246 result.attributes = propertyMirror.attributes();
2247 }
2248 if (propertyMirror.propertyType() != PropertyType.Normal) {
2249 result.propertyType = propertyMirror.propertyType();
2250 }
2251 result.ref = propertyValue.handle();
2252 }
2253 return result;
2254 }
2255
2256
2257 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2258 content.index = mirror.index();
2259 content.receiver = this.serializeReference(mirror.receiver());
2260 var func = mirror.func();
2261 content.func = this.serializeReference(func);
2262 if (func.script()) {
2263 content.script = this.serializeReference(func.script());
2264 }
2265 content.constructCall = mirror.isConstructCall();
2266 content.debuggerFrame = mirror.isDebuggerFrame();
2267 var x = new Array(mirror.argumentCount());
2268 for (var i = 0; i < mirror.argumentCount(); i++) {
2269 var arg = {};
2270 var argument_name = mirror.argumentName(i)
2271 if (argument_name) {
2272 arg.name = argument_name;
2273 }
2274 arg.value = this.serializeReference(mirror.argumentValue(i));
2275 x[i] = arg;
2276 }
2277 content.arguments = x;
2278 var x = new Array(mirror.localCount());
2279 for (var i = 0; i < mirror.localCount(); i++) {
2280 var local = {};
2281 local.name = mirror.localName(i);
2282 local.value = this.serializeReference(mirror.localValue(i));
2283 x[i] = local;
2284 }
2285 content.locals = x;
2286 serializeLocationFields(mirror.sourceLocation(), content);
2287 var source_line_text = mirror.sourceLineText();
2288 if (!IS_UNDEFINED(source_line_text)) {
2289 content.sourceLineText = source_line_text;
2290 }
2291
2292 content.scopes = [];
2293 for (var i = 0; i < mirror.scopeCount(); i++) {
2294 var scope = mirror.scope(i);
2295 content.scopes.push({
2296 type: scope.scopeType(),
2297 index: i
2298 });
2299 }
2300 }
2301
2302
2303 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2304 content.index = mirror.scopeIndex();
2305 content.frameIndex = mirror.frameIndex();
2306 content.type = mirror.scopeType();
2307 content.object = this.inlineRefs_() ?
2308 this.serializeValue(mirror.scopeObject()) :
2309 this.serializeReference(mirror.scopeObject());
2310 }
2311
2312
2313 /**
2314 * Convert a number to a protocol value. For all finite numbers the number
2315 * itself is returned. For non finite numbers NaN, Infinite and
2316 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
2317 * (not including the quotes) is returned.
2318 *
2319 * @param {number} value The number value to convert to a protocol value.
2320 * @returns {number|string} Protocol value.
2321 */
2322 function NumberToJSON_(value) {
2323 if (isNaN(value)) {
2324 return 'NaN';
2325 }
2326 if (!isFinite(value)) {
2327 if (value > 0) {
2328 return 'Infinity';
2329 } else {
2330 return '-Infinity';
2331 }
2332 }
2333 return value;
2334 }
OLDNEW
« no previous file with comments | « src/mirror-debugger.js ('k') | src/mksnapshot.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698