The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / mirror-debugger.js @ f230a1cf

History | View | Annotate | Download (69.7 KB)

1
// Copyright 2006-2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
// Handle id counters.
29
var next_handle_ = 0;
30
var next_transient_handle_ = -1;
31

    
32
// Mirror cache.
33
var mirror_cache_ = [];
34

    
35

    
36
/**
37
 * Clear the mirror handle cache.
38
 */
39
function ClearMirrorCache() {
40
  next_handle_ = 0;
41
  mirror_cache_ = [];
42
}
43

    
44

    
45
/**
46
 * Returns the mirror for a specified value or object.
47
 *
48
 * @param {value or Object} value the value or object to retreive the mirror for
49
 * @param {boolean} transient indicate whether this object is transient and
50
 *    should not be added to the mirror cache. The default is not transient.
51
 * @returns {Mirror} the mirror reflects the passed value or object
52
 */
53
function MakeMirror(value, opt_transient) {
54
  var mirror;
55

    
56
  // Look for non transient mirrors in the mirror cache.
57
  if (!opt_transient) {
58
    for (id in mirror_cache_) {
59
      mirror = mirror_cache_[id];
60
      if (mirror.value() === value) {
61
        return mirror;
62
      }
63
      // Special check for NaN as NaN == NaN is false.
64
      if (mirror.isNumber() && isNaN(mirror.value()) &&
65
          typeof value == 'number' && isNaN(value)) {
66
        return mirror;
67
      }
68
    }
69
  }
70

    
71
  if (IS_UNDEFINED(value)) {
72
    mirror = new UndefinedMirror();
73
  } else if (IS_NULL(value)) {
74
    mirror = new NullMirror();
75
  } else if (IS_BOOLEAN(value)) {
76
    mirror = new BooleanMirror(value);
77
  } else if (IS_NUMBER(value)) {
78
    mirror = new NumberMirror(value);
79
  } else if (IS_STRING(value)) {
80
    mirror = new StringMirror(value);
81
  } else if (IS_ARRAY(value)) {
82
    mirror = new ArrayMirror(value);
83
  } else if (IS_DATE(value)) {
84
    mirror = new DateMirror(value);
85
  } else if (IS_FUNCTION(value)) {
86
    mirror = new FunctionMirror(value);
87
  } else if (IS_REGEXP(value)) {
88
    mirror = new RegExpMirror(value);
89
  } else if (IS_ERROR(value)) {
90
    mirror = new ErrorMirror(value);
91
  } else if (IS_SCRIPT(value)) {
92
    mirror = new ScriptMirror(value);
93
  } else {
94
    mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
95
  }
96

    
97
  mirror_cache_[mirror.handle()] = mirror;
98
  return mirror;
99
}
100

    
101

    
102
/**
103
 * Returns the mirror for a specified mirror handle.
104
 *
105
 * @param {number} handle the handle to find the mirror for
106
 * @returns {Mirror or undefiend} the mirror with the requested handle or
107
 *     undefined if no mirror with the requested handle was found
108
 */
109
function LookupMirror(handle) {
110
  return mirror_cache_[handle];
111
}
112

    
113

    
114
/**
115
 * Returns the mirror for the undefined value.
116
 *
117
 * @returns {Mirror} the mirror reflects the undefined value
118
 */
119
function GetUndefinedMirror() {
120
  return MakeMirror(UNDEFINED);
121
}
122

    
123

    
124
/**
125
 * Inherit the prototype methods from one constructor into another.
126
 *
127
 * The Function.prototype.inherits from lang.js rewritten as a standalone
128
 * function (not on Function.prototype). NOTE: If this file is to be loaded
129
 * during bootstrapping this function needs to be revritten using some native
130
 * functions as prototype setup using normal JavaScript does not work as
131
 * expected during bootstrapping (see mirror.js in r114903).
132
 *
133
 * @param {function} ctor Constructor function which needs to inherit the
134
 *     prototype
135
 * @param {function} superCtor Constructor function to inherit prototype from
136
 */
137
function inherits(ctor, superCtor) {
138
  var tempCtor = function(){};
139
  tempCtor.prototype = superCtor.prototype;
140
  ctor.super_ = superCtor.prototype;
141
  ctor.prototype = new tempCtor();
142
  ctor.prototype.constructor = ctor;
143
}
144

    
145

    
146
// Type names of the different mirrors.
147
var UNDEFINED_TYPE = 'undefined';
148
var NULL_TYPE = 'null';
149
var BOOLEAN_TYPE = 'boolean';
150
var NUMBER_TYPE = 'number';
151
var STRING_TYPE = 'string';
152
var OBJECT_TYPE = 'object';
153
var FUNCTION_TYPE = 'function';
154
var REGEXP_TYPE = 'regexp';
155
var ERROR_TYPE = 'error';
156
var PROPERTY_TYPE = 'property';
157
var INTERNAL_PROPERTY_TYPE = 'internalProperty';
158
var FRAME_TYPE = 'frame';
159
var SCRIPT_TYPE = 'script';
160
var CONTEXT_TYPE = 'context';
161
var SCOPE_TYPE = 'scope';
162

    
163
// Maximum length when sending strings through the JSON protocol.
164
var kMaxProtocolStringLength = 80;
165

    
166
// Different kind of properties.
167
var PropertyKind = {};
168
PropertyKind.Named   = 1;
169
PropertyKind.Indexed = 2;
170

    
171

    
172
// A copy of the PropertyType enum from global.h
173
var PropertyType = {};
174
PropertyType.Normal                  = 0;
175
PropertyType.Field                   = 1;
176
PropertyType.Constant                = 2;
177
PropertyType.Callbacks               = 3;
178
PropertyType.Handler                 = 4;
179
PropertyType.Interceptor             = 5;
180
PropertyType.Transition              = 6;
181
PropertyType.Nonexistent             = 7;
182

    
183

    
184
// Different attributes for a property.
185
var PropertyAttribute = {};
186
PropertyAttribute.None       = NONE;
187
PropertyAttribute.ReadOnly   = READ_ONLY;
188
PropertyAttribute.DontEnum   = DONT_ENUM;
189
PropertyAttribute.DontDelete = DONT_DELETE;
190

    
191

    
192
// A copy of the scope types from runtime.cc.
193
var ScopeType = { Global: 0,
194
                  Local: 1,
195
                  With: 2,
196
                  Closure: 3,
197
                  Catch: 4,
198
                  Block: 5 };
199

    
200

    
201
// Mirror hierarchy:
202
//   - Mirror
203
//     - ValueMirror
204
//       - UndefinedMirror
205
//       - NullMirror
206
//       - NumberMirror
207
//       - StringMirror
208
//       - ObjectMirror
209
//         - FunctionMirror
210
//           - UnresolvedFunctionMirror
211
//         - ArrayMirror
212
//         - DateMirror
213
//         - RegExpMirror
214
//         - ErrorMirror
215
//     - PropertyMirror
216
//     - InternalPropertyMirror
217
//     - FrameMirror
218
//     - ScriptMirror
219

    
220

    
221
/**
222
 * Base class for all mirror objects.
223
 * @param {string} type The type of the mirror
224
 * @constructor
225
 */
226
function Mirror(type) {
227
  this.type_ = type;
228
}
229

    
230

    
231
Mirror.prototype.type = function() {
232
  return this.type_;
233
};
234

    
235

    
236
/**
237
 * Check whether the mirror reflects a value.
238
 * @returns {boolean} True if the mirror reflects a value.
239
 */
240
Mirror.prototype.isValue = function() {
241
  return this instanceof ValueMirror;
242
};
243

    
244

    
245
/**
246
 * Check whether the mirror reflects the undefined value.
247
 * @returns {boolean} True if the mirror reflects the undefined value.
248
 */
249
Mirror.prototype.isUndefined = function() {
250
  return this instanceof UndefinedMirror;
251
};
252

    
253

    
254
/**
255
 * Check whether the mirror reflects the null value.
256
 * @returns {boolean} True if the mirror reflects the null value
257
 */
258
Mirror.prototype.isNull = function() {
259
  return this instanceof NullMirror;
260
};
261

    
262

    
263
/**
264
 * Check whether the mirror reflects a boolean value.
265
 * @returns {boolean} True if the mirror reflects a boolean value
266
 */
267
Mirror.prototype.isBoolean = function() {
268
  return this instanceof BooleanMirror;
269
};
270

    
271

    
272
/**
273
 * Check whether the mirror reflects a number value.
274
 * @returns {boolean} True if the mirror reflects a number value
275
 */
276
Mirror.prototype.isNumber = function() {
277
  return this instanceof NumberMirror;
278
};
279

    
280

    
281
/**
282
 * Check whether the mirror reflects a string value.
283
 * @returns {boolean} True if the mirror reflects a string value
284
 */
285
Mirror.prototype.isString = function() {
286
  return this instanceof StringMirror;
287
};
288

    
289

    
290
/**
291
 * Check whether the mirror reflects an object.
292
 * @returns {boolean} True if the mirror reflects an object
293
 */
294
Mirror.prototype.isObject = function() {
295
  return this instanceof ObjectMirror;
296
};
297

    
298

    
299
/**
300
 * Check whether the mirror reflects a function.
301
 * @returns {boolean} True if the mirror reflects a function
302
 */
303
Mirror.prototype.isFunction = function() {
304
  return this instanceof FunctionMirror;
305
};
306

    
307

    
308
/**
309
 * Check whether the mirror reflects an unresolved function.
310
 * @returns {boolean} True if the mirror reflects an unresolved function
311
 */
312
Mirror.prototype.isUnresolvedFunction = function() {
313
  return this instanceof UnresolvedFunctionMirror;
314
};
315

    
316

    
317
/**
318
 * Check whether the mirror reflects an array.
319
 * @returns {boolean} True if the mirror reflects an array
320
 */
321
Mirror.prototype.isArray = function() {
322
  return this instanceof ArrayMirror;
323
};
324

    
325

    
326
/**
327
 * Check whether the mirror reflects a date.
328
 * @returns {boolean} True if the mirror reflects a date
329
 */
330
Mirror.prototype.isDate = function() {
331
  return this instanceof DateMirror;
332
};
333

    
334

    
335
/**
336
 * Check whether the mirror reflects a regular expression.
337
 * @returns {boolean} True if the mirror reflects a regular expression
338
 */
339
Mirror.prototype.isRegExp = function() {
340
  return this instanceof RegExpMirror;
341
};
342

    
343

    
344
/**
345
 * Check whether the mirror reflects an error.
346
 * @returns {boolean} True if the mirror reflects an error
347
 */
348
Mirror.prototype.isError = function() {
349
  return this instanceof ErrorMirror;
350
};
351

    
352

    
353
/**
354
 * Check whether the mirror reflects a property.
355
 * @returns {boolean} True if the mirror reflects a property
356
 */
357
Mirror.prototype.isProperty = function() {
358
  return this instanceof PropertyMirror;
359
};
360

    
361

    
362
/**
363
 * Check whether the mirror reflects an internal property.
364
 * @returns {boolean} True if the mirror reflects an internal property
365
 */
366
Mirror.prototype.isInternalProperty = function() {
367
  return this instanceof InternalPropertyMirror;
368
};
369

    
370

    
371
/**
372
 * Check whether the mirror reflects a stack frame.
373
 * @returns {boolean} True if the mirror reflects a stack frame
374
 */
375
Mirror.prototype.isFrame = function() {
376
  return this instanceof FrameMirror;
377
};
378

    
379

    
380
/**
381
 * Check whether the mirror reflects a script.
382
 * @returns {boolean} True if the mirror reflects a script
383
 */
384
Mirror.prototype.isScript = function() {
385
  return this instanceof ScriptMirror;
386
};
387

    
388

    
389
/**
390
 * Check whether the mirror reflects a context.
391
 * @returns {boolean} True if the mirror reflects a context
392
 */
393
Mirror.prototype.isContext = function() {
394
  return this instanceof ContextMirror;
395
};
396

    
397

    
398
/**
399
 * Check whether the mirror reflects a scope.
400
 * @returns {boolean} True if the mirror reflects a scope
401
 */
402
Mirror.prototype.isScope = function() {
403
  return this instanceof ScopeMirror;
404
};
405

    
406

    
407
/**
408
 * Allocate a handle id for this object.
409
 */
410
Mirror.prototype.allocateHandle_ = function() {
411
  this.handle_ = next_handle_++;
412
};
413

    
414

    
415
/**
416
 * Allocate a transient handle id for this object. Transient handles are
417
 * negative.
418
 */
419
Mirror.prototype.allocateTransientHandle_ = function() {
420
  this.handle_ = next_transient_handle_--;
421
};
422

    
423

    
424
Mirror.prototype.toText = function() {
425
  // Simpel to text which is used when on specialization in subclass.
426
  return "#<" + this.constructor.name + ">";
427
};
428

    
429

    
430
/**
431
 * Base class for all value mirror objects.
432
 * @param {string} type The type of the mirror
433
 * @param {value} value The value reflected by this mirror
434
 * @param {boolean} transient indicate whether this object is transient with a
435
 *    transient handle
436
 * @constructor
437
 * @extends Mirror
438
 */
439
function ValueMirror(type, value, transient) {
440
  %_CallFunction(this, type, Mirror);
441
  this.value_ = value;
442
  if (!transient) {
443
    this.allocateHandle_();
444
  } else {
445
    this.allocateTransientHandle_();
446
  }
447
}
448
inherits(ValueMirror, Mirror);
449

    
450

    
451
Mirror.prototype.handle = function() {
452
  return this.handle_;
453
};
454

    
455

    
456
/**
457
 * Check whether this is a primitive value.
458
 * @return {boolean} True if the mirror reflects a primitive value
459
 */
460
ValueMirror.prototype.isPrimitive = function() {
461
  var type = this.type();
462
  return type === 'undefined' ||
463
         type === 'null' ||
464
         type === 'boolean' ||
465
         type === 'number' ||
466
         type === 'string';
467
};
468

    
469

    
470
/**
471
 * Get the actual value reflected by this mirror.
472
 * @return {value} The value reflected by this mirror
473
 */
474
ValueMirror.prototype.value = function() {
475
  return this.value_;
476
};
477

    
478

    
479
/**
480
 * Mirror object for Undefined.
481
 * @constructor
482
 * @extends ValueMirror
483
 */
484
function UndefinedMirror() {
485
  %_CallFunction(this, UNDEFINED_TYPE, UNDEFINED, ValueMirror);
486
}
487
inherits(UndefinedMirror, ValueMirror);
488

    
489

    
490
UndefinedMirror.prototype.toText = function() {
491
  return 'undefined';
492
};
493

    
494

    
495
/**
496
 * Mirror object for null.
497
 * @constructor
498
 * @extends ValueMirror
499
 */
500
function NullMirror() {
501
  %_CallFunction(this, NULL_TYPE, null, ValueMirror);
502
}
503
inherits(NullMirror, ValueMirror);
504

    
505

    
506
NullMirror.prototype.toText = function() {
507
  return 'null';
508
};
509

    
510

    
511
/**
512
 * Mirror object for boolean values.
513
 * @param {boolean} value The boolean value reflected by this mirror
514
 * @constructor
515
 * @extends ValueMirror
516
 */
517
function BooleanMirror(value) {
518
  %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
519
}
520
inherits(BooleanMirror, ValueMirror);
521

    
522

    
523
BooleanMirror.prototype.toText = function() {
524
  return this.value_ ? 'true' : 'false';
525
};
526

    
527

    
528
/**
529
 * Mirror object for number values.
530
 * @param {number} value The number value reflected by this mirror
531
 * @constructor
532
 * @extends ValueMirror
533
 */
534
function NumberMirror(value) {
535
  %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
536
}
537
inherits(NumberMirror, ValueMirror);
538

    
539

    
540
NumberMirror.prototype.toText = function() {
541
  return %NumberToString(this.value_);
542
};
543

    
544

    
545
/**
546
 * Mirror object for string values.
547
 * @param {string} value The string value reflected by this mirror
548
 * @constructor
549
 * @extends ValueMirror
550
 */
551
function StringMirror(value) {
552
  %_CallFunction(this, STRING_TYPE, value, ValueMirror);
553
}
554
inherits(StringMirror, ValueMirror);
555

    
556

    
557
StringMirror.prototype.length = function() {
558
  return this.value_.length;
559
};
560

    
561
StringMirror.prototype.getTruncatedValue = function(maxLength) {
562
  if (maxLength != -1 && this.length() > maxLength) {
563
    return this.value_.substring(0, maxLength) +
564
           '... (length: ' + this.length() + ')';
565
  }
566
  return this.value_;
567
};
568

    
569
StringMirror.prototype.toText = function() {
570
  return this.getTruncatedValue(kMaxProtocolStringLength);
571
};
572

    
573

    
574
/**
575
 * Mirror object for objects.
576
 * @param {object} value The object reflected by this mirror
577
 * @param {boolean} transient indicate whether this object is transient with a
578
 *    transient handle
579
 * @constructor
580
 * @extends ValueMirror
581
 */
582
function ObjectMirror(value, type, transient) {
583
  %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
584
}
585
inherits(ObjectMirror, ValueMirror);
586

    
587

    
588
ObjectMirror.prototype.className = function() {
589
  return %_ClassOf(this.value_);
590
};
591

    
592

    
593
ObjectMirror.prototype.constructorFunction = function() {
594
  return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
595
};
596

    
597

    
598
ObjectMirror.prototype.prototypeObject = function() {
599
  return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
600
};
601

    
602

    
603
ObjectMirror.prototype.protoObject = function() {
604
  return MakeMirror(%DebugGetPrototype(this.value_));
605
};
606

    
607

    
608
ObjectMirror.prototype.hasNamedInterceptor = function() {
609
  // Get information on interceptors for this object.
610
  var x = %GetInterceptorInfo(this.value_);
611
  return (x & 2) != 0;
612
};
613

    
614

    
615
ObjectMirror.prototype.hasIndexedInterceptor = function() {
616
  // Get information on interceptors for this object.
617
  var x = %GetInterceptorInfo(this.value_);
618
  return (x & 1) != 0;
619
};
620

    
621

    
622
/**
623
 * Return the property names for this object.
624
 * @param {number} kind Indicate whether named, indexed or both kinds of
625
 *     properties are requested
626
 * @param {number} limit Limit the number of names returend to the specified
627
       value
628
 * @return {Array} Property names for this object
629
 */
630
ObjectMirror.prototype.propertyNames = function(kind, limit) {
631
  // Find kind and limit and allocate array for the result
632
  kind = kind || PropertyKind.Named | PropertyKind.Indexed;
633

    
634
  var propertyNames;
635
  var elementNames;
636
  var total = 0;
637

    
638
  // Find all the named properties.
639
  if (kind & PropertyKind.Named) {
640
    // Get the local property names.
641
    propertyNames = %GetLocalPropertyNames(this.value_, true);
642
    total += propertyNames.length;
643

    
644
    // Get names for named interceptor properties if any.
645
    if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
646
      var namedInterceptorNames =
647
          %GetNamedInterceptorPropertyNames(this.value_);
648
      if (namedInterceptorNames) {
649
        propertyNames = propertyNames.concat(namedInterceptorNames);
650
        total += namedInterceptorNames.length;
651
      }
652
    }
653
  }
654

    
655
  // Find all the indexed properties.
656
  if (kind & PropertyKind.Indexed) {
657
    // Get the local element names.
658
    elementNames = %GetLocalElementNames(this.value_);
659
    total += elementNames.length;
660

    
661
    // Get names for indexed interceptor properties.
662
    if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
663
      var indexedInterceptorNames =
664
          %GetIndexedInterceptorElementNames(this.value_);
665
      if (indexedInterceptorNames) {
666
        elementNames = elementNames.concat(indexedInterceptorNames);
667
        total += indexedInterceptorNames.length;
668
      }
669
    }
670
  }
671
  limit = Math.min(limit || total, total);
672

    
673
  var names = new Array(limit);
674
  var index = 0;
675

    
676
  // Copy names for named properties.
677
  if (kind & PropertyKind.Named) {
678
    for (var i = 0; index < limit && i < propertyNames.length; i++) {
679
      names[index++] = propertyNames[i];
680
    }
681
  }
682

    
683
  // Copy names for indexed properties.
684
  if (kind & PropertyKind.Indexed) {
685
    for (var i = 0; index < limit && i < elementNames.length; i++) {
686
      names[index++] = elementNames[i];
687
    }
688
  }
689

    
690
  return names;
691
};
692

    
693

    
694
/**
695
 * Return the properties for this object as an array of PropertyMirror objects.
696
 * @param {number} kind Indicate whether named, indexed or both kinds of
697
 *     properties are requested
698
 * @param {number} limit Limit the number of properties returned to the
699
       specified value
700
 * @return {Array} Property mirrors for this object
701
 */
702
ObjectMirror.prototype.properties = function(kind, limit) {
703
  var names = this.propertyNames(kind, limit);
704
  var properties = new Array(names.length);
705
  for (var i = 0; i < names.length; i++) {
706
    properties[i] = this.property(names[i]);
707
  }
708

    
709
  return properties;
710
};
711

    
712

    
713
/**
714
 * Return the internal properties for this object as an array of
715
 * InternalPropertyMirror objects.
716
 * @return {Array} Property mirrors for this object
717
 */
718
ObjectMirror.prototype.internalProperties = function() {
719
  return ObjectMirror.GetInternalProperties(this.value_);
720
}
721

    
722

    
723
ObjectMirror.prototype.property = function(name) {
724
  var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
725
  if (details) {
726
    return new PropertyMirror(this, name, details);
727
  }
728

    
729
  // Nothing found.
730
  return GetUndefinedMirror();
731
};
732

    
733

    
734

    
735
/**
736
 * Try to find a property from its value.
737
 * @param {Mirror} value The property value to look for
738
 * @return {PropertyMirror} The property with the specified value. If no
739
 *     property was found with the specified value UndefinedMirror is returned
740
 */
741
ObjectMirror.prototype.lookupProperty = function(value) {
742
  var properties = this.properties();
743

    
744
  // Look for property value in properties.
745
  for (var i = 0; i < properties.length; i++) {
746

    
747
    // Skip properties which are defined through assessors.
748
    var property = properties[i];
749
    if (property.propertyType() != PropertyType.Callbacks) {
750
      if (%_ObjectEquals(property.value_, value.value_)) {
751
        return property;
752
      }
753
    }
754
  }
755

    
756
  // Nothing found.
757
  return GetUndefinedMirror();
758
};
759

    
760

    
761
/**
762
 * Returns objects which has direct references to this object
763
 * @param {number} opt_max_objects Optional parameter specifying the maximum
764
 *     number of referencing objects to return.
765
 * @return {Array} The objects which has direct references to this object.
766
 */
767
ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
768
  // Find all objects with direct references to this object.
769
  var result = %DebugReferencedBy(this.value_,
770
                                  Mirror.prototype, opt_max_objects || 0);
771

    
772
  // Make mirrors for all the references found.
773
  for (var i = 0; i < result.length; i++) {
774
    result[i] = MakeMirror(result[i]);
775
  }
776

    
777
  return result;
778
};
779

    
780

    
781
ObjectMirror.prototype.toText = function() {
782
  var name;
783
  var ctor = this.constructorFunction();
784
  if (!ctor.isFunction()) {
785
    name = this.className();
786
  } else {
787
    name = ctor.name();
788
    if (!name) {
789
      name = this.className();
790
    }
791
  }
792
  return '#<' + name + '>';
793
};
794

    
795

    
796
/**
797
 * Return the internal properties of the value, such as [[PrimitiveValue]] of
798
 * scalar wrapper objects and properties of the bound function.
799
 * This method is done static to be accessible from Debug API with the bare
800
 * values without mirrors.
801
 * @return {Array} array (possibly empty) of InternalProperty instances
802
 */
803
ObjectMirror.GetInternalProperties = function(value) {
804
  if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) ||
805
      IS_BOOLEAN_WRAPPER(value)) {
806
    var primitiveValue = %_ValueOf(value);
807
    return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)];
808
  } else if (IS_FUNCTION(value)) {
809
    var bindings = %BoundFunctionGetBindings(value);
810
    var result = [];
811
    if (bindings && IS_ARRAY(bindings)) {
812
      result.push(new InternalPropertyMirror("[[TargetFunction]]",
813
                                             bindings[0]));
814
      result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1]));
815
      var boundArgs = [];
816
      for (var i = 2; i < bindings.length; i++) {
817
        boundArgs.push(bindings[i]);
818
      }
819
      result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs));
820
    }
821
    return result;
822
  }
823
  return [];
824
}
825

    
826

    
827
/**
828
 * Mirror object for functions.
829
 * @param {function} value The function object reflected by this mirror.
830
 * @constructor
831
 * @extends ObjectMirror
832
 */
833
function FunctionMirror(value) {
834
  %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
835
  this.resolved_ = true;
836
}
837
inherits(FunctionMirror, ObjectMirror);
838

    
839

    
840
/**
841
 * Returns whether the function is resolved.
842
 * @return {boolean} True if the function is resolved. Unresolved functions can
843
 *     only originate as functions from stack frames
844
 */
845
FunctionMirror.prototype.resolved = function() {
846
  return this.resolved_;
847
};
848

    
849

    
850
/**
851
 * Returns the name of the function.
852
 * @return {string} Name of the function
853
 */
854
FunctionMirror.prototype.name = function() {
855
  return %FunctionGetName(this.value_);
856
};
857

    
858

    
859
/**
860
 * Returns the inferred name of the function.
861
 * @return {string} Name of the function
862
 */
863
FunctionMirror.prototype.inferredName = function() {
864
  return %FunctionGetInferredName(this.value_);
865
};
866

    
867

    
868
/**
869
 * Returns the source code for the function.
870
 * @return {string or undefined} The source code for the function. If the
871
 *     function is not resolved undefined will be returned.
872
 */
873
FunctionMirror.prototype.source = function() {
874
  // Return source if function is resolved. Otherwise just fall through to
875
  // return undefined.
876
  if (this.resolved()) {
877
    return builtins.FunctionSourceString(this.value_);
878
  }
879
};
880

    
881

    
882
/**
883
 * Returns the script object for the function.
884
 * @return {ScriptMirror or undefined} Script object for the function or
885
 *     undefined if the function has no script
886
 */
887
FunctionMirror.prototype.script = function() {
888
  // Return script if function is resolved. Otherwise just fall through
889
  // to return undefined.
890
  if (this.resolved()) {
891
    var script = %FunctionGetScript(this.value_);
892
    if (script) {
893
      return MakeMirror(script);
894
    }
895
  }
896
};
897

    
898

    
899
/**
900
 * Returns the script source position for the function. Only makes sense
901
 * for functions which has a script defined.
902
 * @return {Number or undefined} in-script position for the function
903
 */
904
FunctionMirror.prototype.sourcePosition_ = function() {
905
  // Return script if function is resolved. Otherwise just fall through
906
  // to return undefined.
907
  if (this.resolved()) {
908
    return %FunctionGetScriptSourcePosition(this.value_);
909
  }
910
};
911

    
912

    
913
/**
914
 * Returns the script source location object for the function. Only makes sense
915
 * for functions which has a script defined.
916
 * @return {Location or undefined} in-script location for the function begin
917
 */
918
FunctionMirror.prototype.sourceLocation = function() {
919
  if (this.resolved() && this.script()) {
920
    return this.script().locationFromPosition(this.sourcePosition_(),
921
                                              true);
922
  }
923
};
924

    
925

    
926
/**
927
 * Returns objects constructed by this function.
928
 * @param {number} opt_max_instances Optional parameter specifying the maximum
929
 *     number of instances to return.
930
 * @return {Array or undefined} The objects constructed by this function.
931
 */
932
FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
933
  if (this.resolved()) {
934
    // Find all objects constructed from this function.
935
    var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
936

    
937
    // Make mirrors for all the instances found.
938
    for (var i = 0; i < result.length; i++) {
939
      result[i] = MakeMirror(result[i]);
940
    }
941

    
942
    return result;
943
  } else {
944
    return [];
945
  }
946
};
947

    
948

    
949
FunctionMirror.prototype.scopeCount = function() {
950
  if (this.resolved()) {
951
    return %GetFunctionScopeCount(this.value());
952
  } else {
953
    return 0;
954
  }
955
};
956

    
957

    
958
FunctionMirror.prototype.scope = function(index) {
959
  if (this.resolved()) {
960
    return new ScopeMirror(UNDEFINED, this, index);
961
  }
962
};
963

    
964

    
965
FunctionMirror.prototype.toText = function() {
966
  return this.source();
967
};
968

    
969

    
970
/**
971
 * Mirror object for unresolved functions.
972
 * @param {string} value The name for the unresolved function reflected by this
973
 *     mirror.
974
 * @constructor
975
 * @extends ObjectMirror
976
 */
977
function UnresolvedFunctionMirror(value) {
978
  // Construct this using the ValueMirror as an unresolved function is not a
979
  // real object but just a string.
980
  %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
981
  this.propertyCount_ = 0;
982
  this.elementCount_ = 0;
983
  this.resolved_ = false;
984
}
985
inherits(UnresolvedFunctionMirror, FunctionMirror);
986

    
987

    
988
UnresolvedFunctionMirror.prototype.className = function() {
989
  return 'Function';
990
};
991

    
992

    
993
UnresolvedFunctionMirror.prototype.constructorFunction = function() {
994
  return GetUndefinedMirror();
995
};
996

    
997

    
998
UnresolvedFunctionMirror.prototype.prototypeObject = function() {
999
  return GetUndefinedMirror();
1000
};
1001

    
1002

    
1003
UnresolvedFunctionMirror.prototype.protoObject = function() {
1004
  return GetUndefinedMirror();
1005
};
1006

    
1007

    
1008
UnresolvedFunctionMirror.prototype.name = function() {
1009
  return this.value_;
1010
};
1011

    
1012

    
1013
UnresolvedFunctionMirror.prototype.inferredName = function() {
1014
  return undefined;
1015
};
1016

    
1017

    
1018
UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
1019
  return [];
1020
};
1021

    
1022

    
1023
/**
1024
 * Mirror object for arrays.
1025
 * @param {Array} value The Array object reflected by this mirror
1026
 * @constructor
1027
 * @extends ObjectMirror
1028
 */
1029
function ArrayMirror(value) {
1030
  %_CallFunction(this, value, ObjectMirror);
1031
}
1032
inherits(ArrayMirror, ObjectMirror);
1033

    
1034

    
1035
ArrayMirror.prototype.length = function() {
1036
  return this.value_.length;
1037
};
1038

    
1039

    
1040
ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index,
1041
                                                            opt_to_index) {
1042
  var from_index = opt_from_index || 0;
1043
  var to_index = opt_to_index || this.length() - 1;
1044
  if (from_index > to_index) return new Array();
1045
  var values = new Array(to_index - from_index + 1);
1046
  for (var i = from_index; i <= to_index; i++) {
1047
    var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
1048
    var value;
1049
    if (details) {
1050
      value = new PropertyMirror(this, i, details);
1051
    } else {
1052
      value = GetUndefinedMirror();
1053
    }
1054
    values[i - from_index] = value;
1055
  }
1056
  return values;
1057
};
1058

    
1059

    
1060
/**
1061
 * Mirror object for dates.
1062
 * @param {Date} value The Date object reflected by this mirror
1063
 * @constructor
1064
 * @extends ObjectMirror
1065
 */
1066
function DateMirror(value) {
1067
  %_CallFunction(this, value, ObjectMirror);
1068
}
1069
inherits(DateMirror, ObjectMirror);
1070

    
1071

    
1072
DateMirror.prototype.toText = function() {
1073
  var s = JSON.stringify(this.value_);
1074
  return s.substring(1, s.length - 1);  // cut quotes
1075
};
1076

    
1077

    
1078
/**
1079
 * Mirror object for regular expressions.
1080
 * @param {RegExp} value The RegExp object reflected by this mirror
1081
 * @constructor
1082
 * @extends ObjectMirror
1083
 */
1084
function RegExpMirror(value) {
1085
  %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
1086
}
1087
inherits(RegExpMirror, ObjectMirror);
1088

    
1089

    
1090
/**
1091
 * Returns the source to the regular expression.
1092
 * @return {string or undefined} The source to the regular expression
1093
 */
1094
RegExpMirror.prototype.source = function() {
1095
  return this.value_.source;
1096
};
1097

    
1098

    
1099
/**
1100
 * Returns whether this regular expression has the global (g) flag set.
1101
 * @return {boolean} Value of the global flag
1102
 */
1103
RegExpMirror.prototype.global = function() {
1104
  return this.value_.global;
1105
};
1106

    
1107

    
1108
/**
1109
 * Returns whether this regular expression has the ignore case (i) flag set.
1110
 * @return {boolean} Value of the ignore case flag
1111
 */
1112
RegExpMirror.prototype.ignoreCase = function() {
1113
  return this.value_.ignoreCase;
1114
};
1115

    
1116

    
1117
/**
1118
 * Returns whether this regular expression has the multiline (m) flag set.
1119
 * @return {boolean} Value of the multiline flag
1120
 */
1121
RegExpMirror.prototype.multiline = function() {
1122
  return this.value_.multiline;
1123
};
1124

    
1125

    
1126
RegExpMirror.prototype.toText = function() {
1127
  // Simpel to text which is used when on specialization in subclass.
1128
  return "/" + this.source() + "/";
1129
};
1130

    
1131

    
1132
/**
1133
 * Mirror object for error objects.
1134
 * @param {Error} value The error object reflected by this mirror
1135
 * @constructor
1136
 * @extends ObjectMirror
1137
 */
1138
function ErrorMirror(value) {
1139
  %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
1140
}
1141
inherits(ErrorMirror, ObjectMirror);
1142

    
1143

    
1144
/**
1145
 * Returns the message for this eror object.
1146
 * @return {string or undefined} The message for this eror object
1147
 */
1148
ErrorMirror.prototype.message = function() {
1149
  return this.value_.message;
1150
};
1151

    
1152

    
1153
ErrorMirror.prototype.toText = function() {
1154
  // Use the same text representation as in messages.js.
1155
  var text;
1156
  try {
1157
    str = %_CallFunction(this.value_, builtins.ErrorToString);
1158
  } catch (e) {
1159
    str = '#<Error>';
1160
  }
1161
  return str;
1162
};
1163

    
1164

    
1165
/**
1166
 * Base mirror object for properties.
1167
 * @param {ObjectMirror} mirror The mirror object having this property
1168
 * @param {string} name The name of the property
1169
 * @param {Array} details Details about the property
1170
 * @constructor
1171
 * @extends Mirror
1172
 */
1173
function PropertyMirror(mirror, name, details) {
1174
  %_CallFunction(this, PROPERTY_TYPE, Mirror);
1175
  this.mirror_ = mirror;
1176
  this.name_ = name;
1177
  this.value_ = details[0];
1178
  this.details_ = details[1];
1179
  if (details.length > 2) {
1180
    this.exception_ = details[2];
1181
    this.getter_ = details[3];
1182
    this.setter_ = details[4];
1183
  }
1184
}
1185
inherits(PropertyMirror, Mirror);
1186

    
1187

    
1188
PropertyMirror.prototype.isReadOnly = function() {
1189
  return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1190
};
1191

    
1192

    
1193
PropertyMirror.prototype.isEnum = function() {
1194
  return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1195
};
1196

    
1197

    
1198
PropertyMirror.prototype.canDelete = function() {
1199
  return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1200
};
1201

    
1202

    
1203
PropertyMirror.prototype.name = function() {
1204
  return this.name_;
1205
};
1206

    
1207

    
1208
PropertyMirror.prototype.isIndexed = function() {
1209
  for (var i = 0; i < this.name_.length; i++) {
1210
    if (this.name_[i] < '0' || '9' < this.name_[i]) {
1211
      return false;
1212
    }
1213
  }
1214
  return true;
1215
};
1216

    
1217

    
1218
PropertyMirror.prototype.value = function() {
1219
  return MakeMirror(this.value_, false);
1220
};
1221

    
1222

    
1223
/**
1224
 * Returns whether this property value is an exception.
1225
 * @return {booolean} True if this property value is an exception
1226
 */
1227
PropertyMirror.prototype.isException = function() {
1228
  return this.exception_ ? true : false;
1229
};
1230

    
1231

    
1232
PropertyMirror.prototype.attributes = function() {
1233
  return %DebugPropertyAttributesFromDetails(this.details_);
1234
};
1235

    
1236

    
1237
PropertyMirror.prototype.propertyType = function() {
1238
  return %DebugPropertyTypeFromDetails(this.details_);
1239
};
1240

    
1241

    
1242
PropertyMirror.prototype.insertionIndex = function() {
1243
  return %DebugPropertyIndexFromDetails(this.details_);
1244
};
1245

    
1246

    
1247
/**
1248
 * Returns whether this property has a getter defined through __defineGetter__.
1249
 * @return {booolean} True if this property has a getter
1250
 */
1251
PropertyMirror.prototype.hasGetter = function() {
1252
  return this.getter_ ? true : false;
1253
};
1254

    
1255

    
1256
/**
1257
 * Returns whether this property has a setter defined through __defineSetter__.
1258
 * @return {booolean} True if this property has a setter
1259
 */
1260
PropertyMirror.prototype.hasSetter = function() {
1261
  return this.setter_ ? true : false;
1262
};
1263

    
1264

    
1265
/**
1266
 * Returns the getter for this property defined through __defineGetter__.
1267
 * @return {Mirror} FunctionMirror reflecting the getter function or
1268
 *     UndefinedMirror if there is no getter for this property
1269
 */
1270
PropertyMirror.prototype.getter = function() {
1271
  if (this.hasGetter()) {
1272
    return MakeMirror(this.getter_);
1273
  } else {
1274
    return GetUndefinedMirror();
1275
  }
1276
};
1277

    
1278

    
1279
/**
1280
 * Returns the setter for this property defined through __defineSetter__.
1281
 * @return {Mirror} FunctionMirror reflecting the setter function or
1282
 *     UndefinedMirror if there is no setter for this property
1283
 */
1284
PropertyMirror.prototype.setter = function() {
1285
  if (this.hasSetter()) {
1286
    return MakeMirror(this.setter_);
1287
  } else {
1288
    return GetUndefinedMirror();
1289
  }
1290
};
1291

    
1292

    
1293
/**
1294
 * Returns whether this property is natively implemented by the host or a set
1295
 * through JavaScript code.
1296
 * @return {boolean} True if the property is
1297
 *     UndefinedMirror if there is no setter for this property
1298
 */
1299
PropertyMirror.prototype.isNative = function() {
1300
  return (this.propertyType() == PropertyType.Interceptor) ||
1301
         ((this.propertyType() == PropertyType.Callbacks) &&
1302
          !this.hasGetter() && !this.hasSetter());
1303
};
1304

    
1305

    
1306
/**
1307
 * Mirror object for internal properties. Internal property reflects properties
1308
 * not accessible from user code such as [[BoundThis]] in bound function.
1309
 * Their names are merely symbolic.
1310
 * @param {string} name The name of the property
1311
 * @param {value} property value
1312
 * @constructor
1313
 * @extends Mirror
1314
 */
1315
function InternalPropertyMirror(name, value) {
1316
  %_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror);
1317
  this.name_ = name;
1318
  this.value_ = value;
1319
}
1320
inherits(InternalPropertyMirror, Mirror);
1321

    
1322

    
1323
InternalPropertyMirror.prototype.name = function() {
1324
  return this.name_;
1325
};
1326

    
1327

    
1328
InternalPropertyMirror.prototype.value = function() {
1329
  return MakeMirror(this.value_, false);
1330
};
1331

    
1332

    
1333
var kFrameDetailsFrameIdIndex = 0;
1334
var kFrameDetailsReceiverIndex = 1;
1335
var kFrameDetailsFunctionIndex = 2;
1336
var kFrameDetailsArgumentCountIndex = 3;
1337
var kFrameDetailsLocalCountIndex = 4;
1338
var kFrameDetailsSourcePositionIndex = 5;
1339
var kFrameDetailsConstructCallIndex = 6;
1340
var kFrameDetailsAtReturnIndex = 7;
1341
var kFrameDetailsFlagsIndex = 8;
1342
var kFrameDetailsFirstDynamicIndex = 9;
1343

    
1344
var kFrameDetailsNameIndex = 0;
1345
var kFrameDetailsValueIndex = 1;
1346
var kFrameDetailsNameValueSize = 2;
1347

    
1348
var kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1349
var kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1350
var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
1351

    
1352
/**
1353
 * Wrapper for the frame details information retreived from the VM. The frame
1354
 * details from the VM is an array with the following content. See runtime.cc
1355
 * Runtime_GetFrameDetails.
1356
 *     0: Id
1357
 *     1: Receiver
1358
 *     2: Function
1359
 *     3: Argument count
1360
 *     4: Local count
1361
 *     5: Source position
1362
 *     6: Construct call
1363
 *     7: Is at return
1364
 *     8: Flags (debugger frame, optimized frame, inlined frame index)
1365
 *     Arguments name, value
1366
 *     Locals name, value
1367
 *     Return value if any
1368
 * @param {number} break_id Current break id
1369
 * @param {number} index Frame number
1370
 * @constructor
1371
 */
1372
function FrameDetails(break_id, index) {
1373
  this.break_id_ = break_id;
1374
  this.details_ = %GetFrameDetails(break_id, index);
1375
}
1376

    
1377

    
1378
FrameDetails.prototype.frameId = function() {
1379
  %CheckExecutionState(this.break_id_);
1380
  return this.details_[kFrameDetailsFrameIdIndex];
1381
};
1382

    
1383

    
1384
FrameDetails.prototype.receiver = function() {
1385
  %CheckExecutionState(this.break_id_);
1386
  return this.details_[kFrameDetailsReceiverIndex];
1387
};
1388

    
1389

    
1390
FrameDetails.prototype.func = function() {
1391
  %CheckExecutionState(this.break_id_);
1392
  return this.details_[kFrameDetailsFunctionIndex];
1393
};
1394

    
1395

    
1396
FrameDetails.prototype.isConstructCall = function() {
1397
  %CheckExecutionState(this.break_id_);
1398
  return this.details_[kFrameDetailsConstructCallIndex];
1399
};
1400

    
1401

    
1402
FrameDetails.prototype.isAtReturn = function() {
1403
  %CheckExecutionState(this.break_id_);
1404
  return this.details_[kFrameDetailsAtReturnIndex];
1405
};
1406

    
1407

    
1408
FrameDetails.prototype.isDebuggerFrame = function() {
1409
  %CheckExecutionState(this.break_id_);
1410
  var f = kFrameDetailsFlagDebuggerFrameMask;
1411
  return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1412
};
1413

    
1414

    
1415
FrameDetails.prototype.isOptimizedFrame = function() {
1416
  %CheckExecutionState(this.break_id_);
1417
  var f = kFrameDetailsFlagOptimizedFrameMask;
1418
  return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1419
};
1420

    
1421

    
1422
FrameDetails.prototype.isInlinedFrame = function() {
1423
  return this.inlinedFrameIndex() > 0;
1424
};
1425

    
1426

    
1427
FrameDetails.prototype.inlinedFrameIndex = function() {
1428
  %CheckExecutionState(this.break_id_);
1429
  var f = kFrameDetailsFlagInlinedFrameIndexMask;
1430
  return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2;
1431
};
1432

    
1433

    
1434
FrameDetails.prototype.argumentCount = function() {
1435
  %CheckExecutionState(this.break_id_);
1436
  return this.details_[kFrameDetailsArgumentCountIndex];
1437
};
1438

    
1439

    
1440
FrameDetails.prototype.argumentName = function(index) {
1441
  %CheckExecutionState(this.break_id_);
1442
  if (index >= 0 && index < this.argumentCount()) {
1443
    return this.details_[kFrameDetailsFirstDynamicIndex +
1444
                         index * kFrameDetailsNameValueSize +
1445
                         kFrameDetailsNameIndex];
1446
  }
1447
};
1448

    
1449

    
1450
FrameDetails.prototype.argumentValue = function(index) {
1451
  %CheckExecutionState(this.break_id_);
1452
  if (index >= 0 && index < this.argumentCount()) {
1453
    return this.details_[kFrameDetailsFirstDynamicIndex +
1454
                         index * kFrameDetailsNameValueSize +
1455
                         kFrameDetailsValueIndex];
1456
  }
1457
};
1458

    
1459

    
1460
FrameDetails.prototype.localCount = function() {
1461
  %CheckExecutionState(this.break_id_);
1462
  return this.details_[kFrameDetailsLocalCountIndex];
1463
};
1464

    
1465

    
1466
FrameDetails.prototype.sourcePosition = function() {
1467
  %CheckExecutionState(this.break_id_);
1468
  return this.details_[kFrameDetailsSourcePositionIndex];
1469
};
1470

    
1471

    
1472
FrameDetails.prototype.localName = function(index) {
1473
  %CheckExecutionState(this.break_id_);
1474
  if (index >= 0 && index < this.localCount()) {
1475
    var locals_offset = kFrameDetailsFirstDynamicIndex +
1476
                        this.argumentCount() * kFrameDetailsNameValueSize;
1477
    return this.details_[locals_offset +
1478
                         index * kFrameDetailsNameValueSize +
1479
                         kFrameDetailsNameIndex];
1480
  }
1481
};
1482

    
1483

    
1484
FrameDetails.prototype.localValue = function(index) {
1485
  %CheckExecutionState(this.break_id_);
1486
  if (index >= 0 && index < this.localCount()) {
1487
    var locals_offset = kFrameDetailsFirstDynamicIndex +
1488
                        this.argumentCount() * kFrameDetailsNameValueSize;
1489
    return this.details_[locals_offset +
1490
                         index * kFrameDetailsNameValueSize +
1491
                         kFrameDetailsValueIndex];
1492
  }
1493
};
1494

    
1495

    
1496
FrameDetails.prototype.returnValue = function() {
1497
  %CheckExecutionState(this.break_id_);
1498
  var return_value_offset =
1499
      kFrameDetailsFirstDynamicIndex +
1500
      (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1501
  if (this.details_[kFrameDetailsAtReturnIndex]) {
1502
    return this.details_[return_value_offset];
1503
  }
1504
};
1505

    
1506

    
1507
FrameDetails.prototype.scopeCount = function() {
1508
  return %GetScopeCount(this.break_id_, this.frameId());
1509
};
1510

    
1511

    
1512
FrameDetails.prototype.stepInPositionsImpl = function() {
1513
  return %GetStepInPositions(this.break_id_, this.frameId());
1514
};
1515

    
1516

    
1517
/**
1518
 * Mirror object for stack frames.
1519
 * @param {number} break_id The break id in the VM for which this frame is
1520
       valid
1521
 * @param {number} index The frame index (top frame is index 0)
1522
 * @constructor
1523
 * @extends Mirror
1524
 */
1525
function FrameMirror(break_id, index) {
1526
  %_CallFunction(this, FRAME_TYPE, Mirror);
1527
  this.break_id_ = break_id;
1528
  this.index_ = index;
1529
  this.details_ = new FrameDetails(break_id, index);
1530
}
1531
inherits(FrameMirror, Mirror);
1532

    
1533

    
1534
FrameMirror.prototype.index = function() {
1535
  return this.index_;
1536
};
1537

    
1538

    
1539
FrameMirror.prototype.func = function() {
1540
  // Get the function for this frame from the VM.
1541
  var f = this.details_.func();
1542

    
1543
  // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1544
  // value returned from the VM might be a string if the function for the
1545
  // frame is unresolved.
1546
  if (IS_FUNCTION(f)) {
1547
    return MakeMirror(f);
1548
  } else {
1549
    return new UnresolvedFunctionMirror(f);
1550
  }
1551
};
1552

    
1553

    
1554
FrameMirror.prototype.receiver = function() {
1555
  return MakeMirror(this.details_.receiver());
1556
};
1557

    
1558

    
1559
FrameMirror.prototype.isConstructCall = function() {
1560
  return this.details_.isConstructCall();
1561
};
1562

    
1563

    
1564
FrameMirror.prototype.isAtReturn = function() {
1565
  return this.details_.isAtReturn();
1566
};
1567

    
1568

    
1569
FrameMirror.prototype.isDebuggerFrame = function() {
1570
  return this.details_.isDebuggerFrame();
1571
};
1572

    
1573

    
1574
FrameMirror.prototype.isOptimizedFrame = function() {
1575
  return this.details_.isOptimizedFrame();
1576
};
1577

    
1578

    
1579
FrameMirror.prototype.isInlinedFrame = function() {
1580
  return this.details_.isInlinedFrame();
1581
};
1582

    
1583

    
1584
FrameMirror.prototype.inlinedFrameIndex = function() {
1585
  return this.details_.inlinedFrameIndex();
1586
};
1587

    
1588

    
1589
FrameMirror.prototype.argumentCount = function() {
1590
  return this.details_.argumentCount();
1591
};
1592

    
1593

    
1594
FrameMirror.prototype.argumentName = function(index) {
1595
  return this.details_.argumentName(index);
1596
};
1597

    
1598

    
1599
FrameMirror.prototype.argumentValue = function(index) {
1600
  return MakeMirror(this.details_.argumentValue(index));
1601
};
1602

    
1603

    
1604
FrameMirror.prototype.localCount = function() {
1605
  return this.details_.localCount();
1606
};
1607

    
1608

    
1609
FrameMirror.prototype.localName = function(index) {
1610
  return this.details_.localName(index);
1611
};
1612

    
1613

    
1614
FrameMirror.prototype.localValue = function(index) {
1615
  return MakeMirror(this.details_.localValue(index));
1616
};
1617

    
1618

    
1619
FrameMirror.prototype.returnValue = function() {
1620
  return MakeMirror(this.details_.returnValue());
1621
};
1622

    
1623

    
1624
FrameMirror.prototype.sourcePosition = function() {
1625
  return this.details_.sourcePosition();
1626
};
1627

    
1628

    
1629
FrameMirror.prototype.sourceLocation = function() {
1630
  if (this.func().resolved() && this.func().script()) {
1631
    return this.func().script().locationFromPosition(this.sourcePosition(),
1632
                                                     true);
1633
  }
1634
};
1635

    
1636

    
1637
FrameMirror.prototype.sourceLine = function() {
1638
  if (this.func().resolved()) {
1639
    var location = this.sourceLocation();
1640
    if (location) {
1641
      return location.line;
1642
    }
1643
  }
1644
};
1645

    
1646

    
1647
FrameMirror.prototype.sourceColumn = function() {
1648
  if (this.func().resolved()) {
1649
    var location = this.sourceLocation();
1650
    if (location) {
1651
      return location.column;
1652
    }
1653
  }
1654
};
1655

    
1656

    
1657
FrameMirror.prototype.sourceLineText = function() {
1658
  if (this.func().resolved()) {
1659
    var location = this.sourceLocation();
1660
    if (location) {
1661
      return location.sourceText();
1662
    }
1663
  }
1664
};
1665

    
1666

    
1667
FrameMirror.prototype.scopeCount = function() {
1668
  return this.details_.scopeCount();
1669
};
1670

    
1671

    
1672
FrameMirror.prototype.scope = function(index) {
1673
  return new ScopeMirror(this, UNDEFINED, index);
1674
};
1675

    
1676

    
1677
FrameMirror.prototype.stepInPositions = function() {
1678
  var script = this.func().script();
1679
  var funcOffset = this.func().sourcePosition_();
1680

    
1681
  var stepInRaw = this.details_.stepInPositionsImpl();
1682
  var result = [];
1683
  if (stepInRaw) {
1684
    for (var i = 0; i < stepInRaw.length; i++) {
1685
      var posStruct = {};
1686
      var offset = script.locationFromPosition(funcOffset + stepInRaw[i],
1687
                                               true);
1688
      serializeLocationFields(offset, posStruct);
1689
      var item = {
1690
        position: posStruct
1691
      };
1692
      result.push(item);
1693
    }
1694
  }
1695

    
1696
  return result;
1697
};
1698

    
1699

    
1700
FrameMirror.prototype.evaluate = function(source, disable_break,
1701
                                          opt_context_object) {
1702
  return MakeMirror(%DebugEvaluate(this.break_id_,
1703
                                   this.details_.frameId(),
1704
                                   this.details_.inlinedFrameIndex(),
1705
                                   source,
1706
                                   Boolean(disable_break),
1707
                                   opt_context_object));
1708
};
1709

    
1710

    
1711
FrameMirror.prototype.invocationText = function() {
1712
  // Format frame invoaction (receiver, function and arguments).
1713
  var result = '';
1714
  var func = this.func();
1715
  var receiver = this.receiver();
1716
  if (this.isConstructCall()) {
1717
    // For constructor frames display new followed by the function name.
1718
    result += 'new ';
1719
    result += func.name() ? func.name() : '[anonymous]';
1720
  } else if (this.isDebuggerFrame()) {
1721
    result += '[debugger]';
1722
  } else {
1723
    // If the receiver has a className which is 'global' don't display it.
1724
    var display_receiver =
1725
      !receiver.className || (receiver.className() != 'global');
1726
    if (display_receiver) {
1727
      result += receiver.toText();
1728
    }
1729
    // Try to find the function as a property in the receiver. Include the
1730
    // prototype chain in the lookup.
1731
    var property = GetUndefinedMirror();
1732
    if (receiver.isObject()) {
1733
      for (var r = receiver;
1734
           !r.isNull() && property.isUndefined();
1735
           r = r.protoObject()) {
1736
        property = r.lookupProperty(func);
1737
      }
1738
    }
1739
    if (!property.isUndefined()) {
1740
      // The function invoked was found on the receiver. Use the property name
1741
      // for the backtrace.
1742
      if (!property.isIndexed()) {
1743
        if (display_receiver) {
1744
          result += '.';
1745
        }
1746
        result += property.name();
1747
      } else {
1748
        result += '[';
1749
        result += property.name();
1750
        result += ']';
1751
      }
1752
      // Also known as - if the name in the function doesn't match the name
1753
      // under which it was looked up.
1754
      if (func.name() && func.name() != property.name()) {
1755
        result += '(aka ' + func.name() + ')';
1756
      }
1757
    } else {
1758
      // The function invoked was not found on the receiver. Use the function
1759
      // name if available for the backtrace.
1760
      if (display_receiver) {
1761
        result += '.';
1762
      }
1763
      result += func.name() ? func.name() : '[anonymous]';
1764
    }
1765
  }
1766

    
1767
  // Render arguments for normal frames.
1768
  if (!this.isDebuggerFrame()) {
1769
    result += '(';
1770
    for (var i = 0; i < this.argumentCount(); i++) {
1771
      if (i != 0) result += ', ';
1772
      if (this.argumentName(i)) {
1773
        result += this.argumentName(i);
1774
        result += '=';
1775
      }
1776
      result += this.argumentValue(i).toText();
1777
    }
1778
    result += ')';
1779
  }
1780

    
1781
  if (this.isAtReturn()) {
1782
    result += ' returning ';
1783
    result += this.returnValue().toText();
1784
  }
1785

    
1786
  return result;
1787
};
1788

    
1789

    
1790
FrameMirror.prototype.sourceAndPositionText = function() {
1791
  // Format source and position.
1792
  var result = '';
1793
  var func = this.func();
1794
  if (func.resolved()) {
1795
    if (func.script()) {
1796
      if (func.script().name()) {
1797
        result += func.script().name();
1798
      } else {
1799
        result += '[unnamed]';
1800
      }
1801
      if (!this.isDebuggerFrame()) {
1802
        var location = this.sourceLocation();
1803
        result += ' line ';
1804
        result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1805
        result += ' column ';
1806
        result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1807
        if (!IS_UNDEFINED(this.sourcePosition())) {
1808
          result += ' (position ' + (this.sourcePosition() + 1) + ')';
1809
        }
1810
      }
1811
    } else {
1812
      result += '[no source]';
1813
    }
1814
  } else {
1815
    result += '[unresolved]';
1816
  }
1817

    
1818
  return result;
1819
};
1820

    
1821

    
1822
FrameMirror.prototype.localsText = function() {
1823
  // Format local variables.
1824
  var result = '';
1825
  var locals_count = this.localCount();
1826
  if (locals_count > 0) {
1827
    for (var i = 0; i < locals_count; ++i) {
1828
      result += '      var ';
1829
      result += this.localName(i);
1830
      result += ' = ';
1831
      result += this.localValue(i).toText();
1832
      if (i < locals_count - 1) result += '\n';
1833
    }
1834
  }
1835

    
1836
  return result;
1837
};
1838

    
1839

    
1840
FrameMirror.prototype.restart = function() {
1841
  var result = %LiveEditRestartFrame(this.break_id_, this.index_);
1842
  if (IS_UNDEFINED(result)) {
1843
    result = "Failed to find requested frame";
1844
  }
1845
  return result;
1846
};
1847

    
1848

    
1849
FrameMirror.prototype.toText = function(opt_locals) {
1850
  var result = '';
1851
  result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1852
  result += ' ';
1853
  result += this.invocationText();
1854
  result += ' ';
1855
  result += this.sourceAndPositionText();
1856
  if (opt_locals) {
1857
    result += '\n';
1858
    result += this.localsText();
1859
  }
1860
  return result;
1861
};
1862

    
1863

    
1864
var kScopeDetailsTypeIndex = 0;
1865
var kScopeDetailsObjectIndex = 1;
1866

    
1867
function ScopeDetails(frame, fun, index) {
1868
  if (frame) {
1869
    this.break_id_ = frame.break_id_;
1870
    this.details_ = %GetScopeDetails(frame.break_id_,
1871
                                     frame.details_.frameId(),
1872
                                     frame.details_.inlinedFrameIndex(),
1873
                                     index);
1874
    this.frame_id_ = frame.details_.frameId();
1875
    this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
1876
  } else {
1877
    this.details_ = %GetFunctionScopeDetails(fun.value(), index);
1878
    this.fun_value_ = fun.value();
1879
    this.break_id_ = undefined;
1880
  }
1881
  this.index_ = index;
1882
}
1883

    
1884

    
1885
ScopeDetails.prototype.type = function() {
1886
  if (!IS_UNDEFINED(this.break_id_)) {
1887
    %CheckExecutionState(this.break_id_);
1888
  }
1889
  return this.details_[kScopeDetailsTypeIndex];
1890
};
1891

    
1892

    
1893
ScopeDetails.prototype.object = function() {
1894
  if (!IS_UNDEFINED(this.break_id_)) {
1895
    %CheckExecutionState(this.break_id_);
1896
  }
1897
  return this.details_[kScopeDetailsObjectIndex];
1898
};
1899

    
1900

    
1901
ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
1902
  var raw_res;
1903
  if (!IS_UNDEFINED(this.break_id_)) {
1904
    %CheckExecutionState(this.break_id_);
1905
    raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_,
1906
        this.inlined_frame_id_, this.index_, name, new_value);
1907
  } else {
1908
    raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_,
1909
        name, new_value);
1910
  }
1911
  if (!raw_res) {
1912
    throw new Error("Failed to set variable value");
1913
  }
1914
};
1915

    
1916

    
1917
/**
1918
 * Mirror object for scope of frame or function. Either frame or function must
1919
 * be specified.
1920
 * @param {FrameMirror} frame The frame this scope is a part of
1921
 * @param {FunctionMirror} function The function this scope is a part of
1922
 * @param {number} index The scope index in the frame
1923
 * @constructor
1924
 * @extends Mirror
1925
 */
1926
function ScopeMirror(frame, function, index) {
1927
  %_CallFunction(this, SCOPE_TYPE, Mirror);
1928
  if (frame) {
1929
    this.frame_index_ = frame.index_;
1930
  } else {
1931
    this.frame_index_ = undefined;
1932
  }
1933
  this.scope_index_ = index;
1934
  this.details_ = new ScopeDetails(frame, function, index);
1935
}
1936
inherits(ScopeMirror, Mirror);
1937

    
1938

    
1939
ScopeMirror.prototype.frameIndex = function() {
1940
  return this.frame_index_;
1941
};
1942

    
1943

    
1944
ScopeMirror.prototype.scopeIndex = function() {
1945
  return this.scope_index_;
1946
};
1947

    
1948

    
1949
ScopeMirror.prototype.scopeType = function() {
1950
  return this.details_.type();
1951
};
1952

    
1953

    
1954
ScopeMirror.prototype.scopeObject = function() {
1955
  // For local and closure scopes create a transient mirror as these objects are
1956
  // created on the fly materializing the local or closure scopes and
1957
  // therefore will not preserve identity.
1958
  var transient = this.scopeType() == ScopeType.Local ||
1959
                  this.scopeType() == ScopeType.Closure;
1960
  return MakeMirror(this.details_.object(), transient);
1961
};
1962

    
1963

    
1964
ScopeMirror.prototype.setVariableValue = function(name, new_value) {
1965
  this.details_.setVariableValueImpl(name, new_value);
1966
};
1967

    
1968

    
1969
/**
1970
 * Mirror object for script source.
1971
 * @param {Script} script The script object
1972
 * @constructor
1973
 * @extends Mirror
1974
 */
1975
function ScriptMirror(script) {
1976
  %_CallFunction(this, SCRIPT_TYPE, Mirror);
1977
  this.script_ = script;
1978
  this.context_ = new ContextMirror(script.context_data);
1979
  this.allocateHandle_();
1980
}
1981
inherits(ScriptMirror, Mirror);
1982

    
1983

    
1984
ScriptMirror.prototype.value = function() {
1985
  return this.script_;
1986
};
1987

    
1988

    
1989
ScriptMirror.prototype.name = function() {
1990
  return this.script_.name || this.script_.nameOrSourceURL();
1991
};
1992

    
1993

    
1994
ScriptMirror.prototype.id = function() {
1995
  return this.script_.id;
1996
};
1997

    
1998

    
1999
ScriptMirror.prototype.source = function() {
2000
  return this.script_.source;
2001
};
2002

    
2003

    
2004
ScriptMirror.prototype.setSource = function(source) {
2005
  %DebugSetScriptSource(this.script_, source);
2006
};
2007

    
2008

    
2009
ScriptMirror.prototype.lineOffset = function() {
2010
  return this.script_.line_offset;
2011
};
2012

    
2013

    
2014
ScriptMirror.prototype.columnOffset = function() {
2015
  return this.script_.column_offset;
2016
};
2017

    
2018

    
2019
ScriptMirror.prototype.data = function() {
2020
  return this.script_.data;
2021
};
2022

    
2023

    
2024
ScriptMirror.prototype.scriptType = function() {
2025
  return this.script_.type;
2026
};
2027

    
2028

    
2029
ScriptMirror.prototype.compilationType = function() {
2030
  return this.script_.compilation_type;
2031
};
2032

    
2033

    
2034
ScriptMirror.prototype.lineCount = function() {
2035
  return this.script_.lineCount();
2036
};
2037

    
2038

    
2039
ScriptMirror.prototype.locationFromPosition = function(
2040
    position, include_resource_offset) {
2041
  return this.script_.locationFromPosition(position, include_resource_offset);
2042
};
2043

    
2044

    
2045
ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
2046
  return this.script_.sourceSlice(opt_from_line, opt_to_line);
2047
};
2048

    
2049

    
2050
ScriptMirror.prototype.context = function() {
2051
  return this.context_;
2052
};
2053

    
2054

    
2055
ScriptMirror.prototype.evalFromScript = function() {
2056
  return MakeMirror(this.script_.eval_from_script);
2057
};
2058

    
2059

    
2060
ScriptMirror.prototype.evalFromFunctionName = function() {
2061
  return MakeMirror(this.script_.eval_from_function_name);
2062
};
2063

    
2064

    
2065
ScriptMirror.prototype.evalFromLocation = function() {
2066
  var eval_from_script = this.evalFromScript();
2067
  if (!eval_from_script.isUndefined()) {
2068
    var position = this.script_.eval_from_script_position;
2069
    return eval_from_script.locationFromPosition(position, true);
2070
  }
2071
};
2072

    
2073

    
2074
ScriptMirror.prototype.toText = function() {
2075
  var result = '';
2076
  result += this.name();
2077
  result += ' (lines: ';
2078
  if (this.lineOffset() > 0) {
2079
    result += this.lineOffset();
2080
    result += '-';
2081
    result += this.lineOffset() + this.lineCount() - 1;
2082
  } else {
2083
    result += this.lineCount();
2084
  }
2085
  result += ')';
2086
  return result;
2087
};
2088

    
2089

    
2090
/**
2091
 * Mirror object for context.
2092
 * @param {Object} data The context data
2093
 * @constructor
2094
 * @extends Mirror
2095
 */
2096
function ContextMirror(data) {
2097
  %_CallFunction(this, CONTEXT_TYPE, Mirror);
2098
  this.data_ = data;
2099
  this.allocateHandle_();
2100
}
2101
inherits(ContextMirror, Mirror);
2102

    
2103

    
2104
ContextMirror.prototype.data = function() {
2105
  return this.data_;
2106
};
2107

    
2108

    
2109
/**
2110
 * Returns a mirror serializer
2111
 *
2112
 * @param {boolean} details Set to true to include details
2113
 * @param {Object} options Options comtrolling the serialization
2114
 *     The following options can be set:
2115
 *       includeSource: include ths full source of scripts
2116
 * @returns {MirrorSerializer} mirror serializer
2117
 */
2118
function MakeMirrorSerializer(details, options) {
2119
  return new JSONProtocolSerializer(details, options);
2120
}
2121

    
2122

    
2123
/**
2124
 * Object for serializing a mirror objects and its direct references.
2125
 * @param {boolean} details Indicates whether to include details for the mirror
2126
 *     serialized
2127
 * @constructor
2128
 */
2129
function JSONProtocolSerializer(details, options) {
2130
  this.details_ = details;
2131
  this.options_ = options;
2132
  this.mirrors_ = [ ];
2133
}
2134

    
2135

    
2136
/**
2137
 * Returns a serialization of an object reference. The referenced object are
2138
 * added to the serialization state.
2139
 *
2140
 * @param {Mirror} mirror The mirror to serialize
2141
 * @returns {String} JSON serialization
2142
 */
2143
JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
2144
  return this.serialize_(mirror, true, true);
2145
};
2146

    
2147

    
2148
/**
2149
 * Returns a serialization of an object value. The referenced objects are
2150
 * added to the serialization state.
2151
 *
2152
 * @param {Mirror} mirror The mirror to serialize
2153
 * @returns {String} JSON serialization
2154
 */
2155
JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
2156
  var json = this.serialize_(mirror, false, true);
2157
  return json;
2158
};
2159

    
2160

    
2161
/**
2162
 * Returns a serialization of all the objects referenced.
2163
 *
2164
 * @param {Mirror} mirror The mirror to serialize.
2165
 * @returns {Array.<Object>} Array of the referenced objects converted to
2166
 *     protcol objects.
2167
 */
2168
JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
2169
  // Collect the protocol representation of the referenced objects in an array.
2170
  var content = [];
2171

    
2172
  // Get the number of referenced objects.
2173
  var count = this.mirrors_.length;
2174

    
2175
  for (var i = 0; i < count; i++) {
2176
    content.push(this.serialize_(this.mirrors_[i], false, false));
2177
  }
2178

    
2179
  return content;
2180
};
2181

    
2182

    
2183
JSONProtocolSerializer.prototype.includeSource_ = function() {
2184
  return this.options_ && this.options_.includeSource;
2185
};
2186

    
2187

    
2188
JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2189
  return this.options_ && this.options_.inlineRefs;
2190
};
2191

    
2192

    
2193
JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2194
  if (IS_UNDEFINED(this.options_) ||
2195
      IS_UNDEFINED(this.options_.maxStringLength)) {
2196
    return kMaxProtocolStringLength;
2197
  }
2198
  return this.options_.maxStringLength;
2199
};
2200

    
2201

    
2202
JSONProtocolSerializer.prototype.add_ = function(mirror) {
2203
  // If this mirror is already in the list just return.
2204
  for (var i = 0; i < this.mirrors_.length; i++) {
2205
    if (this.mirrors_[i] === mirror) {
2206
      return;
2207
    }
2208
  }
2209

    
2210
  // Add the mirror to the list of mirrors to be serialized.
2211
  this.mirrors_.push(mirror);
2212
};
2213

    
2214

    
2215
/**
2216
 * Formats mirror object to protocol reference object with some data that can
2217
 * be used to display the value in debugger.
2218
 * @param {Mirror} mirror Mirror to serialize.
2219
 * @return {Object} Protocol reference object.
2220
 */
2221
JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
2222
    function(mirror) {
2223
  var o = {};
2224
  o.ref = mirror.handle();
2225
  o.type = mirror.type();
2226
  switch (mirror.type()) {
2227
    case UNDEFINED_TYPE:
2228
    case NULL_TYPE:
2229
    case BOOLEAN_TYPE:
2230
    case NUMBER_TYPE:
2231
      o.value = mirror.value();
2232
      break;
2233
    case STRING_TYPE:
2234
      o.value = mirror.getTruncatedValue(this.maxStringLength_());
2235
      break;
2236
    case FUNCTION_TYPE:
2237
      o.name = mirror.name();
2238
      o.inferredName = mirror.inferredName();
2239
      if (mirror.script()) {
2240
        o.scriptId = mirror.script().id();
2241
      }
2242
      break;
2243
    case ERROR_TYPE:
2244
    case REGEXP_TYPE:
2245
      o.value = mirror.toText();
2246
      break;
2247
    case OBJECT_TYPE:
2248
      o.className = mirror.className();
2249
      break;
2250
  }
2251
  return o;
2252
};
2253

    
2254

    
2255
JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2256
                                                       details) {
2257
  // If serializing a reference to a mirror just return the reference and add
2258
  // the mirror to the referenced mirrors.
2259
  if (reference &&
2260
      (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
2261
    if (this.inlineRefs_() && mirror.isValue()) {
2262
      return this.serializeReferenceWithDisplayData_(mirror);
2263
    } else {
2264
      this.add_(mirror);
2265
      return {'ref' : mirror.handle()};
2266
    }
2267
  }
2268

    
2269
  // Collect the JSON property/value pairs.
2270
  var content = {};
2271

    
2272
  // Add the mirror handle.
2273
  if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
2274
    content.handle = mirror.handle();
2275
  }
2276

    
2277
  // Always add the type.
2278
  content.type = mirror.type();
2279

    
2280
  switch (mirror.type()) {
2281
    case UNDEFINED_TYPE:
2282
    case NULL_TYPE:
2283
      // Undefined and null are represented just by their type.
2284
      break;
2285

    
2286
    case BOOLEAN_TYPE:
2287
      // Boolean values are simply represented by their value.
2288
      content.value = mirror.value();
2289
      break;
2290

    
2291
    case NUMBER_TYPE:
2292
      // Number values are simply represented by their value.
2293
      content.value = NumberToJSON_(mirror.value());
2294
      break;
2295

    
2296
    case STRING_TYPE:
2297
      // String values might have their value cropped to keep down size.
2298
      if (this.maxStringLength_() != -1 &&
2299
          mirror.length() > this.maxStringLength_()) {
2300
        var str = mirror.getTruncatedValue(this.maxStringLength_());
2301
        content.value = str;
2302
        content.fromIndex = 0;
2303
        content.toIndex = this.maxStringLength_();
2304
      } else {
2305
        content.value = mirror.value();
2306
      }
2307
      content.length = mirror.length();
2308
      break;
2309

    
2310
    case OBJECT_TYPE:
2311
    case FUNCTION_TYPE:
2312
    case ERROR_TYPE:
2313
    case REGEXP_TYPE:
2314
      // Add object representation.
2315
      this.serializeObject_(mirror, content, details);
2316
      break;
2317

    
2318
    case PROPERTY_TYPE:
2319
    case INTERNAL_PROPERTY_TYPE:
2320
      throw new Error('PropertyMirror cannot be serialized independently');
2321
      break;
2322

    
2323
    case FRAME_TYPE:
2324
      // Add object representation.
2325
      this.serializeFrame_(mirror, content);
2326
      break;
2327

    
2328
    case SCOPE_TYPE:
2329
      // Add object representation.
2330
      this.serializeScope_(mirror, content);
2331
      break;
2332

    
2333
    case SCRIPT_TYPE:
2334
      // Script is represented by id, name and source attributes.
2335
      if (mirror.name()) {
2336
        content.name = mirror.name();
2337
      }
2338
      content.id = mirror.id();
2339
      content.lineOffset = mirror.lineOffset();
2340
      content.columnOffset = mirror.columnOffset();
2341
      content.lineCount = mirror.lineCount();
2342
      if (mirror.data()) {
2343
        content.data = mirror.data();
2344
      }
2345
      if (this.includeSource_()) {
2346
        content.source = mirror.source();
2347
      } else {
2348
        var sourceStart = mirror.source().substring(0, 80);
2349
        content.sourceStart = sourceStart;
2350
      }
2351
      content.sourceLength = mirror.source().length;
2352
      content.scriptType = mirror.scriptType();
2353
      content.compilationType = mirror.compilationType();
2354
      // For compilation type eval emit information on the script from which
2355
      // eval was called if a script is present.
2356
      if (mirror.compilationType() == 1 &&
2357
          mirror.evalFromScript()) {
2358
        content.evalFromScript =
2359
            this.serializeReference(mirror.evalFromScript());
2360
        var evalFromLocation = mirror.evalFromLocation();
2361
        if (evalFromLocation) {
2362
          content.evalFromLocation = { line: evalFromLocation.line,
2363
                                       column: evalFromLocation.column };
2364
        }
2365
        if (mirror.evalFromFunctionName()) {
2366
          content.evalFromFunctionName = mirror.evalFromFunctionName();
2367
        }
2368
      }
2369
      if (mirror.context()) {
2370
        content.context = this.serializeReference(mirror.context());
2371
      }
2372
      break;
2373

    
2374
    case CONTEXT_TYPE:
2375
      content.data = mirror.data();
2376
      break;
2377
  }
2378

    
2379
  // Always add the text representation.
2380
  content.text = mirror.toText();
2381

    
2382
  // Create and return the JSON string.
2383
  return content;
2384
};
2385

    
2386

    
2387
/**
2388
 * Serialize object information to the following JSON format.
2389
 *
2390
 *   {"className":"<class name>",
2391
 *    "constructorFunction":{"ref":<number>},
2392
 *    "protoObject":{"ref":<number>},
2393
 *    "prototypeObject":{"ref":<number>},
2394
 *    "namedInterceptor":<boolean>,
2395
 *    "indexedInterceptor":<boolean>,
2396
 *    "properties":[<properties>],
2397
 *    "internalProperties":[<internal properties>]}
2398
 */
2399
JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2400
                                                             details) {
2401
  // Add general object properties.
2402
  content.className = mirror.className();
2403
  content.constructorFunction =
2404
      this.serializeReference(mirror.constructorFunction());
2405
  content.protoObject = this.serializeReference(mirror.protoObject());
2406
  content.prototypeObject = this.serializeReference(mirror.prototypeObject());
2407

    
2408
  // Add flags to indicate whether there are interceptors.
2409
  if (mirror.hasNamedInterceptor()) {
2410
    content.namedInterceptor = true;
2411
  }
2412
  if (mirror.hasIndexedInterceptor()) {
2413
    content.indexedInterceptor = true;
2414
  }
2415

    
2416
  // Add function specific properties.
2417
  if (mirror.isFunction()) {
2418
    // Add function specific properties.
2419
    content.name = mirror.name();
2420
    if (!IS_UNDEFINED(mirror.inferredName())) {
2421
      content.inferredName = mirror.inferredName();
2422
    }
2423
    content.resolved = mirror.resolved();
2424
    if (mirror.resolved()) {
2425
      content.source = mirror.source();
2426
    }
2427
    if (mirror.script()) {
2428
      content.script = this.serializeReference(mirror.script());
2429
      content.scriptId = mirror.script().id();
2430

    
2431
      serializeLocationFields(mirror.sourceLocation(), content);
2432
    }
2433

    
2434
    content.scopes = [];
2435
    for (var i = 0; i < mirror.scopeCount(); i++) {
2436
      var scope = mirror.scope(i);
2437
      content.scopes.push({
2438
        type: scope.scopeType(),
2439
        index: i
2440
      });
2441
    }
2442
  }
2443

    
2444
  // Add date specific properties.
2445
  if (mirror.isDate()) {
2446
    // Add date specific properties.
2447
    content.value = mirror.value();
2448
  }
2449

    
2450
  // Add actual properties - named properties followed by indexed properties.
2451
  var propertyNames = mirror.propertyNames(PropertyKind.Named);
2452
  var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2453
  var p = new Array(propertyNames.length + propertyIndexes.length);
2454
  for (var i = 0; i < propertyNames.length; i++) {
2455
    var propertyMirror = mirror.property(propertyNames[i]);
2456
    p[i] = this.serializeProperty_(propertyMirror);
2457
    if (details) {
2458
      this.add_(propertyMirror.value());
2459
    }
2460
  }
2461
  for (var i = 0; i < propertyIndexes.length; i++) {
2462
    var propertyMirror = mirror.property(propertyIndexes[i]);
2463
    p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
2464
    if (details) {
2465
      this.add_(propertyMirror.value());
2466
    }
2467
  }
2468
  content.properties = p;
2469

    
2470
  var internalProperties = mirror.internalProperties();
2471
  if (internalProperties.length > 0) {
2472
    var ip = [];
2473
    for (var i = 0; i < internalProperties.length; i++) {
2474
      ip.push(this.serializeInternalProperty_(internalProperties[i]));
2475
    }
2476
    content.internalProperties = ip;
2477
  }
2478
};
2479

    
2480

    
2481
/**
2482
 * Serialize location information to the following JSON format:
2483
 *
2484
 *   "position":"<position>",
2485
 *   "line":"<line>",
2486
 *   "column":"<column>",
2487
 *
2488
 * @param {SourceLocation} location The location to serialize, may be undefined.
2489
 */
2490
function serializeLocationFields (location, content) {
2491
  if (!location) {
2492
    return;
2493
  }
2494
  content.position = location.position;
2495
  var line = location.line;
2496
  if (!IS_UNDEFINED(line)) {
2497
    content.line = line;
2498
  }
2499
  var column = location.column;
2500
  if (!IS_UNDEFINED(column)) {
2501
    content.column = column;
2502
  }
2503
}
2504

    
2505

    
2506
/**
2507
 * Serialize property information to the following JSON format for building the
2508
 * array of properties.
2509
 *
2510
 *   {"name":"<property name>",
2511
 *    "attributes":<number>,
2512
 *    "propertyType":<number>,
2513
 *    "ref":<number>}
2514
 *
2515
 * If the attribute for the property is PropertyAttribute.None it is not added.
2516
 * If the propertyType for the property is PropertyType.Normal it is not added.
2517
 * Here are a couple of examples.
2518
 *
2519
 *   {"name":"hello","ref":1}
2520
 *   {"name":"length","attributes":7,"propertyType":3,"ref":2}
2521
 *
2522
 * @param {PropertyMirror} propertyMirror The property to serialize.
2523
 * @returns {Object} Protocol object representing the property.
2524
 */
2525
JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2526
  var result = {};
2527

    
2528
  result.name = propertyMirror.name();
2529
  var propertyValue = propertyMirror.value();
2530
  if (this.inlineRefs_() && propertyValue.isValue()) {
2531
    result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2532
  } else {
2533
    if (propertyMirror.attributes() != PropertyAttribute.None) {
2534
      result.attributes = propertyMirror.attributes();
2535
    }
2536
    if (propertyMirror.propertyType() != PropertyType.Normal) {
2537
      result.propertyType = propertyMirror.propertyType();
2538
    }
2539
    result.ref = propertyValue.handle();
2540
  }
2541
  return result;
2542
};
2543

    
2544

    
2545
/**
2546
 * Serialize internal property information to the following JSON format for
2547
 * building the array of properties.
2548
 *
2549
 *   {"name":"<property name>",
2550
 *    "ref":<number>}
2551
 *
2552
 *   {"name":"[[BoundThis]]","ref":117}
2553
 *
2554
 * @param {InternalPropertyMirror} propertyMirror The property to serialize.
2555
 * @returns {Object} Protocol object representing the property.
2556
 */
2557
JSONProtocolSerializer.prototype.serializeInternalProperty_ =
2558
    function(propertyMirror) {
2559
  var result = {};
2560

    
2561
  result.name = propertyMirror.name();
2562
  var propertyValue = propertyMirror.value();
2563
  if (this.inlineRefs_() && propertyValue.isValue()) {
2564
    result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2565
  } else {
2566
    result.ref = propertyValue.handle();
2567
  }
2568
  return result;
2569
};
2570

    
2571

    
2572
JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
2573
  content.index = mirror.index();
2574
  content.receiver = this.serializeReference(mirror.receiver());
2575
  var func = mirror.func();
2576
  content.func = this.serializeReference(func);
2577
  if (func.script()) {
2578
    content.script = this.serializeReference(func.script());
2579
  }
2580
  content.constructCall = mirror.isConstructCall();
2581
  content.atReturn = mirror.isAtReturn();
2582
  if (mirror.isAtReturn()) {
2583
    content.returnValue = this.serializeReference(mirror.returnValue());
2584
  }
2585
  content.debuggerFrame = mirror.isDebuggerFrame();
2586
  var x = new Array(mirror.argumentCount());
2587
  for (var i = 0; i < mirror.argumentCount(); i++) {
2588
    var arg = {};
2589
    var argument_name = mirror.argumentName(i);
2590
    if (argument_name) {
2591
      arg.name = argument_name;
2592
    }
2593
    arg.value = this.serializeReference(mirror.argumentValue(i));
2594
    x[i] = arg;
2595
  }
2596
  content.arguments = x;
2597
  var x = new Array(mirror.localCount());
2598
  for (var i = 0; i < mirror.localCount(); i++) {
2599
    var local = {};
2600
    local.name = mirror.localName(i);
2601
    local.value = this.serializeReference(mirror.localValue(i));
2602
    x[i] = local;
2603
  }
2604
  content.locals = x;
2605
  serializeLocationFields(mirror.sourceLocation(), content);
2606
  var source_line_text = mirror.sourceLineText();
2607
  if (!IS_UNDEFINED(source_line_text)) {
2608
    content.sourceLineText = source_line_text;
2609
  }
2610

    
2611
  content.scopes = [];
2612
  for (var i = 0; i < mirror.scopeCount(); i++) {
2613
    var scope = mirror.scope(i);
2614
    content.scopes.push({
2615
      type: scope.scopeType(),
2616
      index: i
2617
    });
2618
  }
2619
};
2620

    
2621

    
2622
JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2623
  content.index = mirror.scopeIndex();
2624
  content.frameIndex = mirror.frameIndex();
2625
  content.type = mirror.scopeType();
2626
  content.object = this.inlineRefs_() ?
2627
                   this.serializeValue(mirror.scopeObject()) :
2628
                   this.serializeReference(mirror.scopeObject());
2629
};
2630

    
2631

    
2632
/**
2633
 * Convert a number to a protocol value. For all finite numbers the number
2634
 * itself is returned. For non finite numbers NaN, Infinite and
2635
 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
2636
 * (not including the quotes) is returned.
2637
 *
2638
 * @param {number} value The number value to convert to a protocol value.
2639
 * @returns {number|string} Protocol value.
2640
 */
2641
function NumberToJSON_(value) {
2642
  if (isNaN(value)) {
2643
    return 'NaN';
2644
  }
2645
  if (!NUMBER_IS_FINITE(value)) {
2646
    if (value > 0) {
2647
      return 'Infinity';
2648
    } else {
2649
      return '-Infinity';
2650
    }
2651
  }
2652
  return value;
2653
}