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

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

Issue 1265923002: Debugger: move implementation to a separate folder. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 5 years, 4 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
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | src/objects.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-2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 "use strict";
5
6 // Handle id counters.
7 var next_handle_ = 0;
8 var next_transient_handle_ = -1;
9
10 // Mirror cache.
11 var mirror_cache_ = [];
12 var mirror_cache_enabled_ = true;
13
14
15 function ToggleMirrorCache(value) {
16 mirror_cache_enabled_ = value;
17 next_handle_ = 0;
18 mirror_cache_ = [];
19 }
20
21
22 // Wrapper to check whether an object is a Promise. The call may not work
23 // if promises are not enabled.
24 // TODO(yangguo): remove try-catch once promises are enabled by default.
25 function ObjectIsPromise(value) {
26 try {
27 return IS_SPEC_OBJECT(value) &&
28 !IS_UNDEFINED(%DebugGetProperty(value, builtins.$promiseStatus));
29 } catch (e) {
30 return false;
31 }
32 }
33
34
35 /**
36 * Returns the mirror for a specified value or object.
37 *
38 * @param {value or Object} value the value or object to retreive the mirror for
39 * @param {boolean} transient indicate whether this object is transient and
40 * should not be added to the mirror cache. The default is not transient.
41 * @returns {Mirror} the mirror reflects the passed value or object
42 */
43 function MakeMirror(value, opt_transient) {
44 var mirror;
45
46 // Look for non transient mirrors in the mirror cache.
47 if (!opt_transient && mirror_cache_enabled_) {
48 for (var id in mirror_cache_) {
49 mirror = mirror_cache_[id];
50 if (mirror.value() === value) {
51 return mirror;
52 }
53 // Special check for NaN as NaN == NaN is false.
54 if (mirror.isNumber() && isNaN(mirror.value()) &&
55 typeof value == 'number' && isNaN(value)) {
56 return mirror;
57 }
58 }
59 }
60
61 if (IS_UNDEFINED(value)) {
62 mirror = new UndefinedMirror();
63 } else if (IS_NULL(value)) {
64 mirror = new NullMirror();
65 } else if (IS_BOOLEAN(value)) {
66 mirror = new BooleanMirror(value);
67 } else if (IS_NUMBER(value)) {
68 mirror = new NumberMirror(value);
69 } else if (IS_STRING(value)) {
70 mirror = new StringMirror(value);
71 } else if (IS_SYMBOL(value)) {
72 mirror = new SymbolMirror(value);
73 } else if (IS_ARRAY(value)) {
74 mirror = new ArrayMirror(value);
75 } else if (IS_DATE(value)) {
76 mirror = new DateMirror(value);
77 } else if (IS_FUNCTION(value)) {
78 mirror = new FunctionMirror(value);
79 } else if (IS_REGEXP(value)) {
80 mirror = new RegExpMirror(value);
81 } else if (IS_ERROR(value)) {
82 mirror = new ErrorMirror(value);
83 } else if (IS_SCRIPT(value)) {
84 mirror = new ScriptMirror(value);
85 } else if (IS_MAP(value) || IS_WEAKMAP(value)) {
86 mirror = new MapMirror(value);
87 } else if (IS_SET(value) || IS_WEAKSET(value)) {
88 mirror = new SetMirror(value);
89 } else if (IS_MAP_ITERATOR(value) || IS_SET_ITERATOR(value)) {
90 mirror = new IteratorMirror(value);
91 } else if (ObjectIsPromise(value)) {
92 mirror = new PromiseMirror(value);
93 } else if (IS_GENERATOR(value)) {
94 mirror = new GeneratorMirror(value);
95 } else {
96 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
97 }
98
99 if (mirror_cache_enabled_) mirror_cache_[mirror.handle()] = mirror;
100 return mirror;
101 }
102
103
104 /**
105 * Returns the mirror for a specified mirror handle.
106 *
107 * @param {number} handle the handle to find the mirror for
108 * @returns {Mirror or undefiend} the mirror with the requested handle or
109 * undefined if no mirror with the requested handle was found
110 */
111 function LookupMirror(handle) {
112 if (!mirror_cache_enabled_) throw new Error("Mirror cache is disabled");
113 return mirror_cache_[handle];
114 }
115
116
117 /**
118 * Returns the mirror for the undefined value.
119 *
120 * @returns {Mirror} the mirror reflects the undefined value
121 */
122 function GetUndefinedMirror() {
123 return MakeMirror(UNDEFINED);
124 }
125
126
127 /**
128 * Inherit the prototype methods from one constructor into another.
129 *
130 * The Function.prototype.inherits from lang.js rewritten as a standalone
131 * function (not on Function.prototype). NOTE: If this file is to be loaded
132 * during bootstrapping this function needs to be revritten using some native
133 * functions as prototype setup using normal JavaScript does not work as
134 * expected during bootstrapping (see mirror.js in r114903).
135 *
136 * @param {function} ctor Constructor function which needs to inherit the
137 * prototype
138 * @param {function} superCtor Constructor function to inherit prototype from
139 */
140 function inherits(ctor, superCtor) {
141 var tempCtor = function(){};
142 tempCtor.prototype = superCtor.prototype;
143 ctor.super_ = superCtor.prototype;
144 ctor.prototype = new tempCtor();
145 ctor.prototype.constructor = ctor;
146 }
147
148
149 // Type names of the different mirrors.
150 var UNDEFINED_TYPE = 'undefined';
151 var NULL_TYPE = 'null';
152 var BOOLEAN_TYPE = 'boolean';
153 var NUMBER_TYPE = 'number';
154 var STRING_TYPE = 'string';
155 var SYMBOL_TYPE = 'symbol';
156 var OBJECT_TYPE = 'object';
157 var FUNCTION_TYPE = 'function';
158 var REGEXP_TYPE = 'regexp';
159 var ERROR_TYPE = 'error';
160 var PROPERTY_TYPE = 'property';
161 var INTERNAL_PROPERTY_TYPE = 'internalProperty';
162 var FRAME_TYPE = 'frame';
163 var SCRIPT_TYPE = 'script';
164 var CONTEXT_TYPE = 'context';
165 var SCOPE_TYPE = 'scope';
166 var PROMISE_TYPE = 'promise';
167 var MAP_TYPE = 'map';
168 var SET_TYPE = 'set';
169 var ITERATOR_TYPE = 'iterator';
170 var GENERATOR_TYPE = 'generator';
171
172 // Maximum length when sending strings through the JSON protocol.
173 var kMaxProtocolStringLength = 80;
174
175 // Different kind of properties.
176 var PropertyKind = {};
177 PropertyKind.Named = 1;
178 PropertyKind.Indexed = 2;
179
180
181 // A copy of the PropertyType enum from property-details.h
182 var PropertyType = {};
183 PropertyType.Data = 0;
184 PropertyType.DataConstant = 2;
185 PropertyType.AccessorConstant = 3;
186
187
188 // Different attributes for a property.
189 var PropertyAttribute = {};
190 PropertyAttribute.None = NONE;
191 PropertyAttribute.ReadOnly = READ_ONLY;
192 PropertyAttribute.DontEnum = DONT_ENUM;
193 PropertyAttribute.DontDelete = DONT_DELETE;
194
195
196 // A copy of the scope types from runtime-debug.cc.
197 // NOTE: these constants should be backward-compatible, so
198 // add new ones to the end of this list.
199 var ScopeType = { Global: 0,
200 Local: 1,
201 With: 2,
202 Closure: 3,
203 Catch: 4,
204 Block: 5,
205 Script: 6 };
206
207
208 // Mirror hierarchy:
209 // - Mirror
210 // - ValueMirror
211 // - UndefinedMirror
212 // - NullMirror
213 // - NumberMirror
214 // - StringMirror
215 // - SymbolMirror
216 // - ObjectMirror
217 // - FunctionMirror
218 // - UnresolvedFunctionMirror
219 // - ArrayMirror
220 // - DateMirror
221 // - RegExpMirror
222 // - ErrorMirror
223 // - PromiseMirror
224 // - MapMirror
225 // - SetMirror
226 // - IteratorMirror
227 // - GeneratorMirror
228 // - PropertyMirror
229 // - InternalPropertyMirror
230 // - FrameMirror
231 // - ScriptMirror
232
233
234 /**
235 * Base class for all mirror objects.
236 * @param {string} type The type of the mirror
237 * @constructor
238 */
239 function Mirror(type) {
240 this.type_ = type;
241 }
242
243
244 Mirror.prototype.type = function() {
245 return this.type_;
246 };
247
248
249 /**
250 * Check whether the mirror reflects a value.
251 * @returns {boolean} True if the mirror reflects a value.
252 */
253 Mirror.prototype.isValue = function() {
254 return this instanceof ValueMirror;
255 };
256
257
258 /**
259 * Check whether the mirror reflects the undefined value.
260 * @returns {boolean} True if the mirror reflects the undefined value.
261 */
262 Mirror.prototype.isUndefined = function() {
263 return this instanceof UndefinedMirror;
264 };
265
266
267 /**
268 * Check whether the mirror reflects the null value.
269 * @returns {boolean} True if the mirror reflects the null value
270 */
271 Mirror.prototype.isNull = function() {
272 return this instanceof NullMirror;
273 };
274
275
276 /**
277 * Check whether the mirror reflects a boolean value.
278 * @returns {boolean} True if the mirror reflects a boolean value
279 */
280 Mirror.prototype.isBoolean = function() {
281 return this instanceof BooleanMirror;
282 };
283
284
285 /**
286 * Check whether the mirror reflects a number value.
287 * @returns {boolean} True if the mirror reflects a number value
288 */
289 Mirror.prototype.isNumber = function() {
290 return this instanceof NumberMirror;
291 };
292
293
294 /**
295 * Check whether the mirror reflects a string value.
296 * @returns {boolean} True if the mirror reflects a string value
297 */
298 Mirror.prototype.isString = function() {
299 return this instanceof StringMirror;
300 };
301
302
303 /**
304 * Check whether the mirror reflects a symbol.
305 * @returns {boolean} True if the mirror reflects a symbol
306 */
307 Mirror.prototype.isSymbol = function() {
308 return this instanceof SymbolMirror;
309 };
310
311
312 /**
313 * Check whether the mirror reflects an object.
314 * @returns {boolean} True if the mirror reflects an object
315 */
316 Mirror.prototype.isObject = function() {
317 return this instanceof ObjectMirror;
318 };
319
320
321 /**
322 * Check whether the mirror reflects a function.
323 * @returns {boolean} True if the mirror reflects a function
324 */
325 Mirror.prototype.isFunction = function() {
326 return this instanceof FunctionMirror;
327 };
328
329
330 /**
331 * Check whether the mirror reflects an unresolved function.
332 * @returns {boolean} True if the mirror reflects an unresolved function
333 */
334 Mirror.prototype.isUnresolvedFunction = function() {
335 return this instanceof UnresolvedFunctionMirror;
336 };
337
338
339 /**
340 * Check whether the mirror reflects an array.
341 * @returns {boolean} True if the mirror reflects an array
342 */
343 Mirror.prototype.isArray = function() {
344 return this instanceof ArrayMirror;
345 };
346
347
348 /**
349 * Check whether the mirror reflects a date.
350 * @returns {boolean} True if the mirror reflects a date
351 */
352 Mirror.prototype.isDate = function() {
353 return this instanceof DateMirror;
354 };
355
356
357 /**
358 * Check whether the mirror reflects a regular expression.
359 * @returns {boolean} True if the mirror reflects a regular expression
360 */
361 Mirror.prototype.isRegExp = function() {
362 return this instanceof RegExpMirror;
363 };
364
365
366 /**
367 * Check whether the mirror reflects an error.
368 * @returns {boolean} True if the mirror reflects an error
369 */
370 Mirror.prototype.isError = function() {
371 return this instanceof ErrorMirror;
372 };
373
374
375 /**
376 * Check whether the mirror reflects a promise.
377 * @returns {boolean} True if the mirror reflects a promise
378 */
379 Mirror.prototype.isPromise = function() {
380 return this instanceof PromiseMirror;
381 };
382
383
384 /**
385 * Check whether the mirror reflects a generator object.
386 * @returns {boolean} True if the mirror reflects a generator object
387 */
388 Mirror.prototype.isGenerator = function() {
389 return this instanceof GeneratorMirror;
390 };
391
392
393 /**
394 * Check whether the mirror reflects a property.
395 * @returns {boolean} True if the mirror reflects a property
396 */
397 Mirror.prototype.isProperty = function() {
398 return this instanceof PropertyMirror;
399 };
400
401
402 /**
403 * Check whether the mirror reflects an internal property.
404 * @returns {boolean} True if the mirror reflects an internal property
405 */
406 Mirror.prototype.isInternalProperty = function() {
407 return this instanceof InternalPropertyMirror;
408 };
409
410
411 /**
412 * Check whether the mirror reflects a stack frame.
413 * @returns {boolean} True if the mirror reflects a stack frame
414 */
415 Mirror.prototype.isFrame = function() {
416 return this instanceof FrameMirror;
417 };
418
419
420 /**
421 * Check whether the mirror reflects a script.
422 * @returns {boolean} True if the mirror reflects a script
423 */
424 Mirror.prototype.isScript = function() {
425 return this instanceof ScriptMirror;
426 };
427
428
429 /**
430 * Check whether the mirror reflects a context.
431 * @returns {boolean} True if the mirror reflects a context
432 */
433 Mirror.prototype.isContext = function() {
434 return this instanceof ContextMirror;
435 };
436
437
438 /**
439 * Check whether the mirror reflects a scope.
440 * @returns {boolean} True if the mirror reflects a scope
441 */
442 Mirror.prototype.isScope = function() {
443 return this instanceof ScopeMirror;
444 };
445
446
447 /**
448 * Check whether the mirror reflects a map.
449 * @returns {boolean} True if the mirror reflects a map
450 */
451 Mirror.prototype.isMap = function() {
452 return this instanceof MapMirror;
453 };
454
455
456 /**
457 * Check whether the mirror reflects a set.
458 * @returns {boolean} True if the mirror reflects a set
459 */
460 Mirror.prototype.isSet = function() {
461 return this instanceof SetMirror;
462 };
463
464
465 /**
466 * Check whether the mirror reflects an iterator.
467 * @returns {boolean} True if the mirror reflects an iterator
468 */
469 Mirror.prototype.isIterator = function() {
470 return this instanceof IteratorMirror;
471 };
472
473
474 /**
475 * Allocate a handle id for this object.
476 */
477 Mirror.prototype.allocateHandle_ = function() {
478 if (mirror_cache_enabled_) this.handle_ = next_handle_++;
479 };
480
481
482 /**
483 * Allocate a transient handle id for this object. Transient handles are
484 * negative.
485 */
486 Mirror.prototype.allocateTransientHandle_ = function() {
487 this.handle_ = next_transient_handle_--;
488 };
489
490
491 Mirror.prototype.toText = function() {
492 // Simpel to text which is used when on specialization in subclass.
493 return "#<" + this.constructor.name + ">";
494 };
495
496
497 /**
498 * Base class for all value mirror objects.
499 * @param {string} type The type of the mirror
500 * @param {value} value The value reflected by this mirror
501 * @param {boolean} transient indicate whether this object is transient with a
502 * transient handle
503 * @constructor
504 * @extends Mirror
505 */
506 function ValueMirror(type, value, transient) {
507 %_CallFunction(this, type, Mirror);
508 this.value_ = value;
509 if (!transient) {
510 this.allocateHandle_();
511 } else {
512 this.allocateTransientHandle_();
513 }
514 }
515 inherits(ValueMirror, Mirror);
516
517
518 Mirror.prototype.handle = function() {
519 return this.handle_;
520 };
521
522
523 /**
524 * Check whether this is a primitive value.
525 * @return {boolean} True if the mirror reflects a primitive value
526 */
527 ValueMirror.prototype.isPrimitive = function() {
528 var type = this.type();
529 return type === 'undefined' ||
530 type === 'null' ||
531 type === 'boolean' ||
532 type === 'number' ||
533 type === 'string' ||
534 type === 'symbol';
535 };
536
537
538 /**
539 * Get the actual value reflected by this mirror.
540 * @return {value} The value reflected by this mirror
541 */
542 ValueMirror.prototype.value = function() {
543 return this.value_;
544 };
545
546
547 /**
548 * Mirror object for Undefined.
549 * @constructor
550 * @extends ValueMirror
551 */
552 function UndefinedMirror() {
553 %_CallFunction(this, UNDEFINED_TYPE, UNDEFINED, ValueMirror);
554 }
555 inherits(UndefinedMirror, ValueMirror);
556
557
558 UndefinedMirror.prototype.toText = function() {
559 return 'undefined';
560 };
561
562
563 /**
564 * Mirror object for null.
565 * @constructor
566 * @extends ValueMirror
567 */
568 function NullMirror() {
569 %_CallFunction(this, NULL_TYPE, null, ValueMirror);
570 }
571 inherits(NullMirror, ValueMirror);
572
573
574 NullMirror.prototype.toText = function() {
575 return 'null';
576 };
577
578
579 /**
580 * Mirror object for boolean values.
581 * @param {boolean} value The boolean value reflected by this mirror
582 * @constructor
583 * @extends ValueMirror
584 */
585 function BooleanMirror(value) {
586 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
587 }
588 inherits(BooleanMirror, ValueMirror);
589
590
591 BooleanMirror.prototype.toText = function() {
592 return this.value_ ? 'true' : 'false';
593 };
594
595
596 /**
597 * Mirror object for number values.
598 * @param {number} value The number value reflected by this mirror
599 * @constructor
600 * @extends ValueMirror
601 */
602 function NumberMirror(value) {
603 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
604 }
605 inherits(NumberMirror, ValueMirror);
606
607
608 NumberMirror.prototype.toText = function() {
609 return %_NumberToString(this.value_);
610 };
611
612
613 /**
614 * Mirror object for string values.
615 * @param {string} value The string value reflected by this mirror
616 * @constructor
617 * @extends ValueMirror
618 */
619 function StringMirror(value) {
620 %_CallFunction(this, STRING_TYPE, value, ValueMirror);
621 }
622 inherits(StringMirror, ValueMirror);
623
624
625 StringMirror.prototype.length = function() {
626 return this.value_.length;
627 };
628
629 StringMirror.prototype.getTruncatedValue = function(maxLength) {
630 if (maxLength != -1 && this.length() > maxLength) {
631 return this.value_.substring(0, maxLength) +
632 '... (length: ' + this.length() + ')';
633 }
634 return this.value_;
635 };
636
637 StringMirror.prototype.toText = function() {
638 return this.getTruncatedValue(kMaxProtocolStringLength);
639 };
640
641
642 /**
643 * Mirror object for a Symbol
644 * @param {Object} value The Symbol
645 * @constructor
646 * @extends Mirror
647 */
648 function SymbolMirror(value) {
649 %_CallFunction(this, SYMBOL_TYPE, value, ValueMirror);
650 }
651 inherits(SymbolMirror, ValueMirror);
652
653
654 SymbolMirror.prototype.description = function() {
655 return %SymbolDescription(%_ValueOf(this.value_));
656 }
657
658
659 SymbolMirror.prototype.toText = function() {
660 return %_CallFunction(this.value_, builtins.$symbolToString);
661 }
662
663
664 /**
665 * Mirror object for objects.
666 * @param {object} value The object reflected by this mirror
667 * @param {boolean} transient indicate whether this object is transient with a
668 * transient handle
669 * @constructor
670 * @extends ValueMirror
671 */
672 function ObjectMirror(value, type, transient) {
673 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
674 }
675 inherits(ObjectMirror, ValueMirror);
676
677
678 ObjectMirror.prototype.className = function() {
679 return %_ClassOf(this.value_);
680 };
681
682
683 ObjectMirror.prototype.constructorFunction = function() {
684 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
685 };
686
687
688 ObjectMirror.prototype.prototypeObject = function() {
689 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
690 };
691
692
693 ObjectMirror.prototype.protoObject = function() {
694 return MakeMirror(%DebugGetPrototype(this.value_));
695 };
696
697
698 ObjectMirror.prototype.hasNamedInterceptor = function() {
699 // Get information on interceptors for this object.
700 var x = %GetInterceptorInfo(this.value_);
701 return (x & 2) != 0;
702 };
703
704
705 ObjectMirror.prototype.hasIndexedInterceptor = function() {
706 // Get information on interceptors for this object.
707 var x = %GetInterceptorInfo(this.value_);
708 return (x & 1) != 0;
709 };
710
711
712 // Get all own property names except for private symbols.
713 function TryGetPropertyNames(object) {
714 try {
715 // TODO(yangguo): Should there be a special debugger implementation of
716 // %GetOwnPropertyNames that doesn't perform access checks?
717 return %GetOwnPropertyNames(object, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL);
718 } catch (e) {
719 // Might have hit a failed access check.
720 return [];
721 }
722 }
723
724
725 /**
726 * Return the property names for this object.
727 * @param {number} kind Indicate whether named, indexed or both kinds of
728 * properties are requested
729 * @param {number} limit Limit the number of names returend to the specified
730 value
731 * @return {Array} Property names for this object
732 */
733 ObjectMirror.prototype.propertyNames = function(kind, limit) {
734 // Find kind and limit and allocate array for the result
735 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
736
737 var propertyNames;
738 var elementNames;
739 var total = 0;
740
741 // Find all the named properties.
742 if (kind & PropertyKind.Named) {
743 propertyNames = TryGetPropertyNames(this.value_);
744 total += propertyNames.length;
745
746 // Get names for named interceptor properties if any.
747 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
748 var namedInterceptorNames =
749 %GetNamedInterceptorPropertyNames(this.value_);
750 if (namedInterceptorNames) {
751 propertyNames = propertyNames.concat(namedInterceptorNames);
752 total += namedInterceptorNames.length;
753 }
754 }
755 }
756
757 // Find all the indexed properties.
758 if (kind & PropertyKind.Indexed) {
759 // Get own element names.
760 elementNames = %GetOwnElementNames(this.value_);
761 total += elementNames.length;
762
763 // Get names for indexed interceptor properties.
764 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
765 var indexedInterceptorNames =
766 %GetIndexedInterceptorElementNames(this.value_);
767 if (indexedInterceptorNames) {
768 elementNames = elementNames.concat(indexedInterceptorNames);
769 total += indexedInterceptorNames.length;
770 }
771 }
772 }
773 limit = Math.min(limit || total, total);
774
775 var names = new Array(limit);
776 var index = 0;
777
778 // Copy names for named properties.
779 if (kind & PropertyKind.Named) {
780 for (var i = 0; index < limit && i < propertyNames.length; i++) {
781 names[index++] = propertyNames[i];
782 }
783 }
784
785 // Copy names for indexed properties.
786 if (kind & PropertyKind.Indexed) {
787 for (var i = 0; index < limit && i < elementNames.length; i++) {
788 names[index++] = elementNames[i];
789 }
790 }
791
792 return names;
793 };
794
795
796 /**
797 * Return the properties for this object as an array of PropertyMirror objects.
798 * @param {number} kind Indicate whether named, indexed or both kinds of
799 * properties are requested
800 * @param {number} limit Limit the number of properties returned to the
801 specified value
802 * @return {Array} Property mirrors for this object
803 */
804 ObjectMirror.prototype.properties = function(kind, limit) {
805 var names = this.propertyNames(kind, limit);
806 var properties = new Array(names.length);
807 for (var i = 0; i < names.length; i++) {
808 properties[i] = this.property(names[i]);
809 }
810
811 return properties;
812 };
813
814
815 /**
816 * Return the internal properties for this object as an array of
817 * InternalPropertyMirror objects.
818 * @return {Array} Property mirrors for this object
819 */
820 ObjectMirror.prototype.internalProperties = function() {
821 return ObjectMirror.GetInternalProperties(this.value_);
822 }
823
824
825 ObjectMirror.prototype.property = function(name) {
826 var details = %DebugGetPropertyDetails(this.value_, builtins.$toName(name));
827 if (details) {
828 return new PropertyMirror(this, name, details);
829 }
830
831 // Nothing found.
832 return GetUndefinedMirror();
833 };
834
835
836
837 /**
838 * Try to find a property from its value.
839 * @param {Mirror} value The property value to look for
840 * @return {PropertyMirror} The property with the specified value. If no
841 * property was found with the specified value UndefinedMirror is returned
842 */
843 ObjectMirror.prototype.lookupProperty = function(value) {
844 var properties = this.properties();
845
846 // Look for property value in properties.
847 for (var i = 0; i < properties.length; i++) {
848
849 // Skip properties which are defined through assessors.
850 var property = properties[i];
851 if (property.propertyType() != PropertyType.AccessorConstant) {
852 if (%_ObjectEquals(property.value_, value.value_)) {
853 return property;
854 }
855 }
856 }
857
858 // Nothing found.
859 return GetUndefinedMirror();
860 };
861
862
863 /**
864 * Returns objects which has direct references to this object
865 * @param {number} opt_max_objects Optional parameter specifying the maximum
866 * number of referencing objects to return.
867 * @return {Array} The objects which has direct references to this object.
868 */
869 ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
870 // Find all objects with direct references to this object.
871 var result = %DebugReferencedBy(this.value_,
872 Mirror.prototype, opt_max_objects || 0);
873
874 // Make mirrors for all the references found.
875 for (var i = 0; i < result.length; i++) {
876 result[i] = MakeMirror(result[i]);
877 }
878
879 return result;
880 };
881
882
883 ObjectMirror.prototype.toText = function() {
884 var name;
885 var ctor = this.constructorFunction();
886 if (!ctor.isFunction()) {
887 name = this.className();
888 } else {
889 name = ctor.name();
890 if (!name) {
891 name = this.className();
892 }
893 }
894 return '#<' + name + '>';
895 };
896
897
898 /**
899 * Return the internal properties of the value, such as [[PrimitiveValue]] of
900 * scalar wrapper objects, properties of the bound function and properties of
901 * the promise.
902 * This method is done static to be accessible from Debug API with the bare
903 * values without mirrors.
904 * @return {Array} array (possibly empty) of InternalProperty instances
905 */
906 ObjectMirror.GetInternalProperties = function(value) {
907 var properties = %DebugGetInternalProperties(value);
908 var result = [];
909 for (var i = 0; i < properties.length; i += 2) {
910 result.push(new InternalPropertyMirror(properties[i], properties[i + 1]));
911 }
912 return result;
913 }
914
915
916 /**
917 * Mirror object for functions.
918 * @param {function} value The function object reflected by this mirror.
919 * @constructor
920 * @extends ObjectMirror
921 */
922 function FunctionMirror(value) {
923 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
924 this.resolved_ = true;
925 }
926 inherits(FunctionMirror, ObjectMirror);
927
928
929 /**
930 * Returns whether the function is resolved.
931 * @return {boolean} True if the function is resolved. Unresolved functions can
932 * only originate as functions from stack frames
933 */
934 FunctionMirror.prototype.resolved = function() {
935 return this.resolved_;
936 };
937
938
939 /**
940 * Returns the name of the function.
941 * @return {string} Name of the function
942 */
943 FunctionMirror.prototype.name = function() {
944 return %FunctionGetName(this.value_);
945 };
946
947
948 /**
949 * Returns the inferred name of the function.
950 * @return {string} Name of the function
951 */
952 FunctionMirror.prototype.inferredName = function() {
953 return %FunctionGetInferredName(this.value_);
954 };
955
956
957 /**
958 * Returns the source code for the function.
959 * @return {string or undefined} The source code for the function. If the
960 * function is not resolved undefined will be returned.
961 */
962 FunctionMirror.prototype.source = function() {
963 // Return source if function is resolved. Otherwise just fall through to
964 // return undefined.
965 if (this.resolved()) {
966 return builtins.$functionSourceString(this.value_);
967 }
968 };
969
970
971 /**
972 * Returns the script object for the function.
973 * @return {ScriptMirror or undefined} Script object for the function or
974 * undefined if the function has no script
975 */
976 FunctionMirror.prototype.script = function() {
977 // Return script if function is resolved. Otherwise just fall through
978 // to return undefined.
979 if (this.resolved()) {
980 if (this.script_) {
981 return this.script_;
982 }
983 var script = %FunctionGetScript(this.value_);
984 if (script) {
985 return this.script_ = MakeMirror(script);
986 }
987 }
988 };
989
990
991 /**
992 * Returns the script source position for the function. Only makes sense
993 * for functions which has a script defined.
994 * @return {Number or undefined} in-script position for the function
995 */
996 FunctionMirror.prototype.sourcePosition_ = function() {
997 // Return position if function is resolved. Otherwise just fall
998 // through to return undefined.
999 if (this.resolved()) {
1000 return %FunctionGetScriptSourcePosition(this.value_);
1001 }
1002 };
1003
1004
1005 /**
1006 * Returns the script source location object for the function. Only makes sense
1007 * for functions which has a script defined.
1008 * @return {Location or undefined} in-script location for the function begin
1009 */
1010 FunctionMirror.prototype.sourceLocation = function() {
1011 if (this.resolved()) {
1012 var script = this.script();
1013 if (script) {
1014 return script.locationFromPosition(this.sourcePosition_(), true);
1015 }
1016 }
1017 };
1018
1019
1020 /**
1021 * Returns objects constructed by this function.
1022 * @param {number} opt_max_instances Optional parameter specifying the maximum
1023 * number of instances to return.
1024 * @return {Array or undefined} The objects constructed by this function.
1025 */
1026 FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
1027 if (this.resolved()) {
1028 // Find all objects constructed from this function.
1029 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
1030
1031 // Make mirrors for all the instances found.
1032 for (var i = 0; i < result.length; i++) {
1033 result[i] = MakeMirror(result[i]);
1034 }
1035
1036 return result;
1037 } else {
1038 return [];
1039 }
1040 };
1041
1042
1043 FunctionMirror.prototype.scopeCount = function() {
1044 if (this.resolved()) {
1045 if (IS_UNDEFINED(this.scopeCount_)) {
1046 this.scopeCount_ = %GetFunctionScopeCount(this.value());
1047 }
1048 return this.scopeCount_;
1049 } else {
1050 return 0;
1051 }
1052 };
1053
1054
1055 FunctionMirror.prototype.scope = function(index) {
1056 if (this.resolved()) {
1057 return new ScopeMirror(UNDEFINED, this, index);
1058 }
1059 };
1060
1061
1062 FunctionMirror.prototype.toText = function() {
1063 return this.source();
1064 };
1065
1066
1067 /**
1068 * Mirror object for unresolved functions.
1069 * @param {string} value The name for the unresolved function reflected by this
1070 * mirror.
1071 * @constructor
1072 * @extends ObjectMirror
1073 */
1074 function UnresolvedFunctionMirror(value) {
1075 // Construct this using the ValueMirror as an unresolved function is not a
1076 // real object but just a string.
1077 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
1078 this.propertyCount_ = 0;
1079 this.elementCount_ = 0;
1080 this.resolved_ = false;
1081 }
1082 inherits(UnresolvedFunctionMirror, FunctionMirror);
1083
1084
1085 UnresolvedFunctionMirror.prototype.className = function() {
1086 return 'Function';
1087 };
1088
1089
1090 UnresolvedFunctionMirror.prototype.constructorFunction = function() {
1091 return GetUndefinedMirror();
1092 };
1093
1094
1095 UnresolvedFunctionMirror.prototype.prototypeObject = function() {
1096 return GetUndefinedMirror();
1097 };
1098
1099
1100 UnresolvedFunctionMirror.prototype.protoObject = function() {
1101 return GetUndefinedMirror();
1102 };
1103
1104
1105 UnresolvedFunctionMirror.prototype.name = function() {
1106 return this.value_;
1107 };
1108
1109
1110 UnresolvedFunctionMirror.prototype.inferredName = function() {
1111 return undefined;
1112 };
1113
1114
1115 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
1116 return [];
1117 };
1118
1119
1120 /**
1121 * Mirror object for arrays.
1122 * @param {Array} value The Array object reflected by this mirror
1123 * @constructor
1124 * @extends ObjectMirror
1125 */
1126 function ArrayMirror(value) {
1127 %_CallFunction(this, value, ObjectMirror);
1128 }
1129 inherits(ArrayMirror, ObjectMirror);
1130
1131
1132 ArrayMirror.prototype.length = function() {
1133 return this.value_.length;
1134 };
1135
1136
1137 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
1138 opt_to_index) {
1139 var from_index = opt_from_index || 0;
1140 var to_index = opt_to_index || this.length() - 1;
1141 if (from_index > to_index) return new Array();
1142 var values = new Array(to_index - from_index + 1);
1143 for (var i = from_index; i <= to_index; i++) {
1144 var details = %DebugGetPropertyDetails(this.value_, builtins.$toString(i));
1145 var value;
1146 if (details) {
1147 value = new PropertyMirror(this, i, details);
1148 } else {
1149 value = GetUndefinedMirror();
1150 }
1151 values[i - from_index] = value;
1152 }
1153 return values;
1154 };
1155
1156
1157 /**
1158 * Mirror object for dates.
1159 * @param {Date} value The Date object reflected by this mirror
1160 * @constructor
1161 * @extends ObjectMirror
1162 */
1163 function DateMirror(value) {
1164 %_CallFunction(this, value, ObjectMirror);
1165 }
1166 inherits(DateMirror, ObjectMirror);
1167
1168
1169 DateMirror.prototype.toText = function() {
1170 var s = JSON.stringify(this.value_);
1171 return s.substring(1, s.length - 1); // cut quotes
1172 };
1173
1174
1175 /**
1176 * Mirror object for regular expressions.
1177 * @param {RegExp} value The RegExp object reflected by this mirror
1178 * @constructor
1179 * @extends ObjectMirror
1180 */
1181 function RegExpMirror(value) {
1182 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
1183 }
1184 inherits(RegExpMirror, ObjectMirror);
1185
1186
1187 /**
1188 * Returns the source to the regular expression.
1189 * @return {string or undefined} The source to the regular expression
1190 */
1191 RegExpMirror.prototype.source = function() {
1192 return this.value_.source;
1193 };
1194
1195
1196 /**
1197 * Returns whether this regular expression has the global (g) flag set.
1198 * @return {boolean} Value of the global flag
1199 */
1200 RegExpMirror.prototype.global = function() {
1201 return this.value_.global;
1202 };
1203
1204
1205 /**
1206 * Returns whether this regular expression has the ignore case (i) flag set.
1207 * @return {boolean} Value of the ignore case flag
1208 */
1209 RegExpMirror.prototype.ignoreCase = function() {
1210 return this.value_.ignoreCase;
1211 };
1212
1213
1214 /**
1215 * Returns whether this regular expression has the multiline (m) flag set.
1216 * @return {boolean} Value of the multiline flag
1217 */
1218 RegExpMirror.prototype.multiline = function() {
1219 return this.value_.multiline;
1220 };
1221
1222
1223 /**
1224 * Returns whether this regular expression has the sticky (y) flag set.
1225 * @return {boolean} Value of the sticky flag
1226 */
1227 RegExpMirror.prototype.sticky = function() {
1228 return this.value_.sticky;
1229 };
1230
1231
1232 /**
1233 * Returns whether this regular expression has the unicode (u) flag set.
1234 * @return {boolean} Value of the unicode flag
1235 */
1236 RegExpMirror.prototype.unicode = function() {
1237 return this.value_.unicode;
1238 };
1239
1240
1241 RegExpMirror.prototype.toText = function() {
1242 // Simpel to text which is used when on specialization in subclass.
1243 return "/" + this.source() + "/";
1244 };
1245
1246
1247 /**
1248 * Mirror object for error objects.
1249 * @param {Error} value The error object reflected by this mirror
1250 * @constructor
1251 * @extends ObjectMirror
1252 */
1253 function ErrorMirror(value) {
1254 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
1255 }
1256 inherits(ErrorMirror, ObjectMirror);
1257
1258
1259 /**
1260 * Returns the message for this eror object.
1261 * @return {string or undefined} The message for this eror object
1262 */
1263 ErrorMirror.prototype.message = function() {
1264 return this.value_.message;
1265 };
1266
1267
1268 ErrorMirror.prototype.toText = function() {
1269 // Use the same text representation as in messages.js.
1270 var text;
1271 try {
1272 text = %_CallFunction(this.value_, builtins.$errorToString);
1273 } catch (e) {
1274 text = '#<Error>';
1275 }
1276 return text;
1277 };
1278
1279
1280 /**
1281 * Mirror object for a Promise object.
1282 * @param {Object} value The Promise object
1283 * @constructor
1284 * @extends ObjectMirror
1285 */
1286 function PromiseMirror(value) {
1287 %_CallFunction(this, value, PROMISE_TYPE, ObjectMirror);
1288 }
1289 inherits(PromiseMirror, ObjectMirror);
1290
1291
1292 function PromiseGetStatus_(value) {
1293 var status = %DebugGetProperty(value, builtins.$promiseStatus);
1294 if (status == 0) return "pending";
1295 if (status == 1) return "resolved";
1296 return "rejected";
1297 }
1298
1299
1300 function PromiseGetValue_(value) {
1301 return %DebugGetProperty(value, builtins.$promiseValue);
1302 }
1303
1304
1305 PromiseMirror.prototype.status = function() {
1306 return PromiseGetStatus_(this.value_);
1307 };
1308
1309
1310 PromiseMirror.prototype.promiseValue = function() {
1311 return MakeMirror(PromiseGetValue_(this.value_));
1312 };
1313
1314
1315 function MapMirror(value) {
1316 %_CallFunction(this, value, MAP_TYPE, ObjectMirror);
1317 }
1318 inherits(MapMirror, ObjectMirror);
1319
1320
1321 /**
1322 * Returns an array of key/value pairs of a map.
1323 * This will keep keys alive for WeakMaps.
1324 *
1325 * @param {number=} opt_limit Max elements to return.
1326 * @returns {Array.<Object>} Array of key/value pairs of a map.
1327 */
1328 MapMirror.prototype.entries = function(opt_limit) {
1329 var result = [];
1330
1331 if (IS_WEAKMAP(this.value_)) {
1332 var entries = %GetWeakMapEntries(this.value_, opt_limit || 0);
1333 for (var i = 0; i < entries.length; i += 2) {
1334 result.push({
1335 key: entries[i],
1336 value: entries[i + 1]
1337 });
1338 }
1339 return result;
1340 }
1341
1342 var iter = %_CallFunction(this.value_, builtins.$mapEntries);
1343 var next;
1344 while ((!opt_limit || result.length < opt_limit) &&
1345 !(next = iter.next()).done) {
1346 result.push({
1347 key: next.value[0],
1348 value: next.value[1]
1349 });
1350 }
1351 return result;
1352 };
1353
1354
1355 function SetMirror(value) {
1356 %_CallFunction(this, value, SET_TYPE, ObjectMirror);
1357 }
1358 inherits(SetMirror, ObjectMirror);
1359
1360
1361 function IteratorGetValues_(iter, next_function, opt_limit) {
1362 var result = [];
1363 var next;
1364 while ((!opt_limit || result.length < opt_limit) &&
1365 !(next = %_CallFunction(iter, next_function)).done) {
1366 result.push(next.value);
1367 }
1368 return result;
1369 }
1370
1371
1372 /**
1373 * Returns an array of elements of a set.
1374 * This will keep elements alive for WeakSets.
1375 *
1376 * @param {number=} opt_limit Max elements to return.
1377 * @returns {Array.<Object>} Array of elements of a set.
1378 */
1379 SetMirror.prototype.values = function(opt_limit) {
1380 if (IS_WEAKSET(this.value_)) {
1381 return %GetWeakSetValues(this.value_, opt_limit || 0);
1382 }
1383
1384 var iter = %_CallFunction(this.value_, builtins.$setValues);
1385 return IteratorGetValues_(iter, builtins.$setIteratorNext, opt_limit);
1386 };
1387
1388
1389 function IteratorMirror(value) {
1390 %_CallFunction(this, value, ITERATOR_TYPE, ObjectMirror);
1391 }
1392 inherits(IteratorMirror, ObjectMirror);
1393
1394
1395 /**
1396 * Returns a preview of elements of an iterator.
1397 * Does not change the backing iterator state.
1398 *
1399 * @param {number=} opt_limit Max elements to return.
1400 * @returns {Array.<Object>} Array of elements of an iterator.
1401 */
1402 IteratorMirror.prototype.preview = function(opt_limit) {
1403 if (IS_MAP_ITERATOR(this.value_)) {
1404 return IteratorGetValues_(%MapIteratorClone(this.value_),
1405 builtins.$mapIteratorNext,
1406 opt_limit);
1407 } else if (IS_SET_ITERATOR(this.value_)) {
1408 return IteratorGetValues_(%SetIteratorClone(this.value_),
1409 builtins.$setIteratorNext,
1410 opt_limit);
1411 }
1412 };
1413
1414
1415 /**
1416 * Mirror object for a Generator object.
1417 * @param {Object} data The Generator object
1418 * @constructor
1419 * @extends Mirror
1420 */
1421 function GeneratorMirror(value) {
1422 %_CallFunction(this, value, GENERATOR_TYPE, ObjectMirror);
1423 }
1424 inherits(GeneratorMirror, ObjectMirror);
1425
1426
1427 function GeneratorGetStatus_(value) {
1428 var continuation = %GeneratorGetContinuation(value);
1429 if (continuation < 0) return "running";
1430 if (continuation == 0) return "closed";
1431 return "suspended";
1432 }
1433
1434
1435 GeneratorMirror.prototype.status = function() {
1436 return GeneratorGetStatus_(this.value_);
1437 };
1438
1439
1440 GeneratorMirror.prototype.sourcePosition_ = function() {
1441 return %GeneratorGetSourcePosition(this.value_);
1442 };
1443
1444
1445 GeneratorMirror.prototype.sourceLocation = function() {
1446 var pos = this.sourcePosition_();
1447 if (!IS_UNDEFINED(pos)) {
1448 var script = this.func().script();
1449 if (script) {
1450 return script.locationFromPosition(pos, true);
1451 }
1452 }
1453 };
1454
1455
1456 GeneratorMirror.prototype.func = function() {
1457 if (!this.func_) {
1458 this.func_ = MakeMirror(%GeneratorGetFunction(this.value_));
1459 }
1460 return this.func_;
1461 };
1462
1463
1464 GeneratorMirror.prototype.context = function() {
1465 if (!this.context_) {
1466 this.context_ = new ContextMirror(%GeneratorGetContext(this.value_));
1467 }
1468 return this.context_;
1469 };
1470
1471
1472 GeneratorMirror.prototype.receiver = function() {
1473 if (!this.receiver_) {
1474 this.receiver_ = MakeMirror(%GeneratorGetReceiver(this.value_));
1475 }
1476 return this.receiver_;
1477 };
1478
1479
1480 /**
1481 * Base mirror object for properties.
1482 * @param {ObjectMirror} mirror The mirror object having this property
1483 * @param {string} name The name of the property
1484 * @param {Array} details Details about the property
1485 * @constructor
1486 * @extends Mirror
1487 */
1488 function PropertyMirror(mirror, name, details) {
1489 %_CallFunction(this, PROPERTY_TYPE, Mirror);
1490 this.mirror_ = mirror;
1491 this.name_ = name;
1492 this.value_ = details[0];
1493 this.details_ = details[1];
1494 this.is_interceptor_ = details[2];
1495 if (details.length > 3) {
1496 this.exception_ = details[3];
1497 this.getter_ = details[4];
1498 this.setter_ = details[5];
1499 }
1500 }
1501 inherits(PropertyMirror, Mirror);
1502
1503
1504 PropertyMirror.prototype.isReadOnly = function() {
1505 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1506 };
1507
1508
1509 PropertyMirror.prototype.isEnum = function() {
1510 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1511 };
1512
1513
1514 PropertyMirror.prototype.canDelete = function() {
1515 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1516 };
1517
1518
1519 PropertyMirror.prototype.name = function() {
1520 return this.name_;
1521 };
1522
1523
1524 PropertyMirror.prototype.isIndexed = function() {
1525 for (var i = 0; i < this.name_.length; i++) {
1526 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1527 return false;
1528 }
1529 }
1530 return true;
1531 };
1532
1533
1534 PropertyMirror.prototype.value = function() {
1535 return MakeMirror(this.value_, false);
1536 };
1537
1538
1539 /**
1540 * Returns whether this property value is an exception.
1541 * @return {booolean} True if this property value is an exception
1542 */
1543 PropertyMirror.prototype.isException = function() {
1544 return this.exception_ ? true : false;
1545 };
1546
1547
1548 PropertyMirror.prototype.attributes = function() {
1549 return %DebugPropertyAttributesFromDetails(this.details_);
1550 };
1551
1552
1553 PropertyMirror.prototype.propertyType = function() {
1554 return %DebugPropertyTypeFromDetails(this.details_);
1555 };
1556
1557
1558 PropertyMirror.prototype.insertionIndex = function() {
1559 return %DebugPropertyIndexFromDetails(this.details_);
1560 };
1561
1562
1563 /**
1564 * Returns whether this property has a getter defined through __defineGetter__.
1565 * @return {booolean} True if this property has a getter
1566 */
1567 PropertyMirror.prototype.hasGetter = function() {
1568 return this.getter_ ? true : false;
1569 };
1570
1571
1572 /**
1573 * Returns whether this property has a setter defined through __defineSetter__.
1574 * @return {booolean} True if this property has a setter
1575 */
1576 PropertyMirror.prototype.hasSetter = function() {
1577 return this.setter_ ? true : false;
1578 };
1579
1580
1581 /**
1582 * Returns the getter for this property defined through __defineGetter__.
1583 * @return {Mirror} FunctionMirror reflecting the getter function or
1584 * UndefinedMirror if there is no getter for this property
1585 */
1586 PropertyMirror.prototype.getter = function() {
1587 if (this.hasGetter()) {
1588 return MakeMirror(this.getter_);
1589 } else {
1590 return GetUndefinedMirror();
1591 }
1592 };
1593
1594
1595 /**
1596 * Returns the setter for this property defined through __defineSetter__.
1597 * @return {Mirror} FunctionMirror reflecting the setter function or
1598 * UndefinedMirror if there is no setter for this property
1599 */
1600 PropertyMirror.prototype.setter = function() {
1601 if (this.hasSetter()) {
1602 return MakeMirror(this.setter_);
1603 } else {
1604 return GetUndefinedMirror();
1605 }
1606 };
1607
1608
1609 /**
1610 * Returns whether this property is natively implemented by the host or a set
1611 * through JavaScript code.
1612 * @return {boolean} True if the property is
1613 * UndefinedMirror if there is no setter for this property
1614 */
1615 PropertyMirror.prototype.isNative = function() {
1616 return this.is_interceptor_ ||
1617 ((this.propertyType() == PropertyType.AccessorConstant) &&
1618 !this.hasGetter() && !this.hasSetter());
1619 };
1620
1621
1622 /**
1623 * Mirror object for internal properties. Internal property reflects properties
1624 * not accessible from user code such as [[BoundThis]] in bound function.
1625 * Their names are merely symbolic.
1626 * @param {string} name The name of the property
1627 * @param {value} property value
1628 * @constructor
1629 * @extends Mirror
1630 */
1631 function InternalPropertyMirror(name, value) {
1632 %_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror);
1633 this.name_ = name;
1634 this.value_ = value;
1635 }
1636 inherits(InternalPropertyMirror, Mirror);
1637
1638
1639 InternalPropertyMirror.prototype.name = function() {
1640 return this.name_;
1641 };
1642
1643
1644 InternalPropertyMirror.prototype.value = function() {
1645 return MakeMirror(this.value_, false);
1646 };
1647
1648
1649 var kFrameDetailsFrameIdIndex = 0;
1650 var kFrameDetailsReceiverIndex = 1;
1651 var kFrameDetailsFunctionIndex = 2;
1652 var kFrameDetailsArgumentCountIndex = 3;
1653 var kFrameDetailsLocalCountIndex = 4;
1654 var kFrameDetailsSourcePositionIndex = 5;
1655 var kFrameDetailsConstructCallIndex = 6;
1656 var kFrameDetailsAtReturnIndex = 7;
1657 var kFrameDetailsFlagsIndex = 8;
1658 var kFrameDetailsFirstDynamicIndex = 9;
1659
1660 var kFrameDetailsNameIndex = 0;
1661 var kFrameDetailsValueIndex = 1;
1662 var kFrameDetailsNameValueSize = 2;
1663
1664 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1665 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1666 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
1667
1668 /**
1669 * Wrapper for the frame details information retreived from the VM. The frame
1670 * details from the VM is an array with the following content. See runtime.cc
1671 * Runtime_GetFrameDetails.
1672 * 0: Id
1673 * 1: Receiver
1674 * 2: Function
1675 * 3: Argument count
1676 * 4: Local count
1677 * 5: Source position
1678 * 6: Construct call
1679 * 7: Is at return
1680 * 8: Flags (debugger frame, optimized frame, inlined frame index)
1681 * Arguments name, value
1682 * Locals name, value
1683 * Return value if any
1684 * @param {number} break_id Current break id
1685 * @param {number} index Frame number
1686 * @constructor
1687 */
1688 function FrameDetails(break_id, index) {
1689 this.break_id_ = break_id;
1690 this.details_ = %GetFrameDetails(break_id, index);
1691 }
1692
1693
1694 FrameDetails.prototype.frameId = function() {
1695 %CheckExecutionState(this.break_id_);
1696 return this.details_[kFrameDetailsFrameIdIndex];
1697 };
1698
1699
1700 FrameDetails.prototype.receiver = function() {
1701 %CheckExecutionState(this.break_id_);
1702 return this.details_[kFrameDetailsReceiverIndex];
1703 };
1704
1705
1706 FrameDetails.prototype.func = function() {
1707 %CheckExecutionState(this.break_id_);
1708 return this.details_[kFrameDetailsFunctionIndex];
1709 };
1710
1711
1712 FrameDetails.prototype.isConstructCall = function() {
1713 %CheckExecutionState(this.break_id_);
1714 return this.details_[kFrameDetailsConstructCallIndex];
1715 };
1716
1717
1718 FrameDetails.prototype.isAtReturn = function() {
1719 %CheckExecutionState(this.break_id_);
1720 return this.details_[kFrameDetailsAtReturnIndex];
1721 };
1722
1723
1724 FrameDetails.prototype.isDebuggerFrame = function() {
1725 %CheckExecutionState(this.break_id_);
1726 var f = kFrameDetailsFlagDebuggerFrameMask;
1727 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1728 };
1729
1730
1731 FrameDetails.prototype.isOptimizedFrame = function() {
1732 %CheckExecutionState(this.break_id_);
1733 var f = kFrameDetailsFlagOptimizedFrameMask;
1734 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1735 };
1736
1737
1738 FrameDetails.prototype.isInlinedFrame = function() {
1739 return this.inlinedFrameIndex() > 0;
1740 };
1741
1742
1743 FrameDetails.prototype.inlinedFrameIndex = function() {
1744 %CheckExecutionState(this.break_id_);
1745 var f = kFrameDetailsFlagInlinedFrameIndexMask;
1746 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
1747 };
1748
1749
1750 FrameDetails.prototype.argumentCount = function() {
1751 %CheckExecutionState(this.break_id_);
1752 return this.details_[kFrameDetailsArgumentCountIndex];
1753 };
1754
1755
1756 FrameDetails.prototype.argumentName = function(index) {
1757 %CheckExecutionState(this.break_id_);
1758 if (index >= 0 && index < this.argumentCount()) {
1759 return this.details_[kFrameDetailsFirstDynamicIndex +
1760 index * kFrameDetailsNameValueSize +
1761 kFrameDetailsNameIndex];
1762 }
1763 };
1764
1765
1766 FrameDetails.prototype.argumentValue = function(index) {
1767 %CheckExecutionState(this.break_id_);
1768 if (index >= 0 && index < this.argumentCount()) {
1769 return this.details_[kFrameDetailsFirstDynamicIndex +
1770 index * kFrameDetailsNameValueSize +
1771 kFrameDetailsValueIndex];
1772 }
1773 };
1774
1775
1776 FrameDetails.prototype.localCount = function() {
1777 %CheckExecutionState(this.break_id_);
1778 return this.details_[kFrameDetailsLocalCountIndex];
1779 };
1780
1781
1782 FrameDetails.prototype.sourcePosition = function() {
1783 %CheckExecutionState(this.break_id_);
1784 return this.details_[kFrameDetailsSourcePositionIndex];
1785 };
1786
1787
1788 FrameDetails.prototype.localName = function(index) {
1789 %CheckExecutionState(this.break_id_);
1790 if (index >= 0 && index < this.localCount()) {
1791 var locals_offset = kFrameDetailsFirstDynamicIndex +
1792 this.argumentCount() * kFrameDetailsNameValueSize;
1793 return this.details_[locals_offset +
1794 index * kFrameDetailsNameValueSize +
1795 kFrameDetailsNameIndex];
1796 }
1797 };
1798
1799
1800 FrameDetails.prototype.localValue = function(index) {
1801 %CheckExecutionState(this.break_id_);
1802 if (index >= 0 && index < this.localCount()) {
1803 var locals_offset = kFrameDetailsFirstDynamicIndex +
1804 this.argumentCount() * kFrameDetailsNameValueSize;
1805 return this.details_[locals_offset +
1806 index * kFrameDetailsNameValueSize +
1807 kFrameDetailsValueIndex];
1808 }
1809 };
1810
1811
1812 FrameDetails.prototype.returnValue = function() {
1813 %CheckExecutionState(this.break_id_);
1814 var return_value_offset =
1815 kFrameDetailsFirstDynamicIndex +
1816 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1817 if (this.details_[kFrameDetailsAtReturnIndex]) {
1818 return this.details_[return_value_offset];
1819 }
1820 };
1821
1822
1823 FrameDetails.prototype.scopeCount = function() {
1824 if (IS_UNDEFINED(this.scopeCount_)) {
1825 this.scopeCount_ = %GetScopeCount(this.break_id_, this.frameId());
1826 }
1827 return this.scopeCount_;
1828 };
1829
1830
1831 FrameDetails.prototype.stepInPositionsImpl = function() {
1832 return %GetStepInPositions(this.break_id_, this.frameId());
1833 };
1834
1835
1836 /**
1837 * Mirror object for stack frames.
1838 * @param {number} break_id The break id in the VM for which this frame is
1839 valid
1840 * @param {number} index The frame index (top frame is index 0)
1841 * @constructor
1842 * @extends Mirror
1843 */
1844 function FrameMirror(break_id, index) {
1845 %_CallFunction(this, FRAME_TYPE, Mirror);
1846 this.break_id_ = break_id;
1847 this.index_ = index;
1848 this.details_ = new FrameDetails(break_id, index);
1849 }
1850 inherits(FrameMirror, Mirror);
1851
1852
1853 FrameMirror.prototype.details = function() {
1854 return this.details_;
1855 };
1856
1857
1858 FrameMirror.prototype.index = function() {
1859 return this.index_;
1860 };
1861
1862
1863 FrameMirror.prototype.func = function() {
1864 if (this.func_) {
1865 return this.func_;
1866 }
1867
1868 // Get the function for this frame from the VM.
1869 var f = this.details_.func();
1870
1871 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1872 // value returned from the VM might be a string if the function for the
1873 // frame is unresolved.
1874 if (IS_FUNCTION(f)) {
1875 return this.func_ = MakeMirror(f);
1876 } else {
1877 return new UnresolvedFunctionMirror(f);
1878 }
1879 };
1880
1881
1882 FrameMirror.prototype.receiver = function() {
1883 return MakeMirror(this.details_.receiver());
1884 };
1885
1886
1887 FrameMirror.prototype.isConstructCall = function() {
1888 return this.details_.isConstructCall();
1889 };
1890
1891
1892 FrameMirror.prototype.isAtReturn = function() {
1893 return this.details_.isAtReturn();
1894 };
1895
1896
1897 FrameMirror.prototype.isDebuggerFrame = function() {
1898 return this.details_.isDebuggerFrame();
1899 };
1900
1901
1902 FrameMirror.prototype.isOptimizedFrame = function() {
1903 return this.details_.isOptimizedFrame();
1904 };
1905
1906
1907 FrameMirror.prototype.isInlinedFrame = function() {
1908 return this.details_.isInlinedFrame();
1909 };
1910
1911
1912 FrameMirror.prototype.inlinedFrameIndex = function() {
1913 return this.details_.inlinedFrameIndex();
1914 };
1915
1916
1917 FrameMirror.prototype.argumentCount = function() {
1918 return this.details_.argumentCount();
1919 };
1920
1921
1922 FrameMirror.prototype.argumentName = function(index) {
1923 return this.details_.argumentName(index);
1924 };
1925
1926
1927 FrameMirror.prototype.argumentValue = function(index) {
1928 return MakeMirror(this.details_.argumentValue(index));
1929 };
1930
1931
1932 FrameMirror.prototype.localCount = function() {
1933 return this.details_.localCount();
1934 };
1935
1936
1937 FrameMirror.prototype.localName = function(index) {
1938 return this.details_.localName(index);
1939 };
1940
1941
1942 FrameMirror.prototype.localValue = function(index) {
1943 return MakeMirror(this.details_.localValue(index));
1944 };
1945
1946
1947 FrameMirror.prototype.returnValue = function() {
1948 return MakeMirror(this.details_.returnValue());
1949 };
1950
1951
1952 FrameMirror.prototype.sourcePosition = function() {
1953 return this.details_.sourcePosition();
1954 };
1955
1956
1957 FrameMirror.prototype.sourceLocation = function() {
1958 var func = this.func();
1959 if (func.resolved()) {
1960 var script = func.script();
1961 if (script) {
1962 return script.locationFromPosition(this.sourcePosition(), true);
1963 }
1964 }
1965 };
1966
1967
1968 FrameMirror.prototype.sourceLine = function() {
1969 var location = this.sourceLocation();
1970 if (location) {
1971 return location.line;
1972 }
1973 };
1974
1975
1976 FrameMirror.prototype.sourceColumn = function() {
1977 var location = this.sourceLocation();
1978 if (location) {
1979 return location.column;
1980 }
1981 };
1982
1983
1984 FrameMirror.prototype.sourceLineText = function() {
1985 var location = this.sourceLocation();
1986 if (location) {
1987 return location.sourceText();
1988 }
1989 };
1990
1991
1992 FrameMirror.prototype.scopeCount = function() {
1993 return this.details_.scopeCount();
1994 };
1995
1996
1997 FrameMirror.prototype.scope = function(index) {
1998 return new ScopeMirror(this, UNDEFINED, index);
1999 };
2000
2001
2002 FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) {
2003 var scopeDetails = %GetAllScopesDetails(this.break_id_,
2004 this.details_.frameId(),
2005 this.details_.inlinedFrameIndex(),
2006 !!opt_ignore_nested_scopes);
2007 var result = [];
2008 for (var i = 0; i < scopeDetails.length; ++i) {
2009 result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
2010 }
2011 return result;
2012 };
2013
2014
2015 FrameMirror.prototype.stepInPositions = function() {
2016 var script = this.func().script();
2017 var funcOffset = this.func().sourcePosition_();
2018
2019 var stepInRaw = this.details_.stepInPositionsImpl();
2020 var result = [];
2021 if (stepInRaw) {
2022 for (var i = 0; i < stepInRaw.length; i++) {
2023 var posStruct = {};
2024 var offset = script.locationFromPosition(funcOffset + stepInRaw[i],
2025 true);
2026 serializeLocationFields(offset, posStruct);
2027 var item = {
2028 position: posStruct
2029 };
2030 result.push(item);
2031 }
2032 }
2033
2034 return result;
2035 };
2036
2037
2038 FrameMirror.prototype.evaluate = function(source, disable_break,
2039 opt_context_object) {
2040 return MakeMirror(%DebugEvaluate(this.break_id_,
2041 this.details_.frameId(),
2042 this.details_.inlinedFrameIndex(),
2043 source,
2044 Boolean(disable_break),
2045 opt_context_object));
2046 };
2047
2048
2049 FrameMirror.prototype.invocationText = function() {
2050 // Format frame invoaction (receiver, function and arguments).
2051 var result = '';
2052 var func = this.func();
2053 var receiver = this.receiver();
2054 if (this.isConstructCall()) {
2055 // For constructor frames display new followed by the function name.
2056 result += 'new ';
2057 result += func.name() ? func.name() : '[anonymous]';
2058 } else if (this.isDebuggerFrame()) {
2059 result += '[debugger]';
2060 } else {
2061 // If the receiver has a className which is 'global' don't display it.
2062 var display_receiver =
2063 !receiver.className || (receiver.className() != 'global');
2064 if (display_receiver) {
2065 result += receiver.toText();
2066 }
2067 // Try to find the function as a property in the receiver. Include the
2068 // prototype chain in the lookup.
2069 var property = GetUndefinedMirror();
2070 if (receiver.isObject()) {
2071 for (var r = receiver;
2072 !r.isNull() && property.isUndefined();
2073 r = r.protoObject()) {
2074 property = r.lookupProperty(func);
2075 }
2076 }
2077 if (!property.isUndefined()) {
2078 // The function invoked was found on the receiver. Use the property name
2079 // for the backtrace.
2080 if (!property.isIndexed()) {
2081 if (display_receiver) {
2082 result += '.';
2083 }
2084 result += property.name();
2085 } else {
2086 result += '[';
2087 result += property.name();
2088 result += ']';
2089 }
2090 // Also known as - if the name in the function doesn't match the name
2091 // under which it was looked up.
2092 if (func.name() && func.name() != property.name()) {
2093 result += '(aka ' + func.name() + ')';
2094 }
2095 } else {
2096 // The function invoked was not found on the receiver. Use the function
2097 // name if available for the backtrace.
2098 if (display_receiver) {
2099 result += '.';
2100 }
2101 result += func.name() ? func.name() : '[anonymous]';
2102 }
2103 }
2104
2105 // Render arguments for normal frames.
2106 if (!this.isDebuggerFrame()) {
2107 result += '(';
2108 for (var i = 0; i < this.argumentCount(); i++) {
2109 if (i != 0) result += ', ';
2110 if (this.argumentName(i)) {
2111 result += this.argumentName(i);
2112 result += '=';
2113 }
2114 result += this.argumentValue(i).toText();
2115 }
2116 result += ')';
2117 }
2118
2119 if (this.isAtReturn()) {
2120 result += ' returning ';
2121 result += this.returnValue().toText();
2122 }
2123
2124 return result;
2125 };
2126
2127
2128 FrameMirror.prototype.sourceAndPositionText = function() {
2129 // Format source and position.
2130 var result = '';
2131 var func = this.func();
2132 if (func.resolved()) {
2133 var script = func.script();
2134 if (script) {
2135 if (script.name()) {
2136 result += script.name();
2137 } else {
2138 result += '[unnamed]';
2139 }
2140 if (!this.isDebuggerFrame()) {
2141 var location = this.sourceLocation();
2142 result += ' line ';
2143 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
2144 result += ' column ';
2145 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
2146 if (!IS_UNDEFINED(this.sourcePosition())) {
2147 result += ' (position ' + (this.sourcePosition() + 1) + ')';
2148 }
2149 }
2150 } else {
2151 result += '[no source]';
2152 }
2153 } else {
2154 result += '[unresolved]';
2155 }
2156
2157 return result;
2158 };
2159
2160
2161 FrameMirror.prototype.localsText = function() {
2162 // Format local variables.
2163 var result = '';
2164 var locals_count = this.localCount();
2165 if (locals_count > 0) {
2166 for (var i = 0; i < locals_count; ++i) {
2167 result += ' var ';
2168 result += this.localName(i);
2169 result += ' = ';
2170 result += this.localValue(i).toText();
2171 if (i < locals_count - 1) result += '\n';
2172 }
2173 }
2174
2175 return result;
2176 };
2177
2178
2179 FrameMirror.prototype.restart = function() {
2180 var result = %LiveEditRestartFrame(this.break_id_, this.index_);
2181 if (IS_UNDEFINED(result)) {
2182 result = "Failed to find requested frame";
2183 }
2184 return result;
2185 };
2186
2187
2188 FrameMirror.prototype.toText = function(opt_locals) {
2189 var result = '';
2190 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
2191 result += ' ';
2192 result += this.invocationText();
2193 result += ' ';
2194 result += this.sourceAndPositionText();
2195 if (opt_locals) {
2196 result += '\n';
2197 result += this.localsText();
2198 }
2199 return result;
2200 };
2201
2202
2203 var kScopeDetailsTypeIndex = 0;
2204 var kScopeDetailsObjectIndex = 1;
2205
2206 function ScopeDetails(frame, fun, index, opt_details) {
2207 if (frame) {
2208 this.break_id_ = frame.break_id_;
2209 this.details_ = opt_details ||
2210 %GetScopeDetails(frame.break_id_,
2211 frame.details_.frameId(),
2212 frame.details_.inlinedFrameIndex(),
2213 index);
2214 this.frame_id_ = frame.details_.frameId();
2215 this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
2216 } else {
2217 this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index);
2218 this.fun_value_ = fun.value();
2219 this.break_id_ = undefined;
2220 }
2221 this.index_ = index;
2222 }
2223
2224
2225 ScopeDetails.prototype.type = function() {
2226 if (!IS_UNDEFINED(this.break_id_)) {
2227 %CheckExecutionState(this.break_id_);
2228 }
2229 return this.details_[kScopeDetailsTypeIndex];
2230 };
2231
2232
2233 ScopeDetails.prototype.object = function() {
2234 if (!IS_UNDEFINED(this.break_id_)) {
2235 %CheckExecutionState(this.break_id_);
2236 }
2237 return this.details_[kScopeDetailsObjectIndex];
2238 };
2239
2240
2241 ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
2242 var raw_res;
2243 if (!IS_UNDEFINED(this.break_id_)) {
2244 %CheckExecutionState(this.break_id_);
2245 raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_,
2246 this.inlined_frame_id_, this.index_, name, new_value);
2247 } else {
2248 raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_,
2249 name, new_value);
2250 }
2251 if (!raw_res) {
2252 throw new Error("Failed to set variable value");
2253 }
2254 };
2255
2256
2257 /**
2258 * Mirror object for scope of frame or function. Either frame or function must
2259 * be specified.
2260 * @param {FrameMirror} frame The frame this scope is a part of
2261 * @param {FunctionMirror} function The function this scope is a part of
2262 * @param {number} index The scope index in the frame
2263 * @param {Array=} opt_details Raw scope details data
2264 * @constructor
2265 * @extends Mirror
2266 */
2267 function ScopeMirror(frame, function, index, opt_details) {
2268 %_CallFunction(this, SCOPE_TYPE, Mirror);
2269 if (frame) {
2270 this.frame_index_ = frame.index_;
2271 } else {
2272 this.frame_index_ = undefined;
2273 }
2274 this.scope_index_ = index;
2275 this.details_ = new ScopeDetails(frame, function, index, opt_details);
2276 }
2277 inherits(ScopeMirror, Mirror);
2278
2279
2280 ScopeMirror.prototype.details = function() {
2281 return this.details_;
2282 };
2283
2284
2285 ScopeMirror.prototype.frameIndex = function() {
2286 return this.frame_index_;
2287 };
2288
2289
2290 ScopeMirror.prototype.scopeIndex = function() {
2291 return this.scope_index_;
2292 };
2293
2294
2295 ScopeMirror.prototype.scopeType = function() {
2296 return this.details_.type();
2297 };
2298
2299
2300 ScopeMirror.prototype.scopeObject = function() {
2301 // For local, closure and script scopes create a transient mirror
2302 // as these objects are created on the fly materializing the local
2303 // or closure scopes and therefore will not preserve identity.
2304 var transient = this.scopeType() == ScopeType.Local ||
2305 this.scopeType() == ScopeType.Closure ||
2306 this.scopeType() == ScopeType.Script;
2307 return MakeMirror(this.details_.object(), transient);
2308 };
2309
2310
2311 ScopeMirror.prototype.setVariableValue = function(name, new_value) {
2312 this.details_.setVariableValueImpl(name, new_value);
2313 };
2314
2315
2316 /**
2317 * Mirror object for script source.
2318 * @param {Script} script The script object
2319 * @constructor
2320 * @extends Mirror
2321 */
2322 function ScriptMirror(script) {
2323 %_CallFunction(this, SCRIPT_TYPE, Mirror);
2324 this.script_ = script;
2325 this.context_ = new ContextMirror(script.context_data);
2326 this.allocateHandle_();
2327 }
2328 inherits(ScriptMirror, Mirror);
2329
2330
2331 ScriptMirror.prototype.value = function() {
2332 return this.script_;
2333 };
2334
2335
2336 ScriptMirror.prototype.name = function() {
2337 return this.script_.name || this.script_.nameOrSourceURL();
2338 };
2339
2340
2341 ScriptMirror.prototype.id = function() {
2342 return this.script_.id;
2343 };
2344
2345
2346 ScriptMirror.prototype.source = function() {
2347 return this.script_.source;
2348 };
2349
2350
2351 ScriptMirror.prototype.setSource = function(source) {
2352 %DebugSetScriptSource(this.script_, source);
2353 };
2354
2355
2356 ScriptMirror.prototype.lineOffset = function() {
2357 return this.script_.line_offset;
2358 };
2359
2360
2361 ScriptMirror.prototype.columnOffset = function() {
2362 return this.script_.column_offset;
2363 };
2364
2365
2366 ScriptMirror.prototype.data = function() {
2367 return this.script_.data;
2368 };
2369
2370
2371 ScriptMirror.prototype.scriptType = function() {
2372 return this.script_.type;
2373 };
2374
2375
2376 ScriptMirror.prototype.compilationType = function() {
2377 return this.script_.compilation_type;
2378 };
2379
2380
2381 ScriptMirror.prototype.lineCount = function() {
2382 return this.script_.lineCount();
2383 };
2384
2385
2386 ScriptMirror.prototype.locationFromPosition = function(
2387 position, include_resource_offset) {
2388 return this.script_.locationFromPosition(position, include_resource_offset);
2389 };
2390
2391
2392 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
2393 return this.script_.sourceSlice(opt_from_line, opt_to_line);
2394 };
2395
2396
2397 ScriptMirror.prototype.context = function() {
2398 return this.context_;
2399 };
2400
2401
2402 ScriptMirror.prototype.evalFromScript = function() {
2403 return MakeMirror(this.script_.eval_from_script);
2404 };
2405
2406
2407 ScriptMirror.prototype.evalFromFunctionName = function() {
2408 return MakeMirror(this.script_.eval_from_function_name);
2409 };
2410
2411
2412 ScriptMirror.prototype.evalFromLocation = function() {
2413 var eval_from_script = this.evalFromScript();
2414 if (!eval_from_script.isUndefined()) {
2415 var position = this.script_.eval_from_script_position;
2416 return eval_from_script.locationFromPosition(position, true);
2417 }
2418 };
2419
2420
2421 ScriptMirror.prototype.toText = function() {
2422 var result = '';
2423 result += this.name();
2424 result += ' (lines: ';
2425 if (this.lineOffset() > 0) {
2426 result += this.lineOffset();
2427 result += '-';
2428 result += this.lineOffset() + this.lineCount() - 1;
2429 } else {
2430 result += this.lineCount();
2431 }
2432 result += ')';
2433 return result;
2434 };
2435
2436
2437 /**
2438 * Mirror object for context.
2439 * @param {Object} data The context data
2440 * @constructor
2441 * @extends Mirror
2442 */
2443 function ContextMirror(data) {
2444 %_CallFunction(this, CONTEXT_TYPE, Mirror);
2445 this.data_ = data;
2446 this.allocateHandle_();
2447 }
2448 inherits(ContextMirror, Mirror);
2449
2450
2451 ContextMirror.prototype.data = function() {
2452 return this.data_;
2453 };
2454
2455
2456 /**
2457 * Returns a mirror serializer
2458 *
2459 * @param {boolean} details Set to true to include details
2460 * @param {Object} options Options comtrolling the serialization
2461 * The following options can be set:
2462 * includeSource: include ths full source of scripts
2463 * @returns {MirrorSerializer} mirror serializer
2464 */
2465 function MakeMirrorSerializer(details, options) {
2466 return new JSONProtocolSerializer(details, options);
2467 }
2468
2469
2470 /**
2471 * Object for serializing a mirror objects and its direct references.
2472 * @param {boolean} details Indicates whether to include details for the mirror
2473 * serialized
2474 * @constructor
2475 */
2476 function JSONProtocolSerializer(details, options) {
2477 this.details_ = details;
2478 this.options_ = options;
2479 this.mirrors_ = [ ];
2480 }
2481
2482
2483 /**
2484 * Returns a serialization of an object reference. The referenced object are
2485 * added to the serialization state.
2486 *
2487 * @param {Mirror} mirror The mirror to serialize
2488 * @returns {String} JSON serialization
2489 */
2490 JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
2491 return this.serialize_(mirror, true, true);
2492 };
2493
2494
2495 /**
2496 * Returns a serialization of an object value. The referenced objects are
2497 * added to the serialization state.
2498 *
2499 * @param {Mirror} mirror The mirror to serialize
2500 * @returns {String} JSON serialization
2501 */
2502 JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
2503 var json = this.serialize_(mirror, false, true);
2504 return json;
2505 };
2506
2507
2508 /**
2509 * Returns a serialization of all the objects referenced.
2510 *
2511 * @param {Mirror} mirror The mirror to serialize.
2512 * @returns {Array.<Object>} Array of the referenced objects converted to
2513 * protcol objects.
2514 */
2515 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
2516 // Collect the protocol representation of the referenced objects in an array.
2517 var content = [];
2518
2519 // Get the number of referenced objects.
2520 var count = this.mirrors_.length;
2521
2522 for (var i = 0; i < count; i++) {
2523 content.push(this.serialize_(this.mirrors_[i], false, false));
2524 }
2525
2526 return content;
2527 };
2528
2529
2530 JSONProtocolSerializer.prototype.includeSource_ = function() {
2531 return this.options_ && this.options_.includeSource;
2532 };
2533
2534
2535 JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2536 return this.options_ && this.options_.inlineRefs;
2537 };
2538
2539
2540 JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2541 if (IS_UNDEFINED(this.options_) ||
2542 IS_UNDEFINED(this.options_.maxStringLength)) {
2543 return kMaxProtocolStringLength;
2544 }
2545 return this.options_.maxStringLength;
2546 };
2547
2548
2549 JSONProtocolSerializer.prototype.add_ = function(mirror) {
2550 // If this mirror is already in the list just return.
2551 for (var i = 0; i < this.mirrors_.length; i++) {
2552 if (this.mirrors_[i] === mirror) {
2553 return;
2554 }
2555 }
2556
2557 // Add the mirror to the list of mirrors to be serialized.
2558 this.mirrors_.push(mirror);
2559 };
2560
2561
2562 /**
2563 * Formats mirror object to protocol reference object with some data that can
2564 * be used to display the value in debugger.
2565 * @param {Mirror} mirror Mirror to serialize.
2566 * @return {Object} Protocol reference object.
2567 */
2568 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
2569 function(mirror) {
2570 var o = {};
2571 o.ref = mirror.handle();
2572 o.type = mirror.type();
2573 switch (mirror.type()) {
2574 case UNDEFINED_TYPE:
2575 case NULL_TYPE:
2576 case BOOLEAN_TYPE:
2577 case NUMBER_TYPE:
2578 o.value = mirror.value();
2579 break;
2580 case STRING_TYPE:
2581 o.value = mirror.getTruncatedValue(this.maxStringLength_());
2582 break;
2583 case SYMBOL_TYPE:
2584 o.description = mirror.description();
2585 break;
2586 case FUNCTION_TYPE:
2587 o.name = mirror.name();
2588 o.inferredName = mirror.inferredName();
2589 if (mirror.script()) {
2590 o.scriptId = mirror.script().id();
2591 }
2592 break;
2593 case ERROR_TYPE:
2594 case REGEXP_TYPE:
2595 o.value = mirror.toText();
2596 break;
2597 case OBJECT_TYPE:
2598 o.className = mirror.className();
2599 break;
2600 }
2601 return o;
2602 };
2603
2604
2605 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2606 details) {
2607 // If serializing a reference to a mirror just return the reference and add
2608 // the mirror to the referenced mirrors.
2609 if (reference &&
2610 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
2611 if (this.inlineRefs_() && mirror.isValue()) {
2612 return this.serializeReferenceWithDisplayData_(mirror);
2613 } else {
2614 this.add_(mirror);
2615 return {'ref' : mirror.handle()};
2616 }
2617 }
2618
2619 // Collect the JSON property/value pairs.
2620 var content = {};
2621
2622 // Add the mirror handle.
2623 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2624 content.handle = mirror.handle();
2625 }
2626
2627 // Always add the type.
2628 content.type = mirror.type();
2629
2630 switch (mirror.type()) {
2631 case UNDEFINED_TYPE:
2632 case NULL_TYPE:
2633 // Undefined and null are represented just by their type.
2634 break;
2635
2636 case BOOLEAN_TYPE:
2637 // Boolean values are simply represented by their value.
2638 content.value = mirror.value();
2639 break;
2640
2641 case NUMBER_TYPE:
2642 // Number values are simply represented by their value.
2643 content.value = NumberToJSON_(mirror.value());
2644 break;
2645
2646 case STRING_TYPE:
2647 // String values might have their value cropped to keep down size.
2648 if (this.maxStringLength_() != -1 &&
2649 mirror.length() > this.maxStringLength_()) {
2650 var str = mirror.getTruncatedValue(this.maxStringLength_());
2651 content.value = str;
2652 content.fromIndex = 0;
2653 content.toIndex = this.maxStringLength_();
2654 } else {
2655 content.value = mirror.value();
2656 }
2657 content.length = mirror.length();
2658 break;
2659
2660 case SYMBOL_TYPE:
2661 content.description = mirror.description();
2662 break;
2663
2664 case OBJECT_TYPE:
2665 case FUNCTION_TYPE:
2666 case ERROR_TYPE:
2667 case REGEXP_TYPE:
2668 case PROMISE_TYPE:
2669 case GENERATOR_TYPE:
2670 // Add object representation.
2671 this.serializeObject_(mirror, content, details);
2672 break;
2673
2674 case PROPERTY_TYPE:
2675 case INTERNAL_PROPERTY_TYPE:
2676 throw new Error('PropertyMirror cannot be serialized independently');
2677 break;
2678
2679 case FRAME_TYPE:
2680 // Add object representation.
2681 this.serializeFrame_(mirror, content);
2682 break;
2683
2684 case SCOPE_TYPE:
2685 // Add object representation.
2686 this.serializeScope_(mirror, content);
2687 break;
2688
2689 case SCRIPT_TYPE:
2690 // Script is represented by id, name and source attributes.
2691 if (mirror.name()) {
2692 content.name = mirror.name();
2693 }
2694 content.id = mirror.id();
2695 content.lineOffset = mirror.lineOffset();
2696 content.columnOffset = mirror.columnOffset();
2697 content.lineCount = mirror.lineCount();
2698 if (mirror.data()) {
2699 content.data = mirror.data();
2700 }
2701 if (this.includeSource_()) {
2702 content.source = mirror.source();
2703 } else {
2704 var sourceStart = mirror.source().substring(0, 80);
2705 content.sourceStart = sourceStart;
2706 }
2707 content.sourceLength = mirror.source().length;
2708 content.scriptType = mirror.scriptType();
2709 content.compilationType = mirror.compilationType();
2710 // For compilation type eval emit information on the script from which
2711 // eval was called if a script is present.
2712 if (mirror.compilationType() == 1 &&
2713 mirror.evalFromScript()) {
2714 content.evalFromScript =
2715 this.serializeReference(mirror.evalFromScript());
2716 var evalFromLocation = mirror.evalFromLocation();
2717 if (evalFromLocation) {
2718 content.evalFromLocation = { line: evalFromLocation.line,
2719 column: evalFromLocation.column };
2720 }
2721 if (mirror.evalFromFunctionName()) {
2722 content.evalFromFunctionName = mirror.evalFromFunctionName();
2723 }
2724 }
2725 if (mirror.context()) {
2726 content.context = this.serializeReference(mirror.context());
2727 }
2728 break;
2729
2730 case CONTEXT_TYPE:
2731 content.data = mirror.data();
2732 break;
2733 }
2734
2735 // Always add the text representation.
2736 content.text = mirror.toText();
2737
2738 // Create and return the JSON string.
2739 return content;
2740 };
2741
2742
2743 /**
2744 * Serialize object information to the following JSON format.
2745 *
2746 * {"className":"<class name>",
2747 * "constructorFunction":{"ref":<number>},
2748 * "protoObject":{"ref":<number>},
2749 * "prototypeObject":{"ref":<number>},
2750 * "namedInterceptor":<boolean>,
2751 * "indexedInterceptor":<boolean>,
2752 * "properties":[<properties>],
2753 * "internalProperties":[<internal properties>]}
2754 */
2755 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2756 details) {
2757 // Add general object properties.
2758 content.className = mirror.className();
2759 content.constructorFunction =
2760 this.serializeReference(mirror.constructorFunction());
2761 content.protoObject = this.serializeReference(mirror.protoObject());
2762 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2763
2764 // Add flags to indicate whether there are interceptors.
2765 if (mirror.hasNamedInterceptor()) {
2766 content.namedInterceptor = true;
2767 }
2768 if (mirror.hasIndexedInterceptor()) {
2769 content.indexedInterceptor = true;
2770 }
2771
2772 if (mirror.isFunction()) {
2773 // Add function specific properties.
2774 content.name = mirror.name();
2775 if (!IS_UNDEFINED(mirror.inferredName())) {
2776 content.inferredName = mirror.inferredName();
2777 }
2778 content.resolved = mirror.resolved();
2779 if (mirror.resolved()) {
2780 content.source = mirror.source();
2781 }
2782 if (mirror.script()) {
2783 content.script = this.serializeReference(mirror.script());
2784 content.scriptId = mirror.script().id();
2785
2786 serializeLocationFields(mirror.sourceLocation(), content);
2787 }
2788
2789 content.scopes = [];
2790 for (var i = 0; i < mirror.scopeCount(); i++) {
2791 var scope = mirror.scope(i);
2792 content.scopes.push({
2793 type: scope.scopeType(),
2794 index: i
2795 });
2796 }
2797 }
2798
2799 if (mirror.isGenerator()) {
2800 // Add generator specific properties.
2801
2802 // Either 'running', 'closed', or 'suspended'.
2803 content.status = mirror.status();
2804
2805 content.func = this.serializeReference(mirror.func())
2806 content.receiver = this.serializeReference(mirror.receiver())
2807
2808 // If the generator is suspended, the content add line/column properties.
2809 serializeLocationFields(mirror.sourceLocation(), content);
2810
2811 // TODO(wingo): Also serialize a reference to the context (scope chain).
2812 }
2813
2814 if (mirror.isDate()) {
2815 // Add date specific properties.
2816 content.value = mirror.value();
2817 }
2818
2819 if (mirror.isPromise()) {
2820 // Add promise specific properties.
2821 content.status = mirror.status();
2822 content.promiseValue = this.serializeReference(mirror.promiseValue());
2823 }
2824
2825 // Add actual properties - named properties followed by indexed properties.
2826 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2827 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2828 var p = new Array(propertyNames.length + propertyIndexes.length);
2829 for (var i = 0; i < propertyNames.length; i++) {
2830 var propertyMirror = mirror.property(propertyNames[i]);
2831 p[i] = this.serializeProperty_(propertyMirror);
2832 if (details) {
2833 this.add_(propertyMirror.value());
2834 }
2835 }
2836 for (var i = 0; i < propertyIndexes.length; i++) {
2837 var propertyMirror = mirror.property(propertyIndexes[i]);
2838 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2839 if (details) {
2840 this.add_(propertyMirror.value());
2841 }
2842 }
2843 content.properties = p;
2844
2845 var internalProperties = mirror.internalProperties();
2846 if (internalProperties.length > 0) {
2847 var ip = [];
2848 for (var i = 0; i < internalProperties.length; i++) {
2849 ip.push(this.serializeInternalProperty_(internalProperties[i]));
2850 }
2851 content.internalProperties = ip;
2852 }
2853 };
2854
2855
2856 /**
2857 * Serialize location information to the following JSON format:
2858 *
2859 * "position":"<position>",
2860 * "line":"<line>",
2861 * "column":"<column>",
2862 *
2863 * @param {SourceLocation} location The location to serialize, may be undefined.
2864 */
2865 function serializeLocationFields (location, content) {
2866 if (!location) {
2867 return;
2868 }
2869 content.position = location.position;
2870 var line = location.line;
2871 if (!IS_UNDEFINED(line)) {
2872 content.line = line;
2873 }
2874 var column = location.column;
2875 if (!IS_UNDEFINED(column)) {
2876 content.column = column;
2877 }
2878 }
2879
2880
2881 /**
2882 * Serialize property information to the following JSON format for building the
2883 * array of properties.
2884 *
2885 * {"name":"<property name>",
2886 * "attributes":<number>,
2887 * "propertyType":<number>,
2888 * "ref":<number>}
2889 *
2890 * If the attribute for the property is PropertyAttribute.None it is not added.
2891 * Here are a couple of examples.
2892 *
2893 * {"name":"hello","propertyType":0,"ref":1}
2894 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2895 *
2896 * @param {PropertyMirror} propertyMirror The property to serialize.
2897 * @returns {Object} Protocol object representing the property.
2898 */
2899 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2900 var result = {};
2901
2902 result.name = propertyMirror.name();
2903 var propertyValue = propertyMirror.value();
2904 if (this.inlineRefs_() && propertyValue.isValue()) {
2905 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2906 } else {
2907 if (propertyMirror.attributes() != PropertyAttribute.None) {
2908 result.attributes = propertyMirror.attributes();
2909 }
2910 result.propertyType = propertyMirror.propertyType();
2911 result.ref = propertyValue.handle();
2912 }
2913 return result;
2914 };
2915
2916
2917 /**
2918 * Serialize internal property information to the following JSON format for
2919 * building the array of properties.
2920 *
2921 * {"name":"<property name>",
2922 * "ref":<number>}
2923 *
2924 * {"name":"[[BoundThis]]","ref":117}
2925 *
2926 * @param {InternalPropertyMirror} propertyMirror The property to serialize.
2927 * @returns {Object} Protocol object representing the property.
2928 */
2929 JSONProtocolSerializer.prototype.serializeInternalProperty_ =
2930 function(propertyMirror) {
2931 var result = {};
2932
2933 result.name = propertyMirror.name();
2934 var propertyValue = propertyMirror.value();
2935 if (this.inlineRefs_() && propertyValue.isValue()) {
2936 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2937 } else {
2938 result.ref = propertyValue.handle();
2939 }
2940 return result;
2941 };
2942
2943
2944 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2945 content.index = mirror.index();
2946 content.receiver = this.serializeReference(mirror.receiver());
2947 var func = mirror.func();
2948 content.func = this.serializeReference(func);
2949 var script = func.script();
2950 if (script) {
2951 content.script = this.serializeReference(script);
2952 }
2953 content.constructCall = mirror.isConstructCall();
2954 content.atReturn = mirror.isAtReturn();
2955 if (mirror.isAtReturn()) {
2956 content.returnValue = this.serializeReference(mirror.returnValue());
2957 }
2958 content.debuggerFrame = mirror.isDebuggerFrame();
2959 var x = new Array(mirror.argumentCount());
2960 for (var i = 0; i < mirror.argumentCount(); i++) {
2961 var arg = {};
2962 var argument_name = mirror.argumentName(i);
2963 if (argument_name) {
2964 arg.name = argument_name;
2965 }
2966 arg.value = this.serializeReference(mirror.argumentValue(i));
2967 x[i] = arg;
2968 }
2969 content.arguments = x;
2970 var x = new Array(mirror.localCount());
2971 for (var i = 0; i < mirror.localCount(); i++) {
2972 var local = {};
2973 local.name = mirror.localName(i);
2974 local.value = this.serializeReference(mirror.localValue(i));
2975 x[i] = local;
2976 }
2977 content.locals = x;
2978 serializeLocationFields(mirror.sourceLocation(), content);
2979 var source_line_text = mirror.sourceLineText();
2980 if (!IS_UNDEFINED(source_line_text)) {
2981 content.sourceLineText = source_line_text;
2982 }
2983
2984 content.scopes = [];
2985 for (var i = 0; i < mirror.scopeCount(); i++) {
2986 var scope = mirror.scope(i);
2987 content.scopes.push({
2988 type: scope.scopeType(),
2989 index: i
2990 });
2991 }
2992 };
2993
2994
2995 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2996 content.index = mirror.scopeIndex();
2997 content.frameIndex = mirror.frameIndex();
2998 content.type = mirror.scopeType();
2999 content.object = this.inlineRefs_() ?
3000 this.serializeValue(mirror.scopeObject()) :
3001 this.serializeReference(mirror.scopeObject());
3002 };
3003
3004
3005 /**
3006 * Convert a number to a protocol value. For all finite numbers the number
3007 * itself is returned. For non finite numbers NaN, Infinite and
3008 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
3009 * (not including the quotes) is returned.
3010 *
3011 * @param {number} value The number value to convert to a protocol value.
3012 * @returns {number|string} Protocol value.
3013 */
3014 function NumberToJSON_(value) {
3015 if (isNaN(value)) {
3016 return 'NaN';
3017 }
3018 if (!NUMBER_IS_FINITE(value)) {
3019 if (value > 0) {
3020 return 'Infinity';
3021 } else {
3022 return '-Infinity';
3023 }
3024 }
3025 return value;
3026 }
OLDNEW
« no previous file with comments | « src/mips64/macro-assembler-mips64.cc ('k') | src/objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698