blob: e3f3c48bb55fd26aaba54c08e787fa5355e21938 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
ager@chromium.orgeadaf222009-06-16 09:43:10 +000028// Handle id counters.
ager@chromium.org32912102009-01-16 10:38:43 +000029var next_handle_ = 0;
ager@chromium.orgeadaf222009-06-16 09:43:10 +000030var next_transient_handle_ = -1;
31
32// Mirror cache.
ager@chromium.org32912102009-01-16 10:38:43 +000033var mirror_cache_ = [];
34
ager@chromium.orgeadaf222009-06-16 09:43:10 +000035
ager@chromium.org32912102009-01-16 10:38:43 +000036/**
37 * Clear the mirror handle cache.
38 */
39function ClearMirrorCache() {
40 next_handle_ = 0;
41 mirror_cache_ = [];
42}
43
44
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +000045/**
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
ager@chromium.orgeadaf222009-06-16 09:43:10 +000049 * @param {boolean} transient indicate whether this object is transient and
50 * should not be added to the mirror cache. The default is not transient.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +000051 * @returns {Mirror} the mirror reflects the passed value or object
52 */
ager@chromium.orgeadaf222009-06-16 09:43:10 +000053function MakeMirror(value, opt_transient) {
ager@chromium.org32912102009-01-16 10:38:43 +000054 var mirror;
ager@chromium.orgeadaf222009-06-16 09:43:10 +000055
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 }
ager@chromium.orgddb913d2009-01-27 10:01:48 +000068 }
ager@chromium.org32912102009-01-16 10:38:43 +000069 }
lrn@chromium.org25156de2010-04-06 13:10:27 +000070
ager@chromium.org32912102009-01-16 10:38:43 +000071 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);
iposva@chromium.org245aa852009-02-10 00:49:54 +000091 } else if (IS_SCRIPT(value)) {
92 mirror = new ScriptMirror(value);
ager@chromium.org32912102009-01-16 10:38:43 +000093 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +000094 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient);
ager@chromium.org32912102009-01-16 10:38:43 +000095 }
96
97 mirror_cache_[mirror.handle()] = mirror;
98 return mirror;
99}
100
101
102/**
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000103 * 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 */
109function LookupMirror(handle) {
110 return mirror_cache_[handle];
111}
112
lrn@chromium.org25156de2010-04-06 13:10:27 +0000113
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000114/**
ager@chromium.org32912102009-01-16 10:38:43 +0000115 * Returns the mirror for the undefined value.
116 *
117 * @returns {Mirror} the mirror reflects the undefined value
118 */
119function GetUndefinedMirror() {
120 return MakeMirror(void 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121}
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 */
137function 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.
147const UNDEFINED_TYPE = 'undefined';
148const NULL_TYPE = 'null';
149const BOOLEAN_TYPE = 'boolean';
150const NUMBER_TYPE = 'number';
151const STRING_TYPE = 'string';
152const OBJECT_TYPE = 'object';
153const FUNCTION_TYPE = 'function';
154const REGEXP_TYPE = 'regexp';
155const ERROR_TYPE = 'error';
156const PROPERTY_TYPE = 'property';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157const FRAME_TYPE = 'frame';
158const SCRIPT_TYPE = 'script';
ager@chromium.org9085a012009-05-11 19:22:57 +0000159const CONTEXT_TYPE = 'context';
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000160const SCOPE_TYPE = 'scope';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161
162// Maximum length when sending strings through the JSON protocol.
163const kMaxProtocolStringLength = 80;
164
165// Different kind of properties.
166PropertyKind = {};
167PropertyKind.Named = 1;
168PropertyKind.Indexed = 2;
169
170
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000171// A copy of the PropertyType enum from global.h
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172PropertyType = {};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000173PropertyType.Normal = 0;
174PropertyType.Field = 1;
175PropertyType.ConstantFunction = 2;
176PropertyType.Callbacks = 3;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000177PropertyType.Handler = 4;
178PropertyType.Interceptor = 5;
179PropertyType.MapTransition = 6;
180PropertyType.ExternalArrayTransition = 7;
181PropertyType.ConstantTransition = 8;
182PropertyType.NullDescriptor = 9;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000183
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185// Different attributes for a property.
186PropertyAttribute = {};
187PropertyAttribute.None = NONE;
188PropertyAttribute.ReadOnly = READ_ONLY;
189PropertyAttribute.DontEnum = DONT_ENUM;
190PropertyAttribute.DontDelete = DONT_DELETE;
191
192
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000193// A copy of the scope types from runtime.cc.
194ScopeType = { Global: 0,
195 Local: 1,
196 With: 2,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000197 Closure: 3,
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000198 Catch: 4,
199 Block: 5 };
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000200
201
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202// Mirror hierarchy:
203// - Mirror
204// - ValueMirror
205// - UndefinedMirror
206// - NullMirror
207// - NumberMirror
208// - StringMirror
209// - ObjectMirror
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000210// - FunctionMirror
211// - UnresolvedFunctionMirror
212// - ArrayMirror
213// - DateMirror
214// - RegExpMirror
215// - ErrorMirror
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216// - PropertyMirror
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217// - 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 */
226function Mirror(type) {
227 this.type_ = type;
228};
229
230
231Mirror.prototype.type = function() {
232 return this.type_;
233};
234
235
236/**
ager@chromium.org32912102009-01-16 10:38:43 +0000237 * Check whether the mirror reflects a value.
238 * @returns {boolean} True if the mirror reflects a value.
239 */
240Mirror.prototype.isValue = function() {
241 return this instanceof ValueMirror;
242}
243
244
245/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000246 * Check whether the mirror reflects the undefined value.
247 * @returns {boolean} True if the mirror reflects the undefined value.
248 */
249Mirror.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 */
258Mirror.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 */
267Mirror.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 */
276Mirror.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 */
285Mirror.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 */
294Mirror.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 */
303Mirror.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 */
312Mirror.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 */
321Mirror.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 */
330Mirror.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 */
339Mirror.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 */
348Mirror.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 */
357Mirror.prototype.isProperty = function() {
358 return this instanceof PropertyMirror;
359}
360
361
362/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000363 * Check whether the mirror reflects a stack frame.
364 * @returns {boolean} True if the mirror reflects a stack frame
365 */
366Mirror.prototype.isFrame = function() {
367 return this instanceof FrameMirror;
368}
369
370
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000371/**
372 * Check whether the mirror reflects a script.
373 * @returns {boolean} True if the mirror reflects a script
374 */
375Mirror.prototype.isScript = function() {
376 return this instanceof ScriptMirror;
377}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378
379
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000380/**
ager@chromium.org9085a012009-05-11 19:22:57 +0000381 * Check whether the mirror reflects a context.
382 * @returns {boolean} True if the mirror reflects a context
383 */
384Mirror.prototype.isContext = function() {
385 return this instanceof ContextMirror;
386}
387
388
389/**
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000390 * Check whether the mirror reflects a scope.
391 * @returns {boolean} True if the mirror reflects a scope
392 */
393Mirror.prototype.isScope = function() {
394 return this instanceof ScopeMirror;
395}
396
397
398/**
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000399 * Allocate a handle id for this object.
400 */
401Mirror.prototype.allocateHandle_ = function() {
402 this.handle_ = next_handle_++;
403}
404
405
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000406/**
407 * Allocate a transient handle id for this object. Transient handles are
408 * negative.
409 */
410Mirror.prototype.allocateTransientHandle_ = function() {
411 this.handle_ = next_transient_handle_--;
412}
413
414
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415Mirror.prototype.toText = function() {
416 // Simpel to text which is used when on specialization in subclass.
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000417 return "#<" + this.constructor.name + ">";
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418}
419
420
421/**
422 * Base class for all value mirror objects.
423 * @param {string} type The type of the mirror
424 * @param {value} value The value reflected by this mirror
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000425 * @param {boolean} transient indicate whether this object is transient with a
426 * transient handle
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 * @constructor
428 * @extends Mirror
429 */
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000430function ValueMirror(type, value, transient) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000431 %_CallFunction(this, type, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 this.value_ = value;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000433 if (!transient) {
434 this.allocateHandle_();
435 } else {
436 this.allocateTransientHandle_();
437 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000438}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000439inherits(ValueMirror, Mirror);
440
441
ager@chromium.org32912102009-01-16 10:38:43 +0000442Mirror.prototype.handle = function() {
443 return this.handle_;
444};
445
446
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447/**
448 * Check whether this is a primitive value.
449 * @return {boolean} True if the mirror reflects a primitive value
450 */
451ValueMirror.prototype.isPrimitive = function() {
452 var type = this.type();
453 return type === 'undefined' ||
454 type === 'null' ||
455 type === 'boolean' ||
456 type === 'number' ||
457 type === 'string';
458};
459
460
ager@chromium.org32912102009-01-16 10:38:43 +0000461/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462 * Get the actual value reflected by this mirror.
463 * @return {value} The value reflected by this mirror
464 */
465ValueMirror.prototype.value = function() {
466 return this.value_;
467};
468
469
470/**
471 * Mirror object for Undefined.
472 * @constructor
473 * @extends ValueMirror
474 */
475function UndefinedMirror() {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000476 %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000477}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000478inherits(UndefinedMirror, ValueMirror);
479
480
481UndefinedMirror.prototype.toText = function() {
482 return 'undefined';
483}
484
485
486/**
487 * Mirror object for null.
488 * @constructor
489 * @extends ValueMirror
490 */
491function NullMirror() {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000492 %_CallFunction(this, NULL_TYPE, null, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000493}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000494inherits(NullMirror, ValueMirror);
495
496
497NullMirror.prototype.toText = function() {
498 return 'null';
499}
500
501
502/**
503 * Mirror object for boolean values.
504 * @param {boolean} value The boolean value reflected by this mirror
505 * @constructor
506 * @extends ValueMirror
507 */
508function BooleanMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000509 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000510}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511inherits(BooleanMirror, ValueMirror);
512
513
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514BooleanMirror.prototype.toText = function() {
515 return this.value_ ? 'true' : 'false';
516}
517
518
519/**
520 * Mirror object for number values.
521 * @param {number} value The number value reflected by this mirror
522 * @constructor
523 * @extends ValueMirror
524 */
525function NumberMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000526 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000527}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528inherits(NumberMirror, ValueMirror);
529
530
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531NumberMirror.prototype.toText = function() {
532 return %NumberToString(this.value_);
533}
534
535
536/**
537 * Mirror object for string values.
538 * @param {string} value The string value reflected by this mirror
539 * @constructor
540 * @extends ValueMirror
541 */
542function StringMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000543 %_CallFunction(this, STRING_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000544}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545inherits(StringMirror, ValueMirror);
546
547
548StringMirror.prototype.length = function() {
549 return this.value_.length;
550};
551
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000552StringMirror.prototype.getTruncatedValue = function(maxLength) {
553 if (maxLength != -1 && this.length() > maxLength) {
554 return this.value_.substring(0, maxLength) +
555 '... (length: ' + this.length() + ')';
556 }
557 return this.value_;
558}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560StringMirror.prototype.toText = function() {
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000561 return this.getTruncatedValue(kMaxProtocolStringLength);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562}
563
564
565/**
566 * Mirror object for objects.
567 * @param {object} value The object reflected by this mirror
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000568 * @param {boolean} transient indicate whether this object is transient with a
569 * transient handle
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570 * @constructor
571 * @extends ValueMirror
572 */
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000573function ObjectMirror(value, type, transient) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000574 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000575}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576inherits(ObjectMirror, ValueMirror);
577
578
579ObjectMirror.prototype.className = function() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000580 return %_ClassOf(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581};
582
583
584ObjectMirror.prototype.constructorFunction = function() {
585 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
586};
587
588
589ObjectMirror.prototype.prototypeObject = function() {
590 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
591};
592
593
594ObjectMirror.prototype.protoObject = function() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000595 return MakeMirror(%DebugGetPrototype(this.value_));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596};
597
598
599ObjectMirror.prototype.hasNamedInterceptor = function() {
600 // Get information on interceptors for this object.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000601 var x = %GetInterceptorInfo(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602 return (x & 2) != 0;
603};
604
605
606ObjectMirror.prototype.hasIndexedInterceptor = function() {
607 // Get information on interceptors for this object.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000608 var x = %GetInterceptorInfo(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609 return (x & 1) != 0;
610};
611
612
613/**
614 * Return the property names for this object.
615 * @param {number} kind Indicate whether named, indexed or both kinds of
616 * properties are requested
617 * @param {number} limit Limit the number of names returend to the specified
618 value
619 * @return {Array} Property names for this object
620 */
621ObjectMirror.prototype.propertyNames = function(kind, limit) {
622 // Find kind and limit and allocate array for the result
623 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
624
625 var propertyNames;
626 var elementNames;
627 var total = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000628
ager@chromium.org32912102009-01-16 10:38:43 +0000629 // Find all the named properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 if (kind & PropertyKind.Named) {
ager@chromium.org32912102009-01-16 10:38:43 +0000631 // Get the local property names.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000632 propertyNames = %GetLocalPropertyNames(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000633 total += propertyNames.length;
ager@chromium.org32912102009-01-16 10:38:43 +0000634
635 // Get names for named interceptor properties if any.
636 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
637 var namedInterceptorNames =
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000638 %GetNamedInterceptorPropertyNames(this.value_);
ager@chromium.org32912102009-01-16 10:38:43 +0000639 if (namedInterceptorNames) {
640 propertyNames = propertyNames.concat(namedInterceptorNames);
641 total += namedInterceptorNames.length;
642 }
643 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644 }
ager@chromium.org32912102009-01-16 10:38:43 +0000645
646 // Find all the indexed properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 if (kind & PropertyKind.Indexed) {
ager@chromium.org32912102009-01-16 10:38:43 +0000648 // Get the local element names.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000649 elementNames = %GetLocalElementNames(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650 total += elementNames.length;
ager@chromium.org32912102009-01-16 10:38:43 +0000651
652 // Get names for indexed interceptor properties.
653 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
654 var indexedInterceptorNames =
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000655 %GetIndexedInterceptorElementNames(this.value_);
ager@chromium.org32912102009-01-16 10:38:43 +0000656 if (indexedInterceptorNames) {
657 elementNames = elementNames.concat(indexedInterceptorNames);
658 total += indexedInterceptorNames.length;
659 }
660 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000661 }
662 limit = Math.min(limit || total, total);
663
664 var names = new Array(limit);
665 var index = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000666
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667 // Copy names for named properties.
668 if (kind & PropertyKind.Named) {
669 for (var i = 0; index < limit && i < propertyNames.length; i++) {
670 names[index++] = propertyNames[i];
671 }
672 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000673
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 // Copy names for indexed properties.
675 if (kind & PropertyKind.Indexed) {
676 for (var i = 0; index < limit && i < elementNames.length; i++) {
677 names[index++] = elementNames[i];
678 }
679 }
680
681 return names;
682};
683
684
685/**
686 * Return the properties for this object as an array of PropertyMirror objects.
687 * @param {number} kind Indicate whether named, indexed or both kinds of
688 * properties are requested
689 * @param {number} limit Limit the number of properties returend to the
690 specified value
691 * @return {Array} Property mirrors for this object
692 */
693ObjectMirror.prototype.properties = function(kind, limit) {
694 var names = this.propertyNames(kind, limit);
695 var properties = new Array(names.length);
696 for (var i = 0; i < names.length; i++) {
697 properties[i] = this.property(names[i]);
698 }
699
700 return properties;
701};
702
703
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000704ObjectMirror.prototype.property = function(name) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000705 var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000706 if (details) {
ager@chromium.org32912102009-01-16 10:38:43 +0000707 return new PropertyMirror(this, name, details);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708 }
709
710 // Nothing found.
ager@chromium.org32912102009-01-16 10:38:43 +0000711 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712};
713
714
715
716/**
717 * Try to find a property from its value.
718 * @param {Mirror} value The property value to look for
719 * @return {PropertyMirror} The property with the specified value. If no
720 * property was found with the specified value UndefinedMirror is returned
721 */
722ObjectMirror.prototype.lookupProperty = function(value) {
723 var properties = this.properties();
724
725 // Look for property value in properties.
726 for (var i = 0; i < properties.length; i++) {
727
728 // Skip properties which are defined through assessors.
729 var property = properties[i];
730 if (property.propertyType() != PropertyType.Callbacks) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000731 if (%_ObjectEquals(property.value_, value.value_)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732 return property;
733 }
734 }
735 }
736
737 // Nothing found.
ager@chromium.org32912102009-01-16 10:38:43 +0000738 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739};
740
741
742/**
743 * Returns objects which has direct references to this object
iposva@chromium.org245aa852009-02-10 00:49:54 +0000744 * @param {number} opt_max_objects Optional parameter specifying the maximum
745 * number of referencing objects to return.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000746 * @return {Array} The objects which has direct references to this object.
747 */
iposva@chromium.org245aa852009-02-10 00:49:54 +0000748ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
749 // Find all objects with direct references to this object.
750 var result = %DebugReferencedBy(this.value_,
751 Mirror.prototype, opt_max_objects || 0);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000752
iposva@chromium.org245aa852009-02-10 00:49:54 +0000753 // Make mirrors for all the references found.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000754 for (var i = 0; i < result.length; i++) {
755 result[i] = MakeMirror(result[i]);
756 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000757
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000758 return result;
759};
760
761
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762ObjectMirror.prototype.toText = function() {
763 var name;
764 var ctor = this.constructorFunction();
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000765 if (!ctor.isFunction()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000766 name = this.className();
767 } else {
768 name = ctor.name();
769 if (!name) {
770 name = this.className();
771 }
772 }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000773 return '#<' + name + '>';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000774};
775
776
777/**
778 * Mirror object for functions.
779 * @param {function} value The function object reflected by this mirror.
780 * @constructor
781 * @extends ObjectMirror
782 */
783function FunctionMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000784 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785 this.resolved_ = true;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000786}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787inherits(FunctionMirror, ObjectMirror);
788
789
790/**
791 * Returns whether the function is resolved.
792 * @return {boolean} True if the function is resolved. Unresolved functions can
793 * only originate as functions from stack frames
794 */
795FunctionMirror.prototype.resolved = function() {
796 return this.resolved_;
797};
798
799
800/**
801 * Returns the name of the function.
802 * @return {string} Name of the function
803 */
804FunctionMirror.prototype.name = function() {
805 return %FunctionGetName(this.value_);
806};
807
808
809/**
ager@chromium.org9085a012009-05-11 19:22:57 +0000810 * Returns the inferred name of the function.
811 * @return {string} Name of the function
812 */
813FunctionMirror.prototype.inferredName = function() {
814 return %FunctionGetInferredName(this.value_);
815};
816
817
818/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000819 * Returns the source code for the function.
820 * @return {string or undefined} The source code for the function. If the
821 * function is not resolved undefined will be returned.
822 */
823FunctionMirror.prototype.source = function() {
824 // Return source if function is resolved. Otherwise just fall through to
825 // return undefined.
826 if (this.resolved()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000827 return builtins.FunctionSourceString(this.value_);
828 }
829};
830
831
832/**
833 * Returns the script object for the function.
834 * @return {ScriptMirror or undefined} Script object for the function or
835 * undefined if the function has no script
836 */
837FunctionMirror.prototype.script = function() {
838 // Return script if function is resolved. Otherwise just fall through
839 // to return undefined.
840 if (this.resolved()) {
841 var script = %FunctionGetScript(this.value_);
842 if (script) {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000843 return MakeMirror(script);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844 }
845 }
846};
847
848
849/**
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000850 * Returns the script source position for the function. Only makes sense
851 * for functions which has a script defined.
852 * @return {Number or undefined} in-script position for the function
853 */
854FunctionMirror.prototype.sourcePosition_ = function() {
855 // Return script if function is resolved. Otherwise just fall through
856 // to return undefined.
857 if (this.resolved()) {
858 return %FunctionGetScriptSourcePosition(this.value_);
859 }
860};
861
862
863/**
864 * Returns the script source location object for the function. Only makes sense
865 * for functions which has a script defined.
866 * @return {Location or undefined} in-script location for the function begin
867 */
868FunctionMirror.prototype.sourceLocation = function() {
869 if (this.resolved() && this.script()) {
870 return this.script().locationFromPosition(this.sourcePosition_(),
871 true);
872 }
873};
874
875
876/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877 * Returns objects constructed by this function.
878 * @param {number} opt_max_instances Optional parameter specifying the maximum
879 * number of instances to return.
880 * @return {Array or undefined} The objects constructed by this function.
881 */
882FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
883 if (this.resolved()) {
884 // Find all objects constructed from this function.
885 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000886
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000887 // Make mirrors for all the instances found.
888 for (var i = 0; i < result.length; i++) {
889 result[i] = MakeMirror(result[i]);
890 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000891
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892 return result;
893 } else {
894 return [];
895 }
896};
897
898
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899FunctionMirror.prototype.toText = function() {
900 return this.source();
901}
902
903
904/**
905 * Mirror object for unresolved functions.
906 * @param {string} value The name for the unresolved function reflected by this
907 * mirror.
908 * @constructor
909 * @extends ObjectMirror
910 */
911function UnresolvedFunctionMirror(value) {
912 // Construct this using the ValueMirror as an unresolved function is not a
913 // real object but just a string.
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000914 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915 this.propertyCount_ = 0;
916 this.elementCount_ = 0;
917 this.resolved_ = false;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000918}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919inherits(UnresolvedFunctionMirror, FunctionMirror);
920
921
922UnresolvedFunctionMirror.prototype.className = function() {
923 return 'Function';
924};
925
926
927UnresolvedFunctionMirror.prototype.constructorFunction = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000928 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000929};
930
931
932UnresolvedFunctionMirror.prototype.prototypeObject = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000933 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000934};
935
936
937UnresolvedFunctionMirror.prototype.protoObject = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000938 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000939};
940
941
942UnresolvedFunctionMirror.prototype.name = function() {
943 return this.value_;
944};
945
946
ager@chromium.org9085a012009-05-11 19:22:57 +0000947UnresolvedFunctionMirror.prototype.inferredName = function() {
948 return undefined;
949};
950
951
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000952UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
953 return [];
954}
955
956
957/**
958 * Mirror object for arrays.
959 * @param {Array} value The Array object reflected by this mirror
960 * @constructor
961 * @extends ObjectMirror
962 */
963function ArrayMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000964 %_CallFunction(this, value, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000965}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000966inherits(ArrayMirror, ObjectMirror);
967
968
969ArrayMirror.prototype.length = function() {
970 return this.value_.length;
971};
972
973
974ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_to_index) {
975 var from_index = opt_from_index || 0;
976 var to_index = opt_to_index || this.length() - 1;
977 if (from_index > to_index) return new Array();
978 var values = new Array(to_index - from_index + 1);
979 for (var i = from_index; i <= to_index; i++) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000980 var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981 var value;
982 if (details) {
ager@chromium.org32912102009-01-16 10:38:43 +0000983 value = new PropertyMirror(this, i, details);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000984 } else {
ager@chromium.org32912102009-01-16 10:38:43 +0000985 value = GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000986 }
987 values[i - from_index] = value;
988 }
989 return values;
990}
991
992
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000993/**
994 * Mirror object for dates.
995 * @param {Date} value The Date object reflected by this mirror
996 * @constructor
997 * @extends ObjectMirror
998 */
999function DateMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001000 %_CallFunction(this, value, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001001}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001002inherits(DateMirror, ObjectMirror);
1003
1004
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001005DateMirror.prototype.toText = function() {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001006 var s = JSON.stringify(this.value_);
1007 return s.substring(1, s.length - 1); // cut quotes
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001008}
1009
1010
1011/**
1012 * Mirror object for regular expressions.
1013 * @param {RegExp} value The RegExp object reflected by this mirror
1014 * @constructor
1015 * @extends ObjectMirror
1016 */
1017function RegExpMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001018 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001019}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001020inherits(RegExpMirror, ObjectMirror);
1021
1022
1023/**
1024 * Returns the source to the regular expression.
1025 * @return {string or undefined} The source to the regular expression
1026 */
1027RegExpMirror.prototype.source = function() {
1028 return this.value_.source;
1029};
1030
1031
1032/**
1033 * Returns whether this regular expression has the global (g) flag set.
1034 * @return {boolean} Value of the global flag
1035 */
1036RegExpMirror.prototype.global = function() {
1037 return this.value_.global;
1038};
1039
1040
1041/**
1042 * Returns whether this regular expression has the ignore case (i) flag set.
1043 * @return {boolean} Value of the ignore case flag
1044 */
1045RegExpMirror.prototype.ignoreCase = function() {
1046 return this.value_.ignoreCase;
1047};
1048
1049
1050/**
1051 * Returns whether this regular expression has the multiline (m) flag set.
1052 * @return {boolean} Value of the multiline flag
1053 */
1054RegExpMirror.prototype.multiline = function() {
1055 return this.value_.multiline;
1056};
1057
1058
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059RegExpMirror.prototype.toText = function() {
1060 // Simpel to text which is used when on specialization in subclass.
1061 return "/" + this.source() + "/";
1062}
1063
1064
1065/**
1066 * Mirror object for error objects.
1067 * @param {Error} value The error object reflected by this mirror
1068 * @constructor
1069 * @extends ObjectMirror
1070 */
1071function ErrorMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001072 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001073}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001074inherits(ErrorMirror, ObjectMirror);
1075
1076
1077/**
1078 * Returns the message for this eror object.
1079 * @return {string or undefined} The message for this eror object
1080 */
1081ErrorMirror.prototype.message = function() {
1082 return this.value_.message;
1083};
1084
1085
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001086ErrorMirror.prototype.toText = function() {
1087 // Use the same text representation as in messages.js.
1088 var text;
1089 try {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001090 str = %_CallFunction(this.value_, builtins.errorToString);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001091 } catch (e) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001092 str = '#<Error>';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001093 }
1094 return str;
1095}
1096
1097
1098/**
1099 * Base mirror object for properties.
1100 * @param {ObjectMirror} mirror The mirror object having this property
1101 * @param {string} name The name of the property
ager@chromium.org32912102009-01-16 10:38:43 +00001102 * @param {Array} details Details about the property
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001103 * @constructor
1104 * @extends Mirror
1105 */
ager@chromium.org32912102009-01-16 10:38:43 +00001106function PropertyMirror(mirror, name, details) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001107 %_CallFunction(this, PROPERTY_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001108 this.mirror_ = mirror;
1109 this.name_ = name;
ager@chromium.org32912102009-01-16 10:38:43 +00001110 this.value_ = details[0];
1111 this.details_ = details[1];
1112 if (details.length > 2) {
1113 this.exception_ = details[2]
1114 this.getter_ = details[3];
1115 this.setter_ = details[4];
1116 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001117}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001118inherits(PropertyMirror, Mirror);
1119
1120
1121PropertyMirror.prototype.isReadOnly = function() {
1122 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1123}
1124
1125
1126PropertyMirror.prototype.isEnum = function() {
1127 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1128}
1129
1130
1131PropertyMirror.prototype.canDelete = function() {
1132 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1133}
1134
1135
1136PropertyMirror.prototype.name = function() {
1137 return this.name_;
1138}
1139
1140
1141PropertyMirror.prototype.isIndexed = function() {
1142 for (var i = 0; i < this.name_.length; i++) {
1143 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1144 return false;
1145 }
1146 }
1147 return true;
1148}
1149
1150
1151PropertyMirror.prototype.value = function() {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001152 return MakeMirror(this.value_, false);
ager@chromium.org32912102009-01-16 10:38:43 +00001153}
1154
1155
1156/**
1157 * Returns whether this property value is an exception.
1158 * @return {booolean} True if this property value is an exception
1159 */
1160PropertyMirror.prototype.isException = function() {
1161 return this.exception_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162}
1163
1164
1165PropertyMirror.prototype.attributes = function() {
1166 return %DebugPropertyAttributesFromDetails(this.details_);
1167}
1168
1169
1170PropertyMirror.prototype.propertyType = function() {
1171 return %DebugPropertyTypeFromDetails(this.details_);
1172}
1173
1174
1175PropertyMirror.prototype.insertionIndex = function() {
1176 return %DebugPropertyIndexFromDetails(this.details_);
1177}
1178
1179
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001180/**
ager@chromium.org32912102009-01-16 10:38:43 +00001181 * Returns whether this property has a getter defined through __defineGetter__.
1182 * @return {booolean} True if this property has a getter
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183 */
ager@chromium.org32912102009-01-16 10:38:43 +00001184PropertyMirror.prototype.hasGetter = function() {
1185 return this.getter_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186}
1187
1188
1189/**
ager@chromium.org32912102009-01-16 10:38:43 +00001190 * Returns whether this property has a setter defined through __defineSetter__.
1191 * @return {booolean} True if this property has a setter
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001192 */
ager@chromium.org32912102009-01-16 10:38:43 +00001193PropertyMirror.prototype.hasSetter = function() {
1194 return this.setter_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001195}
1196
1197
1198/**
ager@chromium.org32912102009-01-16 10:38:43 +00001199 * Returns the getter for this property defined through __defineGetter__.
1200 * @return {Mirror} FunctionMirror reflecting the getter function or
1201 * UndefinedMirror if there is no getter for this property
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001202 */
ager@chromium.org32912102009-01-16 10:38:43 +00001203PropertyMirror.prototype.getter = function() {
1204 if (this.hasGetter()) {
1205 return MakeMirror(this.getter_);
1206 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001207 return GetUndefinedMirror();
ager@chromium.org32912102009-01-16 10:38:43 +00001208 }
1209}
1210
1211
1212/**
1213 * Returns the setter for this property defined through __defineSetter__.
1214 * @return {Mirror} FunctionMirror reflecting the setter function or
1215 * UndefinedMirror if there is no setter for this property
1216 */
1217PropertyMirror.prototype.setter = function() {
1218 if (this.hasSetter()) {
1219 return MakeMirror(this.setter_);
1220 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001221 return GetUndefinedMirror();
ager@chromium.org32912102009-01-16 10:38:43 +00001222 }
1223}
1224
1225
1226/**
1227 * Returns whether this property is natively implemented by the host or a set
1228 * through JavaScript code.
lrn@chromium.org25156de2010-04-06 13:10:27 +00001229 * @return {boolean} True if the property is
ager@chromium.org32912102009-01-16 10:38:43 +00001230 * UndefinedMirror if there is no setter for this property
1231 */
1232PropertyMirror.prototype.isNative = function() {
1233 return (this.propertyType() == PropertyType.Interceptor) ||
1234 ((this.propertyType() == PropertyType.Callbacks) &&
1235 !this.hasGetter() && !this.hasSetter());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001236}
1237
1238
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001239const kFrameDetailsFrameIdIndex = 0;
1240const kFrameDetailsReceiverIndex = 1;
1241const kFrameDetailsFunctionIndex = 2;
1242const kFrameDetailsArgumentCountIndex = 3;
1243const kFrameDetailsLocalCountIndex = 4;
1244const kFrameDetailsSourcePositionIndex = 5;
1245const kFrameDetailsConstructCallIndex = 6;
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001246const kFrameDetailsAtReturnIndex = 7;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001247const kFrameDetailsFlagsIndex = 8;
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001248const kFrameDetailsFirstDynamicIndex = 9;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249
1250const kFrameDetailsNameIndex = 0;
1251const kFrameDetailsValueIndex = 1;
1252const kFrameDetailsNameValueSize = 2;
1253
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001254const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
1255const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
1256const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001257
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001258/**
1259 * Wrapper for the frame details information retreived from the VM. The frame
1260 * details from the VM is an array with the following content. See runtime.cc
1261 * Runtime_GetFrameDetails.
1262 * 0: Id
1263 * 1: Receiver
1264 * 2: Function
1265 * 3: Argument count
1266 * 4: Local count
1267 * 5: Source position
1268 * 6: Construct call
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001269 * 7: Is at return
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001270 * 8: Flags (debugger frame, optimized frame, inlined frame index)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001271 * Arguments name, value
1272 * Locals name, value
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001273 * Return value if any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001274 * @param {number} break_id Current break id
1275 * @param {number} index Frame number
1276 * @constructor
1277 */
1278function FrameDetails(break_id, index) {
1279 this.break_id_ = break_id;
1280 this.details_ = %GetFrameDetails(break_id, index);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001281}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282
1283
1284FrameDetails.prototype.frameId = function() {
1285 %CheckExecutionState(this.break_id_);
1286 return this.details_[kFrameDetailsFrameIdIndex];
1287}
1288
1289
1290FrameDetails.prototype.receiver = function() {
1291 %CheckExecutionState(this.break_id_);
1292 return this.details_[kFrameDetailsReceiverIndex];
1293}
1294
1295
1296FrameDetails.prototype.func = function() {
1297 %CheckExecutionState(this.break_id_);
1298 return this.details_[kFrameDetailsFunctionIndex];
1299}
1300
1301
1302FrameDetails.prototype.isConstructCall = function() {
1303 %CheckExecutionState(this.break_id_);
1304 return this.details_[kFrameDetailsConstructCallIndex];
1305}
1306
1307
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001308FrameDetails.prototype.isAtReturn = function() {
1309 %CheckExecutionState(this.break_id_);
1310 return this.details_[kFrameDetailsAtReturnIndex];
1311}
1312
1313
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001314FrameDetails.prototype.isDebuggerFrame = function() {
1315 %CheckExecutionState(this.break_id_);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001316 var f = kFrameDetailsFlagDebuggerFrameMask;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001317 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1318}
1319
1320
1321FrameDetails.prototype.isOptimizedFrame = function() {
1322 %CheckExecutionState(this.break_id_);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001323 var f = kFrameDetailsFlagOptimizedFrameMask;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001324 return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
1325}
1326
1327
1328FrameDetails.prototype.isInlinedFrame = function() {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001329 return this.inlinedFrameIndex() > 0;
1330}
1331
1332
1333FrameDetails.prototype.inlinedFrameIndex = function() {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001334 %CheckExecutionState(this.break_id_);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001335 var f = kFrameDetailsFlagInlinedFrameIndexMask;
1336 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337}
1338
1339
1340FrameDetails.prototype.argumentCount = function() {
1341 %CheckExecutionState(this.break_id_);
1342 return this.details_[kFrameDetailsArgumentCountIndex];
1343}
1344
1345
1346FrameDetails.prototype.argumentName = function(index) {
1347 %CheckExecutionState(this.break_id_);
1348 if (index >= 0 && index < this.argumentCount()) {
1349 return this.details_[kFrameDetailsFirstDynamicIndex +
1350 index * kFrameDetailsNameValueSize +
1351 kFrameDetailsNameIndex]
1352 }
1353}
1354
1355
1356FrameDetails.prototype.argumentValue = function(index) {
1357 %CheckExecutionState(this.break_id_);
1358 if (index >= 0 && index < this.argumentCount()) {
1359 return this.details_[kFrameDetailsFirstDynamicIndex +
1360 index * kFrameDetailsNameValueSize +
1361 kFrameDetailsValueIndex]
1362 }
1363}
1364
1365
1366FrameDetails.prototype.localCount = function() {
1367 %CheckExecutionState(this.break_id_);
1368 return this.details_[kFrameDetailsLocalCountIndex];
1369}
1370
1371
1372FrameDetails.prototype.sourcePosition = function() {
1373 %CheckExecutionState(this.break_id_);
1374 return this.details_[kFrameDetailsSourcePositionIndex];
1375}
1376
1377
1378FrameDetails.prototype.localName = function(index) {
1379 %CheckExecutionState(this.break_id_);
1380 if (index >= 0 && index < this.localCount()) {
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001381 var locals_offset = kFrameDetailsFirstDynamicIndex +
1382 this.argumentCount() * kFrameDetailsNameValueSize
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001383 return this.details_[locals_offset +
1384 index * kFrameDetailsNameValueSize +
1385 kFrameDetailsNameIndex]
1386 }
1387}
1388
1389
1390FrameDetails.prototype.localValue = function(index) {
1391 %CheckExecutionState(this.break_id_);
1392 if (index >= 0 && index < this.localCount()) {
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001393 var locals_offset = kFrameDetailsFirstDynamicIndex +
1394 this.argumentCount() * kFrameDetailsNameValueSize
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001395 return this.details_[locals_offset +
1396 index * kFrameDetailsNameValueSize +
1397 kFrameDetailsValueIndex]
1398 }
1399}
1400
1401
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001402FrameDetails.prototype.returnValue = function() {
1403 %CheckExecutionState(this.break_id_);
1404 var return_value_offset =
1405 kFrameDetailsFirstDynamicIndex +
1406 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1407 if (this.details_[kFrameDetailsAtReturnIndex]) {
1408 return this.details_[return_value_offset];
1409 }
1410}
1411
1412
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001413FrameDetails.prototype.scopeCount = function() {
1414 return %GetScopeCount(this.break_id_, this.frameId());
1415}
1416
1417
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001418/**
1419 * Mirror object for stack frames.
1420 * @param {number} break_id The break id in the VM for which this frame is
1421 valid
1422 * @param {number} index The frame index (top frame is index 0)
1423 * @constructor
1424 * @extends Mirror
1425 */
1426function FrameMirror(break_id, index) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001427 %_CallFunction(this, FRAME_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001428 this.break_id_ = break_id;
1429 this.index_ = index;
1430 this.details_ = new FrameDetails(break_id, index);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001431}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001432inherits(FrameMirror, Mirror);
1433
1434
1435FrameMirror.prototype.index = function() {
1436 return this.index_;
1437};
1438
1439
1440FrameMirror.prototype.func = function() {
1441 // Get the function for this frame from the VM.
1442 var f = this.details_.func();
lrn@chromium.org25156de2010-04-06 13:10:27 +00001443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001444 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1445 // value returned from the VM might be a string if the function for the
1446 // frame is unresolved.
1447 if (IS_FUNCTION(f)) {
ager@chromium.org32912102009-01-16 10:38:43 +00001448 return MakeMirror(f);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001449 } else {
1450 return new UnresolvedFunctionMirror(f);
1451 }
1452};
1453
1454
1455FrameMirror.prototype.receiver = function() {
1456 return MakeMirror(this.details_.receiver());
1457};
1458
1459
1460FrameMirror.prototype.isConstructCall = function() {
1461 return this.details_.isConstructCall();
1462};
1463
1464
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001465FrameMirror.prototype.isAtReturn = function() {
1466 return this.details_.isAtReturn();
1467};
1468
1469
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001470FrameMirror.prototype.isDebuggerFrame = function() {
1471 return this.details_.isDebuggerFrame();
1472};
1473
1474
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001475FrameMirror.prototype.isOptimizedFrame = function() {
1476 return this.details_.isOptimizedFrame();
1477};
1478
1479
1480FrameMirror.prototype.isInlinedFrame = function() {
1481 return this.details_.isInlinedFrame();
1482};
1483
1484
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001485FrameMirror.prototype.inlinedFrameIndex = function() {
1486 return this.details_.inlinedFrameIndex();
1487};
1488
1489
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001490FrameMirror.prototype.argumentCount = function() {
1491 return this.details_.argumentCount();
1492};
1493
1494
1495FrameMirror.prototype.argumentName = function(index) {
1496 return this.details_.argumentName(index);
1497};
1498
1499
1500FrameMirror.prototype.argumentValue = function(index) {
1501 return MakeMirror(this.details_.argumentValue(index));
1502};
1503
1504
1505FrameMirror.prototype.localCount = function() {
1506 return this.details_.localCount();
1507};
1508
1509
1510FrameMirror.prototype.localName = function(index) {
1511 return this.details_.localName(index);
1512};
1513
1514
1515FrameMirror.prototype.localValue = function(index) {
1516 return MakeMirror(this.details_.localValue(index));
1517};
1518
1519
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001520FrameMirror.prototype.returnValue = function() {
1521 return MakeMirror(this.details_.returnValue());
1522};
1523
1524
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001525FrameMirror.prototype.sourcePosition = function() {
1526 return this.details_.sourcePosition();
1527};
1528
1529
1530FrameMirror.prototype.sourceLocation = function() {
1531 if (this.func().resolved() && this.func().script()) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001532 return this.func().script().locationFromPosition(this.sourcePosition(),
1533 true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001534 }
1535};
1536
1537
1538FrameMirror.prototype.sourceLine = function() {
1539 if (this.func().resolved()) {
1540 var location = this.sourceLocation();
1541 if (location) {
1542 return location.line;
1543 }
1544 }
1545};
1546
1547
1548FrameMirror.prototype.sourceColumn = function() {
1549 if (this.func().resolved()) {
1550 var location = this.sourceLocation();
1551 if (location) {
1552 return location.column;
1553 }
1554 }
1555};
1556
1557
1558FrameMirror.prototype.sourceLineText = function() {
1559 if (this.func().resolved()) {
1560 var location = this.sourceLocation();
1561 if (location) {
1562 return location.sourceText();
1563 }
1564 }
1565};
1566
1567
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001568FrameMirror.prototype.scopeCount = function() {
1569 return this.details_.scopeCount();
1570};
1571
1572
1573FrameMirror.prototype.scope = function(index) {
1574 return new ScopeMirror(this, index);
1575};
1576
1577
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001578FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001579 var result = %DebugEvaluate(this.break_id_,
1580 this.details_.frameId(),
1581 this.details_.inlinedFrameIndex(),
1582 source,
1583 Boolean(disable_break),
1584 opt_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585 return MakeMirror(result);
1586};
1587
1588
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589FrameMirror.prototype.invocationText = function() {
1590 // Format frame invoaction (receiver, function and arguments).
1591 var result = '';
1592 var func = this.func();
1593 var receiver = this.receiver();
1594 if (this.isConstructCall()) {
1595 // For constructor frames display new followed by the function name.
1596 result += 'new ';
1597 result += func.name() ? func.name() : '[anonymous]';
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001598 } else if (this.isDebuggerFrame()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599 result += '[debugger]';
1600 } else {
1601 // If the receiver has a className which is 'global' don't display it.
1602 var display_receiver = !receiver.className || receiver.className() != 'global';
1603 if (display_receiver) {
1604 result += receiver.toText();
1605 }
1606 // Try to find the function as a property in the receiver. Include the
1607 // prototype chain in the lookup.
ager@chromium.org32912102009-01-16 10:38:43 +00001608 var property = GetUndefinedMirror();
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001609 if (receiver.isObject()) {
1610 for (var r = receiver;
1611 !r.isNull() && property.isUndefined();
1612 r = r.protoObject()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001613 property = r.lookupProperty(func);
1614 }
1615 }
1616 if (!property.isUndefined()) {
1617 // The function invoked was found on the receiver. Use the property name
1618 // for the backtrace.
1619 if (!property.isIndexed()) {
1620 if (display_receiver) {
1621 result += '.';
1622 }
1623 result += property.name();
1624 } else {
1625 result += '[';
1626 result += property.name();
1627 result += ']';
1628 }
1629 // Also known as - if the name in the function doesn't match the name
1630 // under which it was looked up.
1631 if (func.name() && func.name() != property.name()) {
1632 result += '(aka ' + func.name() + ')';
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001633 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001634 } else {
1635 // The function invoked was not found on the receiver. Use the function
1636 // name if available for the backtrace.
1637 if (display_receiver) {
1638 result += '.';
1639 }
1640 result += func.name() ? func.name() : '[anonymous]';
1641 }
1642 }
1643
1644 // Render arguments for normal frames.
1645 if (!this.isDebuggerFrame()) {
1646 result += '(';
1647 for (var i = 0; i < this.argumentCount(); i++) {
1648 if (i != 0) result += ', ';
1649 if (this.argumentName(i)) {
1650 result += this.argumentName(i);
1651 result += '=';
1652 }
1653 result += this.argumentValue(i).toText();
1654 }
1655 result += ')';
1656 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001657
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001658 if (this.isAtReturn()) {
1659 result += ' returning ';
1660 result += this.returnValue().toText();
1661 }
vegorov@chromium.org42841962010-10-18 11:18:59 +00001662
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001663 return result;
1664}
1665
1666
1667FrameMirror.prototype.sourceAndPositionText = function() {
1668 // Format source and position.
1669 var result = '';
1670 var func = this.func();
1671 if (func.resolved()) {
1672 if (func.script()) {
1673 if (func.script().name()) {
1674 result += func.script().name();
1675 } else {
1676 result += '[unnamed]';
1677 }
1678 if (!this.isDebuggerFrame()) {
1679 var location = this.sourceLocation();
1680 result += ' line ';
1681 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1682 result += ' column ';
1683 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1684 if (!IS_UNDEFINED(this.sourcePosition())) {
1685 result += ' (position ' + (this.sourcePosition() + 1) + ')';
1686 }
1687 }
1688 } else {
1689 result += '[no source]';
1690 }
1691 } else {
1692 result += '[unresolved]';
1693 }
1694
1695 return result;
1696}
1697
1698
1699FrameMirror.prototype.localsText = function() {
1700 // Format local variables.
1701 var result = '';
1702 var locals_count = this.localCount()
1703 if (locals_count > 0) {
1704 for (var i = 0; i < locals_count; ++i) {
1705 result += ' var ';
1706 result += this.localName(i);
1707 result += ' = ';
1708 result += this.localValue(i).toText();
1709 if (i < locals_count - 1) result += '\n';
1710 }
1711 }
1712
1713 return result;
1714}
1715
1716
1717FrameMirror.prototype.toText = function(opt_locals) {
1718 var result = '';
1719 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1720 result += ' ';
1721 result += this.invocationText();
1722 result += ' ';
1723 result += this.sourceAndPositionText();
1724 if (opt_locals) {
1725 result += '\n';
1726 result += this.localsText();
1727 }
1728 return result;
1729}
1730
1731
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001732const kScopeDetailsTypeIndex = 0;
1733const kScopeDetailsObjectIndex = 1;
1734
1735function ScopeDetails(frame, index) {
1736 this.break_id_ = frame.break_id_;
1737 this.details_ = %GetScopeDetails(frame.break_id_,
1738 frame.details_.frameId(),
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001739 frame.details_.inlinedFrameIndex(),
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001740 index);
1741}
1742
1743
1744ScopeDetails.prototype.type = function() {
1745 %CheckExecutionState(this.break_id_);
1746 return this.details_[kScopeDetailsTypeIndex];
1747}
1748
1749
1750ScopeDetails.prototype.object = function() {
1751 %CheckExecutionState(this.break_id_);
1752 return this.details_[kScopeDetailsObjectIndex];
1753}
1754
1755
1756/**
1757 * Mirror object for scope.
1758 * @param {FrameMirror} frame The frame this scope is a part of
1759 * @param {number} index The scope index in the frame
1760 * @constructor
1761 * @extends Mirror
1762 */
1763function ScopeMirror(frame, index) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001764 %_CallFunction(this, SCOPE_TYPE, Mirror);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001765 this.frame_index_ = frame.index_;
1766 this.scope_index_ = index;
1767 this.details_ = new ScopeDetails(frame, index);
1768}
1769inherits(ScopeMirror, Mirror);
1770
1771
1772ScopeMirror.prototype.frameIndex = function() {
1773 return this.frame_index_;
1774};
1775
1776
1777ScopeMirror.prototype.scopeIndex = function() {
1778 return this.scope_index_;
1779};
1780
1781
1782ScopeMirror.prototype.scopeType = function() {
1783 return this.details_.type();
1784};
1785
1786
1787ScopeMirror.prototype.scopeObject = function() {
1788 // For local and closure scopes create a transient mirror as these objects are
1789 // created on the fly materializing the local or closure scopes and
1790 // therefore will not preserve identity.
1791 var transient = this.scopeType() == ScopeType.Local ||
1792 this.scopeType() == ScopeType.Closure;
1793 return MakeMirror(this.details_.object(), transient);
1794};
1795
1796
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001797/**
1798 * Mirror object for script source.
1799 * @param {Script} script The script object
1800 * @constructor
1801 * @extends Mirror
1802 */
1803function ScriptMirror(script) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001804 %_CallFunction(this, SCRIPT_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001805 this.script_ = script;
ager@chromium.org9085a012009-05-11 19:22:57 +00001806 this.context_ = new ContextMirror(script.context_data);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001807 this.allocateHandle_();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001808}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001809inherits(ScriptMirror, Mirror);
1810
1811
iposva@chromium.org245aa852009-02-10 00:49:54 +00001812ScriptMirror.prototype.value = function() {
1813 return this.script_;
1814};
1815
1816
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001817ScriptMirror.prototype.name = function() {
lrn@chromium.org25156de2010-04-06 13:10:27 +00001818 return this.script_.name || this.script_.nameOrSourceURL();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001819};
1820
1821
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001822ScriptMirror.prototype.id = function() {
1823 return this.script_.id;
1824};
1825
1826
iposva@chromium.org245aa852009-02-10 00:49:54 +00001827ScriptMirror.prototype.source = function() {
1828 return this.script_.source;
1829};
1830
1831
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001832ScriptMirror.prototype.lineOffset = function() {
1833 return this.script_.line_offset;
1834};
1835
1836
1837ScriptMirror.prototype.columnOffset = function() {
1838 return this.script_.column_offset;
1839};
1840
1841
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001842ScriptMirror.prototype.data = function() {
1843 return this.script_.data;
1844};
1845
1846
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001847ScriptMirror.prototype.scriptType = function() {
1848 return this.script_.type;
1849};
1850
1851
ager@chromium.orge2902be2009-06-08 12:21:35 +00001852ScriptMirror.prototype.compilationType = function() {
1853 return this.script_.compilation_type;
1854};
1855
1856
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001857ScriptMirror.prototype.lineCount = function() {
1858 return this.script_.lineCount();
1859};
1860
1861
ager@chromium.org3a6061e2009-03-12 14:24:36 +00001862ScriptMirror.prototype.locationFromPosition = function(
1863 position, include_resource_offset) {
1864 return this.script_.locationFromPosition(position, include_resource_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001865}
1866
1867
1868ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
1869 return this.script_.sourceSlice(opt_from_line, opt_to_line);
1870}
1871
1872
ager@chromium.org9085a012009-05-11 19:22:57 +00001873ScriptMirror.prototype.context = function() {
1874 return this.context_;
1875};
1876
1877
sgjesse@chromium.org98180592009-12-02 08:17:28 +00001878ScriptMirror.prototype.evalFromScript = function() {
1879 return MakeMirror(this.script_.eval_from_script);
1880};
1881
1882
1883ScriptMirror.prototype.evalFromFunctionName = function() {
1884 return MakeMirror(this.script_.eval_from_function_name);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001885};
1886
1887
1888ScriptMirror.prototype.evalFromLocation = function() {
sgjesse@chromium.org98180592009-12-02 08:17:28 +00001889 var eval_from_script = this.evalFromScript();
1890 if (!eval_from_script.isUndefined()) {
1891 var position = this.script_.eval_from_script_position;
1892 return eval_from_script.locationFromPosition(position, true);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001893 }
1894};
1895
1896
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001897ScriptMirror.prototype.toText = function() {
1898 var result = '';
1899 result += this.name();
1900 result += ' (lines: ';
1901 if (this.lineOffset() > 0) {
1902 result += this.lineOffset();
1903 result += '-';
1904 result += this.lineOffset() + this.lineCount() - 1;
1905 } else {
1906 result += this.lineCount();
1907 }
1908 result += ')';
1909 return result;
1910}
1911
1912
ager@chromium.org32912102009-01-16 10:38:43 +00001913/**
ager@chromium.org9085a012009-05-11 19:22:57 +00001914 * Mirror object for context.
1915 * @param {Object} data The context data
1916 * @constructor
1917 * @extends Mirror
1918 */
1919function ContextMirror(data) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001920 %_CallFunction(this, CONTEXT_TYPE, Mirror);
ager@chromium.org9085a012009-05-11 19:22:57 +00001921 this.data_ = data;
1922 this.allocateHandle_();
1923}
1924inherits(ContextMirror, Mirror);
1925
1926
1927ContextMirror.prototype.data = function() {
1928 return this.data_;
1929};
1930
1931
1932/**
ager@chromium.org32912102009-01-16 10:38:43 +00001933 * Returns a mirror serializer
1934 *
1935 * @param {boolean} details Set to true to include details
ager@chromium.org9085a012009-05-11 19:22:57 +00001936 * @param {Object} options Options comtrolling the serialization
1937 * The following options can be set:
1938 * includeSource: include ths full source of scripts
ager@chromium.org32912102009-01-16 10:38:43 +00001939 * @returns {MirrorSerializer} mirror serializer
1940 */
ager@chromium.org9085a012009-05-11 19:22:57 +00001941function MakeMirrorSerializer(details, options) {
1942 return new JSONProtocolSerializer(details, options);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00001943}
1944
1945
ager@chromium.org32912102009-01-16 10:38:43 +00001946/**
1947 * Object for serializing a mirror objects and its direct references.
1948 * @param {boolean} details Indicates whether to include details for the mirror
1949 * serialized
1950 * @constructor
1951 */
ager@chromium.org9085a012009-05-11 19:22:57 +00001952function JSONProtocolSerializer(details, options) {
ager@chromium.org32912102009-01-16 10:38:43 +00001953 this.details_ = details;
ager@chromium.org9085a012009-05-11 19:22:57 +00001954 this.options_ = options;
ager@chromium.org32912102009-01-16 10:38:43 +00001955 this.mirrors_ = [ ];
1956}
1957
1958
1959/**
1960 * Returns a serialization of an object reference. The referenced object are
1961 * added to the serialization state.
1962 *
1963 * @param {Mirror} mirror The mirror to serialize
1964 * @returns {String} JSON serialization
1965 */
1966JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
1967 return this.serialize_(mirror, true, true);
1968}
1969
1970
1971/**
1972 * Returns a serialization of an object value. The referenced objects are
1973 * added to the serialization state.
1974 *
1975 * @param {Mirror} mirror The mirror to serialize
1976 * @returns {String} JSON serialization
1977 */
1978JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
1979 var json = this.serialize_(mirror, false, true);
1980 return json;
1981}
1982
1983
1984/**
1985 * Returns a serialization of all the objects referenced.
1986 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001987 * @param {Mirror} mirror The mirror to serialize.
1988 * @returns {Array.<Object>} Array of the referenced objects converted to
1989 * protcol objects.
ager@chromium.org32912102009-01-16 10:38:43 +00001990 */
1991JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001992 // Collect the protocol representation of the referenced objects in an array.
1993 var content = [];
lrn@chromium.org25156de2010-04-06 13:10:27 +00001994
ager@chromium.org32912102009-01-16 10:38:43 +00001995 // Get the number of referenced objects.
1996 var count = this.mirrors_.length;
lrn@chromium.org25156de2010-04-06 13:10:27 +00001997
ager@chromium.org32912102009-01-16 10:38:43 +00001998 for (var i = 0; i < count; i++) {
1999 content.push(this.serialize_(this.mirrors_[i], false, false));
2000 }
2001
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002002 return content;
ager@chromium.org32912102009-01-16 10:38:43 +00002003}
2004
2005
ager@chromium.org9085a012009-05-11 19:22:57 +00002006JSONProtocolSerializer.prototype.includeSource_ = function() {
2007 return this.options_ && this.options_.includeSource;
2008}
2009
2010
ager@chromium.org3e875802009-06-29 08:26:34 +00002011JSONProtocolSerializer.prototype.inlineRefs_ = function() {
2012 return this.options_ && this.options_.inlineRefs;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002013}
2014
2015
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002016JSONProtocolSerializer.prototype.maxStringLength_ = function() {
2017 if (IS_UNDEFINED(this.options_) ||
2018 IS_UNDEFINED(this.options_.maxStringLength)) {
2019 return kMaxProtocolStringLength;
2020 }
2021 return this.options_.maxStringLength;
2022}
2023
2024
ager@chromium.org32912102009-01-16 10:38:43 +00002025JSONProtocolSerializer.prototype.add_ = function(mirror) {
2026 // If this mirror is already in the list just return.
2027 for (var i = 0; i < this.mirrors_.length; i++) {
2028 if (this.mirrors_[i] === mirror) {
2029 return;
2030 }
2031 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002032
ager@chromium.org32912102009-01-16 10:38:43 +00002033 // Add the mirror to the list of mirrors to be serialized.
2034 this.mirrors_.push(mirror);
2035}
2036
2037
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002038/**
2039 * Formats mirror object to protocol reference object with some data that can
2040 * be used to display the value in debugger.
2041 * @param {Mirror} mirror Mirror to serialize.
2042 * @return {Object} Protocol reference object.
2043 */
lrn@chromium.org25156de2010-04-06 13:10:27 +00002044JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002045 function(mirror) {
2046 var o = {};
2047 o.ref = mirror.handle();
2048 o.type = mirror.type();
2049 switch (mirror.type()) {
2050 case UNDEFINED_TYPE:
2051 case NULL_TYPE:
2052 case BOOLEAN_TYPE:
2053 case NUMBER_TYPE:
2054 o.value = mirror.value();
2055 break;
2056 case STRING_TYPE:
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002057 o.value = mirror.getTruncatedValue(this.maxStringLength_());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002058 break;
2059 case FUNCTION_TYPE:
2060 o.name = mirror.name();
2061 o.inferredName = mirror.inferredName();
2062 if (mirror.script()) {
2063 o.scriptId = mirror.script().id();
2064 }
2065 break;
2066 case ERROR_TYPE:
2067 case REGEXP_TYPE:
2068 o.value = mirror.toText();
2069 break;
2070 case OBJECT_TYPE:
2071 o.className = mirror.className();
2072 break;
2073 }
2074 return o;
2075};
2076
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002077
ager@chromium.org32912102009-01-16 10:38:43 +00002078JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2079 details) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002080 // If serializing a reference to a mirror just return the reference and add
2081 // the mirror to the referenced mirrors.
2082 if (reference &&
ager@chromium.org9085a012009-05-11 19:22:57 +00002083 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002084 if (this.inlineRefs_() && mirror.isValue()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002085 return this.serializeReferenceWithDisplayData_(mirror);
2086 } else {
2087 this.add_(mirror);
2088 return {'ref' : mirror.handle()};
2089 }
ager@chromium.org32912102009-01-16 10:38:43 +00002090 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002091
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002092 // Collect the JSON property/value pairs.
2093 var content = {};
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002094
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002095 // Add the mirror handle.
ager@chromium.org9085a012009-05-11 19:22:57 +00002096 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002097 content.handle = mirror.handle();
ager@chromium.org32912102009-01-16 10:38:43 +00002098 }
2099
2100 // Always add the type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002101 content.type = mirror.type();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002102
2103 switch (mirror.type()) {
2104 case UNDEFINED_TYPE:
2105 case NULL_TYPE:
2106 // Undefined and null are represented just by their type.
2107 break;
2108
2109 case BOOLEAN_TYPE:
2110 // Boolean values are simply represented by their value.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002111 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002112 break;
2113
2114 case NUMBER_TYPE:
2115 // Number values are simply represented by their value.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002116 content.value = NumberToJSON_(mirror.value());
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002117 break;
2118
2119 case STRING_TYPE:
2120 // String values might have their value cropped to keep down size.
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002121 if (this.maxStringLength_() != -1 &&
2122 mirror.length() > this.maxStringLength_()) {
2123 var str = mirror.getTruncatedValue(this.maxStringLength_());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002124 content.value = str;
2125 content.fromIndex = 0;
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002126 content.toIndex = this.maxStringLength_();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002127 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002128 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002129 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002130 content.length = mirror.length();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002131 break;
2132
2133 case OBJECT_TYPE:
2134 case FUNCTION_TYPE:
2135 case ERROR_TYPE:
2136 case REGEXP_TYPE:
2137 // Add object representation.
ager@chromium.org32912102009-01-16 10:38:43 +00002138 this.serializeObject_(mirror, content, details);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002139 break;
2140
2141 case PROPERTY_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00002142 throw new Error('PropertyMirror cannot be serialized independeltly')
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002143 break;
2144
2145 case FRAME_TYPE:
2146 // Add object representation.
2147 this.serializeFrame_(mirror, content);
2148 break;
2149
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002150 case SCOPE_TYPE:
2151 // Add object representation.
2152 this.serializeScope_(mirror, content);
2153 break;
2154
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002155 case SCRIPT_TYPE:
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002156 // Script is represented by id, name and source attributes.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002157 if (mirror.name()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002158 content.name = mirror.name();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002159 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002160 content.id = mirror.id();
2161 content.lineOffset = mirror.lineOffset();
2162 content.columnOffset = mirror.columnOffset();
2163 content.lineCount = mirror.lineCount();
ager@chromium.org9085a012009-05-11 19:22:57 +00002164 if (mirror.data()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002165 content.data = mirror.data();
ager@chromium.org9085a012009-05-11 19:22:57 +00002166 }
2167 if (this.includeSource_()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002168 content.source = mirror.source();
ager@chromium.org9085a012009-05-11 19:22:57 +00002169 } else {
2170 var sourceStart = mirror.source().substring(0, 80);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002171 content.sourceStart = sourceStart;
ager@chromium.org9085a012009-05-11 19:22:57 +00002172 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002173 content.sourceLength = mirror.source().length;
2174 content.scriptType = mirror.scriptType();
ager@chromium.orge2902be2009-06-08 12:21:35 +00002175 content.compilationType = mirror.compilationType();
sgjesse@chromium.org636edf42009-06-18 14:43:07 +00002176 // For compilation type eval emit information on the script from which
2177 // eval was called if a script is present.
2178 if (mirror.compilationType() == 1 &&
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002179 mirror.evalFromScript()) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00002180 content.evalFromScript =
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002181 this.serializeReference(mirror.evalFromScript());
ager@chromium.orge2902be2009-06-08 12:21:35 +00002182 var evalFromLocation = mirror.evalFromLocation()
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002183 if (evalFromLocation) {
2184 content.evalFromLocation = { line: evalFromLocation.line,
2185 column: evalFromLocation.column };
2186 }
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002187 if (mirror.evalFromFunctionName()) {
2188 content.evalFromFunctionName = mirror.evalFromFunctionName();
2189 }
ager@chromium.orge2902be2009-06-08 12:21:35 +00002190 }
ager@chromium.org9085a012009-05-11 19:22:57 +00002191 if (mirror.context()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002192 content.context = this.serializeReference(mirror.context());
ager@chromium.org9085a012009-05-11 19:22:57 +00002193 }
2194 break;
2195
2196 case CONTEXT_TYPE:
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002197 content.data = mirror.data();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002198 break;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002199 }
2200
2201 // Always add the text representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002202 content.text = mirror.toText();
lrn@chromium.org25156de2010-04-06 13:10:27 +00002203
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002204 // Create and return the JSON string.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002205 return content;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002206}
2207
2208
ager@chromium.org32912102009-01-16 10:38:43 +00002209/**
2210 * Serialize object information to the following JSON format.
2211 *
2212 * {"className":"<class name>",
2213 * "constructorFunction":{"ref":<number>},
2214 * "protoObject":{"ref":<number>},
2215 * "prototypeObject":{"ref":<number>},
2216 * "namedInterceptor":<boolean>,
2217 * "indexedInterceptor":<boolean>,
2218 * "properties":[<properties>]}
2219 */
2220JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2221 details) {
2222 // Add general object properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002223 content.className = mirror.className();
2224 content.constructorFunction =
2225 this.serializeReference(mirror.constructorFunction());
2226 content.protoObject = this.serializeReference(mirror.protoObject());
2227 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002228
ager@chromium.org32912102009-01-16 10:38:43 +00002229 // Add flags to indicate whether there are interceptors.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002230 if (mirror.hasNamedInterceptor()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002231 content.namedInterceptor = true;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002232 }
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002233 if (mirror.hasIndexedInterceptor()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002234 content.indexedInterceptor = true;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002235 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002236
ager@chromium.org32912102009-01-16 10:38:43 +00002237 // Add function specific properties.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002238 if (mirror.isFunction()) {
2239 // Add function specific properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002240 content.name = mirror.name();
ager@chromium.org9085a012009-05-11 19:22:57 +00002241 if (!IS_UNDEFINED(mirror.inferredName())) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002242 content.inferredName = mirror.inferredName();
ager@chromium.org9085a012009-05-11 19:22:57 +00002243 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002244 content.resolved = mirror.resolved();
ager@chromium.org32912102009-01-16 10:38:43 +00002245 if (mirror.resolved()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002246 content.source = mirror.source();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002247 }
2248 if (mirror.script()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002249 content.script = this.serializeReference(mirror.script());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002250 content.scriptId = mirror.script().id();
lrn@chromium.org25156de2010-04-06 13:10:27 +00002251
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002252 serializeLocationFields(mirror.sourceLocation(), content);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002253 }
ager@chromium.org32912102009-01-16 10:38:43 +00002254 }
2255
2256 // Add date specific properties.
2257 if (mirror.isDate()) {
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002258 // Add date specific properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002259 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002260 }
ager@chromium.org32912102009-01-16 10:38:43 +00002261
2262 // Add actual properties - named properties followed by indexed properties.
2263 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2264 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2265 var p = new Array(propertyNames.length + propertyIndexes.length);
2266 for (var i = 0; i < propertyNames.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002267 var propertyMirror = mirror.property(propertyNames[i]);
2268 p[i] = this.serializeProperty_(propertyMirror);
ager@chromium.org32912102009-01-16 10:38:43 +00002269 if (details) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002270 this.add_(propertyMirror.value());
ager@chromium.org32912102009-01-16 10:38:43 +00002271 }
2272 }
2273 for (var i = 0; i < propertyIndexes.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002274 var propertyMirror = mirror.property(propertyIndexes[i]);
2275 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
ager@chromium.org32912102009-01-16 10:38:43 +00002276 if (details) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002277 this.add_(propertyMirror.value());
ager@chromium.org32912102009-01-16 10:38:43 +00002278 }
2279 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002280 content.properties = p;
ager@chromium.org32912102009-01-16 10:38:43 +00002281}
2282
2283
2284/**
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002285 * Serialize location information to the following JSON format:
2286 *
2287 * "position":"<position>",
2288 * "line":"<line>",
2289 * "column":"<column>",
lrn@chromium.org25156de2010-04-06 13:10:27 +00002290 *
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002291 * @param {SourceLocation} location The location to serialize, may be undefined.
2292 */
2293function serializeLocationFields (location, content) {
2294 if (!location) {
2295 return;
lrn@chromium.org25156de2010-04-06 13:10:27 +00002296 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002297 content.position = location.position;
2298 var line = location.line;
2299 if (!IS_UNDEFINED(line)) {
2300 content.line = line;
2301 }
2302 var column = location.column;
2303 if (!IS_UNDEFINED(column)) {
2304 content.column = column;
2305 }
2306}
2307
2308
2309/**
ager@chromium.org32912102009-01-16 10:38:43 +00002310 * Serialize property information to the following JSON format for building the
2311 * array of properties.
2312 *
2313 * {"name":"<property name>",
2314 * "attributes":<number>,
2315 * "propertyType":<number>,
2316 * "ref":<number>}
2317 *
2318 * If the attribute for the property is PropertyAttribute.None it is not added.
2319 * If the propertyType for the property is PropertyType.Normal it is not added.
2320 * Here are a couple of examples.
2321 *
2322 * {"name":"hello","ref":1}
2323 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2324 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002325 * @param {PropertyMirror} propertyMirror The property to serialize.
2326 * @returns {Object} Protocol object representing the property.
ager@chromium.org32912102009-01-16 10:38:43 +00002327 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002328JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2329 var result = {};
lrn@chromium.org25156de2010-04-06 13:10:27 +00002330
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002331 result.name = propertyMirror.name();
2332 var propertyValue = propertyMirror.value();
ager@chromium.org3e875802009-06-29 08:26:34 +00002333 if (this.inlineRefs_() && propertyValue.isValue()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002334 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2335 } else {
2336 if (propertyMirror.attributes() != PropertyAttribute.None) {
2337 result.attributes = propertyMirror.attributes();
2338 }
2339 if (propertyMirror.propertyType() != PropertyType.Normal) {
2340 result.propertyType = propertyMirror.propertyType();
2341 }
2342 result.ref = propertyValue.handle();
ager@chromium.org32912102009-01-16 10:38:43 +00002343 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002344 return result;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002345}
2346
2347
2348JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002349 content.index = mirror.index();
2350 content.receiver = this.serializeReference(mirror.receiver());
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002351 var func = mirror.func();
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002352 content.func = this.serializeReference(func);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002353 if (func.script()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002354 content.script = this.serializeReference(func.script());
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002355 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002356 content.constructCall = mirror.isConstructCall();
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00002357 content.atReturn = mirror.isAtReturn();
2358 if (mirror.isAtReturn()) {
2359 content.returnValue = this.serializeReference(mirror.returnValue());
2360 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002361 content.debuggerFrame = mirror.isDebuggerFrame();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002362 var x = new Array(mirror.argumentCount());
2363 for (var i = 0; i < mirror.argumentCount(); i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002364 var arg = {};
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002365 var argument_name = mirror.argumentName(i)
2366 if (argument_name) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002367 arg.name = argument_name;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002368 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002369 arg.value = this.serializeReference(mirror.argumentValue(i));
2370 x[i] = arg;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002371 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002372 content.arguments = x;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002373 var x = new Array(mirror.localCount());
2374 for (var i = 0; i < mirror.localCount(); i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002375 var local = {};
2376 local.name = mirror.localName(i);
2377 local.value = this.serializeReference(mirror.localValue(i));
2378 x[i] = local;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002379 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002380 content.locals = x;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002381 serializeLocationFields(mirror.sourceLocation(), content);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002382 var source_line_text = mirror.sourceLineText();
2383 if (!IS_UNDEFINED(source_line_text)) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002384 content.sourceLineText = source_line_text;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002385 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002386
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002387 content.scopes = [];
2388 for (var i = 0; i < mirror.scopeCount(); i++) {
2389 var scope = mirror.scope(i);
2390 content.scopes.push({
2391 type: scope.scopeType(),
2392 index: i
2393 });
2394 }
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002395}
2396
2397
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002398JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2399 content.index = mirror.scopeIndex();
2400 content.frameIndex = mirror.frameIndex();
2401 content.type = mirror.scopeType();
ager@chromium.org3e875802009-06-29 08:26:34 +00002402 content.object = this.inlineRefs_() ?
2403 this.serializeValue(mirror.scopeObject()) :
2404 this.serializeReference(mirror.scopeObject());
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002405}
2406
2407
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002408/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002409 * Convert a number to a protocol value. For all finite numbers the number
2410 * itself is returned. For non finite numbers NaN, Infinite and
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002411 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002412 * (not including the quotes) is returned.
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002413 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002414 * @param {number} value The number value to convert to a protocol value.
2415 * @returns {number|string} Protocol value.
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002416 */
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002417function NumberToJSON_(value) {
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002418 if (isNaN(value)) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002419 return 'NaN';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002420 }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002421 if (!NUMBER_IS_FINITE(value)) {
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002422 if (value > 0) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002423 return 'Infinity';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002424 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002425 return '-Infinity';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002426 }
2427 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002428 return value;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002429}