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