blob: 416f88794dadf07bbd481ae0f2dc8d152974947d [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 = {};
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000173PropertyType.Normal = 0;
174PropertyType.Field = 1;
175PropertyType.ConstantFunction = 2;
176PropertyType.Callbacks = 3;
177PropertyType.Interceptor = 4;
178PropertyType.MapTransition = 5;
179PropertyType.ConstantTransition = 6;
180PropertyType.NullDescriptor = 7;
181
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183// Different attributes for a property.
184PropertyAttribute = {};
185PropertyAttribute.None = NONE;
186PropertyAttribute.ReadOnly = READ_ONLY;
187PropertyAttribute.DontEnum = DONT_ENUM;
188PropertyAttribute.DontDelete = DONT_DELETE;
189
190
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000191// A copy of the scope types from runtime.cc.
192ScopeType = { Global: 0,
193 Local: 1,
194 With: 2,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000195 Closure: 3,
196 Catch: 4 };
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000197
198
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199// Mirror hierarchy:
200// - Mirror
201// - ValueMirror
202// - UndefinedMirror
203// - NullMirror
204// - NumberMirror
205// - StringMirror
206// - ObjectMirror
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000207// - FunctionMirror
208// - UnresolvedFunctionMirror
209// - ArrayMirror
210// - DateMirror
211// - RegExpMirror
212// - ErrorMirror
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213// - PropertyMirror
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214// - FrameMirror
215// - ScriptMirror
216
217
218/**
219 * Base class for all mirror objects.
220 * @param {string} type The type of the mirror
221 * @constructor
222 */
223function Mirror(type) {
224 this.type_ = type;
225};
226
227
228Mirror.prototype.type = function() {
229 return this.type_;
230};
231
232
233/**
ager@chromium.org32912102009-01-16 10:38:43 +0000234 * Check whether the mirror reflects a value.
235 * @returns {boolean} True if the mirror reflects a value.
236 */
237Mirror.prototype.isValue = function() {
238 return this instanceof ValueMirror;
239}
240
241
242/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 * Check whether the mirror reflects the undefined value.
244 * @returns {boolean} True if the mirror reflects the undefined value.
245 */
246Mirror.prototype.isUndefined = function() {
247 return this instanceof UndefinedMirror;
248}
249
250
251/**
252 * Check whether the mirror reflects the null value.
253 * @returns {boolean} True if the mirror reflects the null value
254 */
255Mirror.prototype.isNull = function() {
256 return this instanceof NullMirror;
257}
258
259
260/**
261 * Check whether the mirror reflects a boolean value.
262 * @returns {boolean} True if the mirror reflects a boolean value
263 */
264Mirror.prototype.isBoolean = function() {
265 return this instanceof BooleanMirror;
266}
267
268
269/**
270 * Check whether the mirror reflects a number value.
271 * @returns {boolean} True if the mirror reflects a number value
272 */
273Mirror.prototype.isNumber = function() {
274 return this instanceof NumberMirror;
275}
276
277
278/**
279 * Check whether the mirror reflects a string value.
280 * @returns {boolean} True if the mirror reflects a string value
281 */
282Mirror.prototype.isString = function() {
283 return this instanceof StringMirror;
284}
285
286
287/**
288 * Check whether the mirror reflects an object.
289 * @returns {boolean} True if the mirror reflects an object
290 */
291Mirror.prototype.isObject = function() {
292 return this instanceof ObjectMirror;
293}
294
295
296/**
297 * Check whether the mirror reflects a function.
298 * @returns {boolean} True if the mirror reflects a function
299 */
300Mirror.prototype.isFunction = function() {
301 return this instanceof FunctionMirror;
302}
303
304
305/**
306 * Check whether the mirror reflects an unresolved function.
307 * @returns {boolean} True if the mirror reflects an unresolved function
308 */
309Mirror.prototype.isUnresolvedFunction = function() {
310 return this instanceof UnresolvedFunctionMirror;
311}
312
313
314/**
315 * Check whether the mirror reflects an array.
316 * @returns {boolean} True if the mirror reflects an array
317 */
318Mirror.prototype.isArray = function() {
319 return this instanceof ArrayMirror;
320}
321
322
323/**
324 * Check whether the mirror reflects a date.
325 * @returns {boolean} True if the mirror reflects a date
326 */
327Mirror.prototype.isDate = function() {
328 return this instanceof DateMirror;
329}
330
331
332/**
333 * Check whether the mirror reflects a regular expression.
334 * @returns {boolean} True if the mirror reflects a regular expression
335 */
336Mirror.prototype.isRegExp = function() {
337 return this instanceof RegExpMirror;
338}
339
340
341/**
342 * Check whether the mirror reflects an error.
343 * @returns {boolean} True if the mirror reflects an error
344 */
345Mirror.prototype.isError = function() {
346 return this instanceof ErrorMirror;
347}
348
349
350/**
351 * Check whether the mirror reflects a property.
352 * @returns {boolean} True if the mirror reflects a property
353 */
354Mirror.prototype.isProperty = function() {
355 return this instanceof PropertyMirror;
356}
357
358
359/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 * Check whether the mirror reflects a stack frame.
361 * @returns {boolean} True if the mirror reflects a stack frame
362 */
363Mirror.prototype.isFrame = function() {
364 return this instanceof FrameMirror;
365}
366
367
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +0000368/**
369 * Check whether the mirror reflects a script.
370 * @returns {boolean} True if the mirror reflects a script
371 */
372Mirror.prototype.isScript = function() {
373 return this instanceof ScriptMirror;
374}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375
376
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000377/**
ager@chromium.org9085a012009-05-11 19:22:57 +0000378 * Check whether the mirror reflects a context.
379 * @returns {boolean} True if the mirror reflects a context
380 */
381Mirror.prototype.isContext = function() {
382 return this instanceof ContextMirror;
383}
384
385
386/**
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000387 * Check whether the mirror reflects a scope.
388 * @returns {boolean} True if the mirror reflects a scope
389 */
390Mirror.prototype.isScope = function() {
391 return this instanceof ScopeMirror;
392}
393
394
395/**
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000396 * Allocate a handle id for this object.
397 */
398Mirror.prototype.allocateHandle_ = function() {
399 this.handle_ = next_handle_++;
400}
401
402
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000403/**
404 * Allocate a transient handle id for this object. Transient handles are
405 * negative.
406 */
407Mirror.prototype.allocateTransientHandle_ = function() {
408 this.handle_ = next_transient_handle_--;
409}
410
411
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412Mirror.prototype.toText = function() {
413 // Simpel to text which is used when on specialization in subclass.
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000414 return "#<" + this.constructor.name + ">";
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000415}
416
417
418/**
419 * Base class for all value mirror objects.
420 * @param {string} type The type of the mirror
421 * @param {value} value The value reflected by this mirror
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000422 * @param {boolean} transient indicate whether this object is transient with a
423 * transient handle
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000424 * @constructor
425 * @extends Mirror
426 */
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000427function ValueMirror(type, value, transient) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000428 %_CallFunction(this, type, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429 this.value_ = value;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000430 if (!transient) {
431 this.allocateHandle_();
432 } else {
433 this.allocateTransientHandle_();
434 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000435}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000436inherits(ValueMirror, Mirror);
437
438
ager@chromium.org32912102009-01-16 10:38:43 +0000439Mirror.prototype.handle = function() {
440 return this.handle_;
441};
442
443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444/**
445 * Check whether this is a primitive value.
446 * @return {boolean} True if the mirror reflects a primitive value
447 */
448ValueMirror.prototype.isPrimitive = function() {
449 var type = this.type();
450 return type === 'undefined' ||
451 type === 'null' ||
452 type === 'boolean' ||
453 type === 'number' ||
454 type === 'string';
455};
456
457
ager@chromium.org32912102009-01-16 10:38:43 +0000458/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000459 * Get the actual value reflected by this mirror.
460 * @return {value} The value reflected by this mirror
461 */
462ValueMirror.prototype.value = function() {
463 return this.value_;
464};
465
466
467/**
468 * Mirror object for Undefined.
469 * @constructor
470 * @extends ValueMirror
471 */
472function UndefinedMirror() {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000473 %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000474}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000475inherits(UndefinedMirror, ValueMirror);
476
477
478UndefinedMirror.prototype.toText = function() {
479 return 'undefined';
480}
481
482
483/**
484 * Mirror object for null.
485 * @constructor
486 * @extends ValueMirror
487 */
488function NullMirror() {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000489 %_CallFunction(this, NULL_TYPE, null, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000490}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491inherits(NullMirror, ValueMirror);
492
493
494NullMirror.prototype.toText = function() {
495 return 'null';
496}
497
498
499/**
500 * Mirror object for boolean values.
501 * @param {boolean} value The boolean value reflected by this mirror
502 * @constructor
503 * @extends ValueMirror
504 */
505function BooleanMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000506 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000507}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508inherits(BooleanMirror, ValueMirror);
509
510
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511BooleanMirror.prototype.toText = function() {
512 return this.value_ ? 'true' : 'false';
513}
514
515
516/**
517 * Mirror object for number values.
518 * @param {number} value The number value reflected by this mirror
519 * @constructor
520 * @extends ValueMirror
521 */
522function NumberMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000523 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000524}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525inherits(NumberMirror, ValueMirror);
526
527
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528NumberMirror.prototype.toText = function() {
529 return %NumberToString(this.value_);
530}
531
532
533/**
534 * Mirror object for string values.
535 * @param {string} value The string value reflected by this mirror
536 * @constructor
537 * @extends ValueMirror
538 */
539function StringMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000540 %_CallFunction(this, STRING_TYPE, value, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000541}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542inherits(StringMirror, ValueMirror);
543
544
545StringMirror.prototype.length = function() {
546 return this.value_.length;
547};
548
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000549StringMirror.prototype.getTruncatedValue = function(maxLength) {
550 if (maxLength != -1 && this.length() > maxLength) {
551 return this.value_.substring(0, maxLength) +
552 '... (length: ' + this.length() + ')';
553 }
554 return this.value_;
555}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000556
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557StringMirror.prototype.toText = function() {
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000558 return this.getTruncatedValue(kMaxProtocolStringLength);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559}
560
561
562/**
563 * Mirror object for objects.
564 * @param {object} value The object reflected by this mirror
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000565 * @param {boolean} transient indicate whether this object is transient with a
566 * transient handle
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567 * @constructor
568 * @extends ValueMirror
569 */
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000570function ObjectMirror(value, type, transient) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000571 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000572}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573inherits(ObjectMirror, ValueMirror);
574
575
576ObjectMirror.prototype.className = function() {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000577 return %_ClassOf(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578};
579
580
581ObjectMirror.prototype.constructorFunction = function() {
582 return MakeMirror(%DebugGetProperty(this.value_, 'constructor'));
583};
584
585
586ObjectMirror.prototype.prototypeObject = function() {
587 return MakeMirror(%DebugGetProperty(this.value_, 'prototype'));
588};
589
590
591ObjectMirror.prototype.protoObject = function() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000592 return MakeMirror(%DebugGetPrototype(this.value_));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000593};
594
595
596ObjectMirror.prototype.hasNamedInterceptor = function() {
597 // Get information on interceptors for this object.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000598 var x = %GetInterceptorInfo(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000599 return (x & 2) != 0;
600};
601
602
603ObjectMirror.prototype.hasIndexedInterceptor = function() {
604 // Get information on interceptors for this object.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000605 var x = %GetInterceptorInfo(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606 return (x & 1) != 0;
607};
608
609
610/**
611 * Return the property names for this object.
612 * @param {number} kind Indicate whether named, indexed or both kinds of
613 * properties are requested
614 * @param {number} limit Limit the number of names returend to the specified
615 value
616 * @return {Array} Property names for this object
617 */
618ObjectMirror.prototype.propertyNames = function(kind, limit) {
619 // Find kind and limit and allocate array for the result
620 kind = kind || PropertyKind.Named | PropertyKind.Indexed;
621
622 var propertyNames;
623 var elementNames;
624 var total = 0;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000625
ager@chromium.org32912102009-01-16 10:38:43 +0000626 // Find all the named properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 if (kind & PropertyKind.Named) {
ager@chromium.org32912102009-01-16 10:38:43 +0000628 // Get the local property names.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000629 propertyNames = %GetLocalPropertyNames(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 total += propertyNames.length;
ager@chromium.org32912102009-01-16 10:38:43 +0000631
632 // Get names for named interceptor properties if any.
633 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
634 var namedInterceptorNames =
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000635 %GetNamedInterceptorPropertyNames(this.value_);
ager@chromium.org32912102009-01-16 10:38:43 +0000636 if (namedInterceptorNames) {
637 propertyNames = propertyNames.concat(namedInterceptorNames);
638 total += namedInterceptorNames.length;
639 }
640 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000641 }
ager@chromium.org32912102009-01-16 10:38:43 +0000642
643 // Find all the indexed properties.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644 if (kind & PropertyKind.Indexed) {
ager@chromium.org32912102009-01-16 10:38:43 +0000645 // Get the local element names.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000646 elementNames = %GetLocalElementNames(this.value_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 total += elementNames.length;
ager@chromium.org32912102009-01-16 10:38:43 +0000648
649 // Get names for indexed interceptor properties.
650 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
651 var indexedInterceptorNames =
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000652 %GetIndexedInterceptorElementNames(this.value_);
ager@chromium.org32912102009-01-16 10:38:43 +0000653 if (indexedInterceptorNames) {
654 elementNames = elementNames.concat(indexedInterceptorNames);
655 total += indexedInterceptorNames.length;
656 }
657 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000658 }
659 limit = Math.min(limit || total, total);
660
661 var names = new Array(limit);
662 var index = 0;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000663
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664 // Copy names for named properties.
665 if (kind & PropertyKind.Named) {
666 for (var i = 0; index < limit && i < propertyNames.length; i++) {
667 names[index++] = propertyNames[i];
668 }
669 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671 // Copy names for indexed properties.
672 if (kind & PropertyKind.Indexed) {
673 for (var i = 0; index < limit && i < elementNames.length; i++) {
674 names[index++] = elementNames[i];
675 }
676 }
677
678 return names;
679};
680
681
682/**
683 * Return the properties for this object as an array of PropertyMirror objects.
684 * @param {number} kind Indicate whether named, indexed or both kinds of
685 * properties are requested
686 * @param {number} limit Limit the number of properties returend to the
687 specified value
688 * @return {Array} Property mirrors for this object
689 */
690ObjectMirror.prototype.properties = function(kind, limit) {
691 var names = this.propertyNames(kind, limit);
692 var properties = new Array(names.length);
693 for (var i = 0; i < names.length; i++) {
694 properties[i] = this.property(names[i]);
695 }
696
697 return properties;
698};
699
700
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701ObjectMirror.prototype.property = function(name) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000702 var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000703 if (details) {
ager@chromium.org32912102009-01-16 10:38:43 +0000704 return new PropertyMirror(this, name, details);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705 }
706
707 // Nothing found.
ager@chromium.org32912102009-01-16 10:38:43 +0000708 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709};
710
711
712
713/**
714 * Try to find a property from its value.
715 * @param {Mirror} value The property value to look for
716 * @return {PropertyMirror} The property with the specified value. If no
717 * property was found with the specified value UndefinedMirror is returned
718 */
719ObjectMirror.prototype.lookupProperty = function(value) {
720 var properties = this.properties();
721
722 // Look for property value in properties.
723 for (var i = 0; i < properties.length; i++) {
724
725 // Skip properties which are defined through assessors.
726 var property = properties[i];
727 if (property.propertyType() != PropertyType.Callbacks) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000728 if (%_ObjectEquals(property.value_, value.value_)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000729 return property;
730 }
731 }
732 }
733
734 // Nothing found.
ager@chromium.org32912102009-01-16 10:38:43 +0000735 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000736};
737
738
739/**
740 * Returns objects which has direct references to this object
iposva@chromium.org245aa852009-02-10 00:49:54 +0000741 * @param {number} opt_max_objects Optional parameter specifying the maximum
742 * number of referencing objects to return.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743 * @return {Array} The objects which has direct references to this object.
744 */
iposva@chromium.org245aa852009-02-10 00:49:54 +0000745ObjectMirror.prototype.referencedBy = function(opt_max_objects) {
746 // Find all objects with direct references to this object.
747 var result = %DebugReferencedBy(this.value_,
748 Mirror.prototype, opt_max_objects || 0);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000749
iposva@chromium.org245aa852009-02-10 00:49:54 +0000750 // Make mirrors for all the references found.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000751 for (var i = 0; i < result.length; i++) {
752 result[i] = MakeMirror(result[i]);
753 }
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000754
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755 return result;
756};
757
758
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759ObjectMirror.prototype.toText = function() {
760 var name;
761 var ctor = this.constructorFunction();
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000762 if (!ctor.isFunction()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000763 name = this.className();
764 } else {
765 name = ctor.name();
766 if (!name) {
767 name = this.className();
768 }
769 }
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000770 return '#<' + name + '>';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771};
772
773
774/**
775 * Mirror object for functions.
776 * @param {function} value The function object reflected by this mirror.
777 * @constructor
778 * @extends ObjectMirror
779 */
780function FunctionMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000781 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000782 this.resolved_ = true;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000783}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000784inherits(FunctionMirror, ObjectMirror);
785
786
787/**
788 * Returns whether the function is resolved.
789 * @return {boolean} True if the function is resolved. Unresolved functions can
790 * only originate as functions from stack frames
791 */
792FunctionMirror.prototype.resolved = function() {
793 return this.resolved_;
794};
795
796
797/**
798 * Returns the name of the function.
799 * @return {string} Name of the function
800 */
801FunctionMirror.prototype.name = function() {
802 return %FunctionGetName(this.value_);
803};
804
805
806/**
ager@chromium.org9085a012009-05-11 19:22:57 +0000807 * Returns the inferred name of the function.
808 * @return {string} Name of the function
809 */
810FunctionMirror.prototype.inferredName = function() {
811 return %FunctionGetInferredName(this.value_);
812};
813
814
815/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000816 * Returns the source code for the function.
817 * @return {string or undefined} The source code for the function. If the
818 * function is not resolved undefined will be returned.
819 */
820FunctionMirror.prototype.source = function() {
821 // Return source if function is resolved. Otherwise just fall through to
822 // return undefined.
823 if (this.resolved()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824 return builtins.FunctionSourceString(this.value_);
825 }
826};
827
828
829/**
830 * Returns the script object for the function.
831 * @return {ScriptMirror or undefined} Script object for the function or
832 * undefined if the function has no script
833 */
834FunctionMirror.prototype.script = function() {
835 // Return script if function is resolved. Otherwise just fall through
836 // to return undefined.
837 if (this.resolved()) {
838 var script = %FunctionGetScript(this.value_);
839 if (script) {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000840 return MakeMirror(script);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000841 }
842 }
843};
844
845
846/**
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000847 * Returns the script source position for the function. Only makes sense
848 * for functions which has a script defined.
849 * @return {Number or undefined} in-script position for the function
850 */
851FunctionMirror.prototype.sourcePosition_ = function() {
852 // Return script if function is resolved. Otherwise just fall through
853 // to return undefined.
854 if (this.resolved()) {
855 return %FunctionGetScriptSourcePosition(this.value_);
856 }
857};
858
859
860/**
861 * Returns the script source location object for the function. Only makes sense
862 * for functions which has a script defined.
863 * @return {Location or undefined} in-script location for the function begin
864 */
865FunctionMirror.prototype.sourceLocation = function() {
866 if (this.resolved() && this.script()) {
867 return this.script().locationFromPosition(this.sourcePosition_(),
868 true);
869 }
870};
871
872
873/**
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000874 * Returns objects constructed by this function.
875 * @param {number} opt_max_instances Optional parameter specifying the maximum
876 * number of instances to return.
877 * @return {Array or undefined} The objects constructed by this function.
878 */
879FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
880 if (this.resolved()) {
881 // Find all objects constructed from this function.
882 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000883
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000884 // Make mirrors for all the instances found.
885 for (var i = 0; i < result.length; i++) {
886 result[i] = MakeMirror(result[i]);
887 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000888
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000889 return result;
890 } else {
891 return [];
892 }
893};
894
895
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000896FunctionMirror.prototype.toText = function() {
897 return this.source();
898}
899
900
901/**
902 * Mirror object for unresolved functions.
903 * @param {string} value The name for the unresolved function reflected by this
904 * mirror.
905 * @constructor
906 * @extends ObjectMirror
907 */
908function UnresolvedFunctionMirror(value) {
909 // Construct this using the ValueMirror as an unresolved function is not a
910 // real object but just a string.
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000911 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000912 this.propertyCount_ = 0;
913 this.elementCount_ = 0;
914 this.resolved_ = false;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000915}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916inherits(UnresolvedFunctionMirror, FunctionMirror);
917
918
919UnresolvedFunctionMirror.prototype.className = function() {
920 return 'Function';
921};
922
923
924UnresolvedFunctionMirror.prototype.constructorFunction = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000925 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000926};
927
928
929UnresolvedFunctionMirror.prototype.prototypeObject = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000930 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000931};
932
933
934UnresolvedFunctionMirror.prototype.protoObject = function() {
ager@chromium.org32912102009-01-16 10:38:43 +0000935 return GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936};
937
938
939UnresolvedFunctionMirror.prototype.name = function() {
940 return this.value_;
941};
942
943
ager@chromium.org9085a012009-05-11 19:22:57 +0000944UnresolvedFunctionMirror.prototype.inferredName = function() {
945 return undefined;
946};
947
948
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000949UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) {
950 return [];
951}
952
953
954/**
955 * Mirror object for arrays.
956 * @param {Array} value The Array object reflected by this mirror
957 * @constructor
958 * @extends ObjectMirror
959 */
960function ArrayMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000961 %_CallFunction(this, value, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000962}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963inherits(ArrayMirror, ObjectMirror);
964
965
966ArrayMirror.prototype.length = function() {
967 return this.value_.length;
968};
969
970
971ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_to_index) {
972 var from_index = opt_from_index || 0;
973 var to_index = opt_to_index || this.length() - 1;
974 if (from_index > to_index) return new Array();
975 var values = new Array(to_index - from_index + 1);
976 for (var i = from_index; i <= to_index; i++) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000977 var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000978 var value;
979 if (details) {
ager@chromium.org32912102009-01-16 10:38:43 +0000980 value = new PropertyMirror(this, i, details);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000981 } else {
ager@chromium.org32912102009-01-16 10:38:43 +0000982 value = GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000983 }
984 values[i - from_index] = value;
985 }
986 return values;
987}
988
989
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000990/**
991 * Mirror object for dates.
992 * @param {Date} value The Date object reflected by this mirror
993 * @constructor
994 * @extends ObjectMirror
995 */
996function DateMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000997 %_CallFunction(this, value, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000998}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000999inherits(DateMirror, ObjectMirror);
1000
1001
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001002DateMirror.prototype.toText = function() {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001003 var s = JSON.stringify(this.value_);
1004 return s.substring(1, s.length - 1); // cut quotes
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001005}
1006
1007
1008/**
1009 * Mirror object for regular expressions.
1010 * @param {RegExp} value The RegExp object reflected by this mirror
1011 * @constructor
1012 * @extends ObjectMirror
1013 */
1014function RegExpMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001015 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001016}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001017inherits(RegExpMirror, ObjectMirror);
1018
1019
1020/**
1021 * Returns the source to the regular expression.
1022 * @return {string or undefined} The source to the regular expression
1023 */
1024RegExpMirror.prototype.source = function() {
1025 return this.value_.source;
1026};
1027
1028
1029/**
1030 * Returns whether this regular expression has the global (g) flag set.
1031 * @return {boolean} Value of the global flag
1032 */
1033RegExpMirror.prototype.global = function() {
1034 return this.value_.global;
1035};
1036
1037
1038/**
1039 * Returns whether this regular expression has the ignore case (i) flag set.
1040 * @return {boolean} Value of the ignore case flag
1041 */
1042RegExpMirror.prototype.ignoreCase = function() {
1043 return this.value_.ignoreCase;
1044};
1045
1046
1047/**
1048 * Returns whether this regular expression has the multiline (m) flag set.
1049 * @return {boolean} Value of the multiline flag
1050 */
1051RegExpMirror.prototype.multiline = function() {
1052 return this.value_.multiline;
1053};
1054
1055
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001056RegExpMirror.prototype.toText = function() {
1057 // Simpel to text which is used when on specialization in subclass.
1058 return "/" + this.source() + "/";
1059}
1060
1061
1062/**
1063 * Mirror object for error objects.
1064 * @param {Error} value The error object reflected by this mirror
1065 * @constructor
1066 * @extends ObjectMirror
1067 */
1068function ErrorMirror(value) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001069 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001070}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001071inherits(ErrorMirror, ObjectMirror);
1072
1073
1074/**
1075 * Returns the message for this eror object.
1076 * @return {string or undefined} The message for this eror object
1077 */
1078ErrorMirror.prototype.message = function() {
1079 return this.value_.message;
1080};
1081
1082
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083ErrorMirror.prototype.toText = function() {
1084 // Use the same text representation as in messages.js.
1085 var text;
1086 try {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001087 str = %_CallFunction(this.value_, builtins.errorToString);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001088 } catch (e) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001089 str = '#<Error>';
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001090 }
1091 return str;
1092}
1093
1094
1095/**
1096 * Base mirror object for properties.
1097 * @param {ObjectMirror} mirror The mirror object having this property
1098 * @param {string} name The name of the property
ager@chromium.org32912102009-01-16 10:38:43 +00001099 * @param {Array} details Details about the property
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001100 * @constructor
1101 * @extends Mirror
1102 */
ager@chromium.org32912102009-01-16 10:38:43 +00001103function PropertyMirror(mirror, name, details) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001104 %_CallFunction(this, PROPERTY_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001105 this.mirror_ = mirror;
1106 this.name_ = name;
ager@chromium.org32912102009-01-16 10:38:43 +00001107 this.value_ = details[0];
1108 this.details_ = details[1];
1109 if (details.length > 2) {
1110 this.exception_ = details[2]
1111 this.getter_ = details[3];
1112 this.setter_ = details[4];
1113 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001114}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001115inherits(PropertyMirror, Mirror);
1116
1117
1118PropertyMirror.prototype.isReadOnly = function() {
1119 return (this.attributes() & PropertyAttribute.ReadOnly) != 0;
1120}
1121
1122
1123PropertyMirror.prototype.isEnum = function() {
1124 return (this.attributes() & PropertyAttribute.DontEnum) == 0;
1125}
1126
1127
1128PropertyMirror.prototype.canDelete = function() {
1129 return (this.attributes() & PropertyAttribute.DontDelete) == 0;
1130}
1131
1132
1133PropertyMirror.prototype.name = function() {
1134 return this.name_;
1135}
1136
1137
1138PropertyMirror.prototype.isIndexed = function() {
1139 for (var i = 0; i < this.name_.length; i++) {
1140 if (this.name_[i] < '0' || '9' < this.name_[i]) {
1141 return false;
1142 }
1143 }
1144 return true;
1145}
1146
1147
1148PropertyMirror.prototype.value = function() {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001149 return MakeMirror(this.value_, false);
ager@chromium.org32912102009-01-16 10:38:43 +00001150}
1151
1152
1153/**
1154 * Returns whether this property value is an exception.
1155 * @return {booolean} True if this property value is an exception
1156 */
1157PropertyMirror.prototype.isException = function() {
1158 return this.exception_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001159}
1160
1161
1162PropertyMirror.prototype.attributes = function() {
1163 return %DebugPropertyAttributesFromDetails(this.details_);
1164}
1165
1166
1167PropertyMirror.prototype.propertyType = function() {
1168 return %DebugPropertyTypeFromDetails(this.details_);
1169}
1170
1171
1172PropertyMirror.prototype.insertionIndex = function() {
1173 return %DebugPropertyIndexFromDetails(this.details_);
1174}
1175
1176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177/**
ager@chromium.org32912102009-01-16 10:38:43 +00001178 * Returns whether this property has a getter defined through __defineGetter__.
1179 * @return {booolean} True if this property has a getter
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001180 */
ager@chromium.org32912102009-01-16 10:38:43 +00001181PropertyMirror.prototype.hasGetter = function() {
1182 return this.getter_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183}
1184
1185
1186/**
ager@chromium.org32912102009-01-16 10:38:43 +00001187 * Returns whether this property has a setter defined through __defineSetter__.
1188 * @return {booolean} True if this property has a setter
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001189 */
ager@chromium.org32912102009-01-16 10:38:43 +00001190PropertyMirror.prototype.hasSetter = function() {
1191 return this.setter_ ? true : false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001192}
1193
1194
1195/**
ager@chromium.org32912102009-01-16 10:38:43 +00001196 * Returns the getter for this property defined through __defineGetter__.
1197 * @return {Mirror} FunctionMirror reflecting the getter function or
1198 * UndefinedMirror if there is no getter for this property
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001199 */
ager@chromium.org32912102009-01-16 10:38:43 +00001200PropertyMirror.prototype.getter = function() {
1201 if (this.hasGetter()) {
1202 return MakeMirror(this.getter_);
1203 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001204 return GetUndefinedMirror();
ager@chromium.org32912102009-01-16 10:38:43 +00001205 }
1206}
1207
1208
1209/**
1210 * Returns the setter for this property defined through __defineSetter__.
1211 * @return {Mirror} FunctionMirror reflecting the setter function or
1212 * UndefinedMirror if there is no setter for this property
1213 */
1214PropertyMirror.prototype.setter = function() {
1215 if (this.hasSetter()) {
1216 return MakeMirror(this.setter_);
1217 } else {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001218 return GetUndefinedMirror();
ager@chromium.org32912102009-01-16 10:38:43 +00001219 }
1220}
1221
1222
1223/**
1224 * Returns whether this property is natively implemented by the host or a set
1225 * through JavaScript code.
lrn@chromium.org25156de2010-04-06 13:10:27 +00001226 * @return {boolean} True if the property is
ager@chromium.org32912102009-01-16 10:38:43 +00001227 * UndefinedMirror if there is no setter for this property
1228 */
1229PropertyMirror.prototype.isNative = function() {
1230 return (this.propertyType() == PropertyType.Interceptor) ||
1231 ((this.propertyType() == PropertyType.Callbacks) &&
1232 !this.hasGetter() && !this.hasSetter());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001233}
1234
1235
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001236const kFrameDetailsFrameIdIndex = 0;
1237const kFrameDetailsReceiverIndex = 1;
1238const kFrameDetailsFunctionIndex = 2;
1239const kFrameDetailsArgumentCountIndex = 3;
1240const kFrameDetailsLocalCountIndex = 4;
1241const kFrameDetailsSourcePositionIndex = 5;
1242const kFrameDetailsConstructCallIndex = 6;
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001243const kFrameDetailsAtReturnIndex = 7;
1244const kFrameDetailsDebuggerFrameIndex = 8;
1245const kFrameDetailsFirstDynamicIndex = 9;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001246
1247const kFrameDetailsNameIndex = 0;
1248const kFrameDetailsValueIndex = 1;
1249const kFrameDetailsNameValueSize = 2;
1250
1251/**
1252 * Wrapper for the frame details information retreived from the VM. The frame
1253 * details from the VM is an array with the following content. See runtime.cc
1254 * Runtime_GetFrameDetails.
1255 * 0: Id
1256 * 1: Receiver
1257 * 2: Function
1258 * 3: Argument count
1259 * 4: Local count
1260 * 5: Source position
1261 * 6: Construct call
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001262 * 7: Is at return
1263 * 8: Debugger frame
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001264 * Arguments name, value
1265 * Locals name, value
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001266 * Return value if any
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001267 * @param {number} break_id Current break id
1268 * @param {number} index Frame number
1269 * @constructor
1270 */
1271function FrameDetails(break_id, index) {
1272 this.break_id_ = break_id;
1273 this.details_ = %GetFrameDetails(break_id, index);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001274}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275
1276
1277FrameDetails.prototype.frameId = function() {
1278 %CheckExecutionState(this.break_id_);
1279 return this.details_[kFrameDetailsFrameIdIndex];
1280}
1281
1282
1283FrameDetails.prototype.receiver = function() {
1284 %CheckExecutionState(this.break_id_);
1285 return this.details_[kFrameDetailsReceiverIndex];
1286}
1287
1288
1289FrameDetails.prototype.func = function() {
1290 %CheckExecutionState(this.break_id_);
1291 return this.details_[kFrameDetailsFunctionIndex];
1292}
1293
1294
1295FrameDetails.prototype.isConstructCall = function() {
1296 %CheckExecutionState(this.break_id_);
1297 return this.details_[kFrameDetailsConstructCallIndex];
1298}
1299
1300
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001301FrameDetails.prototype.isAtReturn = function() {
1302 %CheckExecutionState(this.break_id_);
1303 return this.details_[kFrameDetailsAtReturnIndex];
1304}
1305
1306
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001307FrameDetails.prototype.isDebuggerFrame = function() {
1308 %CheckExecutionState(this.break_id_);
1309 return this.details_[kFrameDetailsDebuggerFrameIndex];
1310}
1311
1312
1313FrameDetails.prototype.argumentCount = function() {
1314 %CheckExecutionState(this.break_id_);
1315 return this.details_[kFrameDetailsArgumentCountIndex];
1316}
1317
1318
1319FrameDetails.prototype.argumentName = function(index) {
1320 %CheckExecutionState(this.break_id_);
1321 if (index >= 0 && index < this.argumentCount()) {
1322 return this.details_[kFrameDetailsFirstDynamicIndex +
1323 index * kFrameDetailsNameValueSize +
1324 kFrameDetailsNameIndex]
1325 }
1326}
1327
1328
1329FrameDetails.prototype.argumentValue = function(index) {
1330 %CheckExecutionState(this.break_id_);
1331 if (index >= 0 && index < this.argumentCount()) {
1332 return this.details_[kFrameDetailsFirstDynamicIndex +
1333 index * kFrameDetailsNameValueSize +
1334 kFrameDetailsValueIndex]
1335 }
1336}
1337
1338
1339FrameDetails.prototype.localCount = function() {
1340 %CheckExecutionState(this.break_id_);
1341 return this.details_[kFrameDetailsLocalCountIndex];
1342}
1343
1344
1345FrameDetails.prototype.sourcePosition = function() {
1346 %CheckExecutionState(this.break_id_);
1347 return this.details_[kFrameDetailsSourcePositionIndex];
1348}
1349
1350
1351FrameDetails.prototype.localName = function(index) {
1352 %CheckExecutionState(this.break_id_);
1353 if (index >= 0 && index < this.localCount()) {
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001354 var locals_offset = kFrameDetailsFirstDynamicIndex +
1355 this.argumentCount() * kFrameDetailsNameValueSize
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356 return this.details_[locals_offset +
1357 index * kFrameDetailsNameValueSize +
1358 kFrameDetailsNameIndex]
1359 }
1360}
1361
1362
1363FrameDetails.prototype.localValue = function(index) {
1364 %CheckExecutionState(this.break_id_);
1365 if (index >= 0 && index < this.localCount()) {
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001366 var locals_offset = kFrameDetailsFirstDynamicIndex +
1367 this.argumentCount() * kFrameDetailsNameValueSize
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001368 return this.details_[locals_offset +
1369 index * kFrameDetailsNameValueSize +
1370 kFrameDetailsValueIndex]
1371 }
1372}
1373
1374
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001375FrameDetails.prototype.returnValue = function() {
1376 %CheckExecutionState(this.break_id_);
1377 var return_value_offset =
1378 kFrameDetailsFirstDynamicIndex +
1379 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize;
1380 if (this.details_[kFrameDetailsAtReturnIndex]) {
1381 return this.details_[return_value_offset];
1382 }
1383}
1384
1385
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001386FrameDetails.prototype.scopeCount = function() {
1387 return %GetScopeCount(this.break_id_, this.frameId());
1388}
1389
1390
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001391/**
1392 * Mirror object for stack frames.
1393 * @param {number} break_id The break id in the VM for which this frame is
1394 valid
1395 * @param {number} index The frame index (top frame is index 0)
1396 * @constructor
1397 * @extends Mirror
1398 */
1399function FrameMirror(break_id, index) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001400 %_CallFunction(this, FRAME_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401 this.break_id_ = break_id;
1402 this.index_ = index;
1403 this.details_ = new FrameDetails(break_id, index);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001404}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405inherits(FrameMirror, Mirror);
1406
1407
1408FrameMirror.prototype.index = function() {
1409 return this.index_;
1410};
1411
1412
1413FrameMirror.prototype.func = function() {
1414 // Get the function for this frame from the VM.
1415 var f = this.details_.func();
lrn@chromium.org25156de2010-04-06 13:10:27 +00001416
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417 // Create a function mirror. NOTE: MakeMirror cannot be used here as the
1418 // value returned from the VM might be a string if the function for the
1419 // frame is unresolved.
1420 if (IS_FUNCTION(f)) {
ager@chromium.org32912102009-01-16 10:38:43 +00001421 return MakeMirror(f);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001422 } else {
1423 return new UnresolvedFunctionMirror(f);
1424 }
1425};
1426
1427
1428FrameMirror.prototype.receiver = function() {
1429 return MakeMirror(this.details_.receiver());
1430};
1431
1432
1433FrameMirror.prototype.isConstructCall = function() {
1434 return this.details_.isConstructCall();
1435};
1436
1437
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001438FrameMirror.prototype.isAtReturn = function() {
1439 return this.details_.isAtReturn();
1440};
1441
1442
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001443FrameMirror.prototype.isDebuggerFrame = function() {
1444 return this.details_.isDebuggerFrame();
1445};
1446
1447
1448FrameMirror.prototype.argumentCount = function() {
1449 return this.details_.argumentCount();
1450};
1451
1452
1453FrameMirror.prototype.argumentName = function(index) {
1454 return this.details_.argumentName(index);
1455};
1456
1457
1458FrameMirror.prototype.argumentValue = function(index) {
1459 return MakeMirror(this.details_.argumentValue(index));
1460};
1461
1462
1463FrameMirror.prototype.localCount = function() {
1464 return this.details_.localCount();
1465};
1466
1467
1468FrameMirror.prototype.localName = function(index) {
1469 return this.details_.localName(index);
1470};
1471
1472
1473FrameMirror.prototype.localValue = function(index) {
1474 return MakeMirror(this.details_.localValue(index));
1475};
1476
1477
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001478FrameMirror.prototype.returnValue = function() {
1479 return MakeMirror(this.details_.returnValue());
1480};
1481
1482
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001483FrameMirror.prototype.sourcePosition = function() {
1484 return this.details_.sourcePosition();
1485};
1486
1487
1488FrameMirror.prototype.sourceLocation = function() {
1489 if (this.func().resolved() && this.func().script()) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001490 return this.func().script().locationFromPosition(this.sourcePosition(),
1491 true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001492 }
1493};
1494
1495
1496FrameMirror.prototype.sourceLine = function() {
1497 if (this.func().resolved()) {
1498 var location = this.sourceLocation();
1499 if (location) {
1500 return location.line;
1501 }
1502 }
1503};
1504
1505
1506FrameMirror.prototype.sourceColumn = function() {
1507 if (this.func().resolved()) {
1508 var location = this.sourceLocation();
1509 if (location) {
1510 return location.column;
1511 }
1512 }
1513};
1514
1515
1516FrameMirror.prototype.sourceLineText = function() {
1517 if (this.func().resolved()) {
1518 var location = this.sourceLocation();
1519 if (location) {
1520 return location.sourceText();
1521 }
1522 }
1523};
1524
1525
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001526FrameMirror.prototype.scopeCount = function() {
1527 return this.details_.scopeCount();
1528};
1529
1530
1531FrameMirror.prototype.scope = function(index) {
1532 return new ScopeMirror(this, index);
1533};
1534
1535
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001536FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001537 var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001538 source, Boolean(disable_break), opt_context_object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539 return MakeMirror(result);
1540};
1541
1542
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001543FrameMirror.prototype.invocationText = function() {
1544 // Format frame invoaction (receiver, function and arguments).
1545 var result = '';
1546 var func = this.func();
1547 var receiver = this.receiver();
1548 if (this.isConstructCall()) {
1549 // For constructor frames display new followed by the function name.
1550 result += 'new ';
1551 result += func.name() ? func.name() : '[anonymous]';
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001552 } else if (this.isDebuggerFrame()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001553 result += '[debugger]';
1554 } else {
1555 // If the receiver has a className which is 'global' don't display it.
1556 var display_receiver = !receiver.className || receiver.className() != 'global';
1557 if (display_receiver) {
1558 result += receiver.toText();
1559 }
1560 // Try to find the function as a property in the receiver. Include the
1561 // prototype chain in the lookup.
ager@chromium.org32912102009-01-16 10:38:43 +00001562 var property = GetUndefinedMirror();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001563 if (!receiver.isUndefined()) {
1564 for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) {
1565 property = r.lookupProperty(func);
1566 }
1567 }
1568 if (!property.isUndefined()) {
1569 // The function invoked was found on the receiver. Use the property name
1570 // for the backtrace.
1571 if (!property.isIndexed()) {
1572 if (display_receiver) {
1573 result += '.';
1574 }
1575 result += property.name();
1576 } else {
1577 result += '[';
1578 result += property.name();
1579 result += ']';
1580 }
1581 // Also known as - if the name in the function doesn't match the name
1582 // under which it was looked up.
1583 if (func.name() && func.name() != property.name()) {
1584 result += '(aka ' + func.name() + ')';
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001585 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001586 } else {
1587 // The function invoked was not found on the receiver. Use the function
1588 // name if available for the backtrace.
1589 if (display_receiver) {
1590 result += '.';
1591 }
1592 result += func.name() ? func.name() : '[anonymous]';
1593 }
1594 }
1595
1596 // Render arguments for normal frames.
1597 if (!this.isDebuggerFrame()) {
1598 result += '(';
1599 for (var i = 0; i < this.argumentCount(); i++) {
1600 if (i != 0) result += ', ';
1601 if (this.argumentName(i)) {
1602 result += this.argumentName(i);
1603 result += '=';
1604 }
1605 result += this.argumentValue(i).toText();
1606 }
1607 result += ')';
1608 }
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001609
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00001610 if (this.isAtReturn()) {
1611 result += ' returning ';
1612 result += this.returnValue().toText();
1613 }
vegorov@chromium.org42841962010-10-18 11:18:59 +00001614
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001615 return result;
1616}
1617
1618
1619FrameMirror.prototype.sourceAndPositionText = function() {
1620 // Format source and position.
1621 var result = '';
1622 var func = this.func();
1623 if (func.resolved()) {
1624 if (func.script()) {
1625 if (func.script().name()) {
1626 result += func.script().name();
1627 } else {
1628 result += '[unnamed]';
1629 }
1630 if (!this.isDebuggerFrame()) {
1631 var location = this.sourceLocation();
1632 result += ' line ';
1633 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?';
1634 result += ' column ';
1635 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?';
1636 if (!IS_UNDEFINED(this.sourcePosition())) {
1637 result += ' (position ' + (this.sourcePosition() + 1) + ')';
1638 }
1639 }
1640 } else {
1641 result += '[no source]';
1642 }
1643 } else {
1644 result += '[unresolved]';
1645 }
1646
1647 return result;
1648}
1649
1650
1651FrameMirror.prototype.localsText = function() {
1652 // Format local variables.
1653 var result = '';
1654 var locals_count = this.localCount()
1655 if (locals_count > 0) {
1656 for (var i = 0; i < locals_count; ++i) {
1657 result += ' var ';
1658 result += this.localName(i);
1659 result += ' = ';
1660 result += this.localValue(i).toText();
1661 if (i < locals_count - 1) result += '\n';
1662 }
1663 }
1664
1665 return result;
1666}
1667
1668
1669FrameMirror.prototype.toText = function(opt_locals) {
1670 var result = '';
1671 result += '#' + (this.index() <= 9 ? '0' : '') + this.index();
1672 result += ' ';
1673 result += this.invocationText();
1674 result += ' ';
1675 result += this.sourceAndPositionText();
1676 if (opt_locals) {
1677 result += '\n';
1678 result += this.localsText();
1679 }
1680 return result;
1681}
1682
1683
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001684const kScopeDetailsTypeIndex = 0;
1685const kScopeDetailsObjectIndex = 1;
1686
1687function ScopeDetails(frame, index) {
1688 this.break_id_ = frame.break_id_;
1689 this.details_ = %GetScopeDetails(frame.break_id_,
1690 frame.details_.frameId(),
1691 index);
1692}
1693
1694
1695ScopeDetails.prototype.type = function() {
1696 %CheckExecutionState(this.break_id_);
1697 return this.details_[kScopeDetailsTypeIndex];
1698}
1699
1700
1701ScopeDetails.prototype.object = function() {
1702 %CheckExecutionState(this.break_id_);
1703 return this.details_[kScopeDetailsObjectIndex];
1704}
1705
1706
1707/**
1708 * Mirror object for scope.
1709 * @param {FrameMirror} frame The frame this scope is a part of
1710 * @param {number} index The scope index in the frame
1711 * @constructor
1712 * @extends Mirror
1713 */
1714function ScopeMirror(frame, index) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001715 %_CallFunction(this, SCOPE_TYPE, Mirror);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001716 this.frame_index_ = frame.index_;
1717 this.scope_index_ = index;
1718 this.details_ = new ScopeDetails(frame, index);
1719}
1720inherits(ScopeMirror, Mirror);
1721
1722
1723ScopeMirror.prototype.frameIndex = function() {
1724 return this.frame_index_;
1725};
1726
1727
1728ScopeMirror.prototype.scopeIndex = function() {
1729 return this.scope_index_;
1730};
1731
1732
1733ScopeMirror.prototype.scopeType = function() {
1734 return this.details_.type();
1735};
1736
1737
1738ScopeMirror.prototype.scopeObject = function() {
1739 // For local and closure scopes create a transient mirror as these objects are
1740 // created on the fly materializing the local or closure scopes and
1741 // therefore will not preserve identity.
1742 var transient = this.scopeType() == ScopeType.Local ||
1743 this.scopeType() == ScopeType.Closure;
1744 return MakeMirror(this.details_.object(), transient);
1745};
1746
1747
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001748/**
1749 * Mirror object for script source.
1750 * @param {Script} script The script object
1751 * @constructor
1752 * @extends Mirror
1753 */
1754function ScriptMirror(script) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001755 %_CallFunction(this, SCRIPT_TYPE, Mirror);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001756 this.script_ = script;
ager@chromium.org9085a012009-05-11 19:22:57 +00001757 this.context_ = new ContextMirror(script.context_data);
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001758 this.allocateHandle_();
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001759}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001760inherits(ScriptMirror, Mirror);
1761
1762
iposva@chromium.org245aa852009-02-10 00:49:54 +00001763ScriptMirror.prototype.value = function() {
1764 return this.script_;
1765};
1766
1767
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001768ScriptMirror.prototype.name = function() {
lrn@chromium.org25156de2010-04-06 13:10:27 +00001769 return this.script_.name || this.script_.nameOrSourceURL();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001770};
1771
1772
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001773ScriptMirror.prototype.id = function() {
1774 return this.script_.id;
1775};
1776
1777
iposva@chromium.org245aa852009-02-10 00:49:54 +00001778ScriptMirror.prototype.source = function() {
1779 return this.script_.source;
1780};
1781
1782
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001783ScriptMirror.prototype.lineOffset = function() {
1784 return this.script_.line_offset;
1785};
1786
1787
1788ScriptMirror.prototype.columnOffset = function() {
1789 return this.script_.column_offset;
1790};
1791
1792
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001793ScriptMirror.prototype.data = function() {
1794 return this.script_.data;
1795};
1796
1797
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001798ScriptMirror.prototype.scriptType = function() {
1799 return this.script_.type;
1800};
1801
1802
ager@chromium.orge2902be2009-06-08 12:21:35 +00001803ScriptMirror.prototype.compilationType = function() {
1804 return this.script_.compilation_type;
1805};
1806
1807
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001808ScriptMirror.prototype.lineCount = function() {
1809 return this.script_.lineCount();
1810};
1811
1812
ager@chromium.org3a6061e2009-03-12 14:24:36 +00001813ScriptMirror.prototype.locationFromPosition = function(
1814 position, include_resource_offset) {
1815 return this.script_.locationFromPosition(position, include_resource_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001816}
1817
1818
1819ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
1820 return this.script_.sourceSlice(opt_from_line, opt_to_line);
1821}
1822
1823
ager@chromium.org9085a012009-05-11 19:22:57 +00001824ScriptMirror.prototype.context = function() {
1825 return this.context_;
1826};
1827
1828
sgjesse@chromium.org98180592009-12-02 08:17:28 +00001829ScriptMirror.prototype.evalFromScript = function() {
1830 return MakeMirror(this.script_.eval_from_script);
1831};
1832
1833
1834ScriptMirror.prototype.evalFromFunctionName = function() {
1835 return MakeMirror(this.script_.eval_from_function_name);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001836};
1837
1838
1839ScriptMirror.prototype.evalFromLocation = function() {
sgjesse@chromium.org98180592009-12-02 08:17:28 +00001840 var eval_from_script = this.evalFromScript();
1841 if (!eval_from_script.isUndefined()) {
1842 var position = this.script_.eval_from_script_position;
1843 return eval_from_script.locationFromPosition(position, true);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001844 }
1845};
1846
1847
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001848ScriptMirror.prototype.toText = function() {
1849 var result = '';
1850 result += this.name();
1851 result += ' (lines: ';
1852 if (this.lineOffset() > 0) {
1853 result += this.lineOffset();
1854 result += '-';
1855 result += this.lineOffset() + this.lineCount() - 1;
1856 } else {
1857 result += this.lineCount();
1858 }
1859 result += ')';
1860 return result;
1861}
1862
1863
ager@chromium.org32912102009-01-16 10:38:43 +00001864/**
ager@chromium.org9085a012009-05-11 19:22:57 +00001865 * Mirror object for context.
1866 * @param {Object} data The context data
1867 * @constructor
1868 * @extends Mirror
1869 */
1870function ContextMirror(data) {
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001871 %_CallFunction(this, CONTEXT_TYPE, Mirror);
ager@chromium.org9085a012009-05-11 19:22:57 +00001872 this.data_ = data;
1873 this.allocateHandle_();
1874}
1875inherits(ContextMirror, Mirror);
1876
1877
1878ContextMirror.prototype.data = function() {
1879 return this.data_;
1880};
1881
1882
1883/**
ager@chromium.org32912102009-01-16 10:38:43 +00001884 * Returns a mirror serializer
1885 *
1886 * @param {boolean} details Set to true to include details
ager@chromium.org9085a012009-05-11 19:22:57 +00001887 * @param {Object} options Options comtrolling the serialization
1888 * The following options can be set:
1889 * includeSource: include ths full source of scripts
ager@chromium.org32912102009-01-16 10:38:43 +00001890 * @returns {MirrorSerializer} mirror serializer
1891 */
ager@chromium.org9085a012009-05-11 19:22:57 +00001892function MakeMirrorSerializer(details, options) {
1893 return new JSONProtocolSerializer(details, options);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00001894}
1895
1896
ager@chromium.org32912102009-01-16 10:38:43 +00001897/**
1898 * Object for serializing a mirror objects and its direct references.
1899 * @param {boolean} details Indicates whether to include details for the mirror
1900 * serialized
1901 * @constructor
1902 */
ager@chromium.org9085a012009-05-11 19:22:57 +00001903function JSONProtocolSerializer(details, options) {
ager@chromium.org32912102009-01-16 10:38:43 +00001904 this.details_ = details;
ager@chromium.org9085a012009-05-11 19:22:57 +00001905 this.options_ = options;
ager@chromium.org32912102009-01-16 10:38:43 +00001906 this.mirrors_ = [ ];
1907}
1908
1909
1910/**
1911 * Returns a serialization of an object reference. The referenced object are
1912 * added to the serialization state.
1913 *
1914 * @param {Mirror} mirror The mirror to serialize
1915 * @returns {String} JSON serialization
1916 */
1917JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
1918 return this.serialize_(mirror, true, true);
1919}
1920
1921
1922/**
1923 * Returns a serialization of an object value. The referenced objects are
1924 * added to the serialization state.
1925 *
1926 * @param {Mirror} mirror The mirror to serialize
1927 * @returns {String} JSON serialization
1928 */
1929JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
1930 var json = this.serialize_(mirror, false, true);
1931 return json;
1932}
1933
1934
1935/**
1936 * Returns a serialization of all the objects referenced.
1937 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001938 * @param {Mirror} mirror The mirror to serialize.
1939 * @returns {Array.<Object>} Array of the referenced objects converted to
1940 * protcol objects.
ager@chromium.org32912102009-01-16 10:38:43 +00001941 */
1942JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001943 // Collect the protocol representation of the referenced objects in an array.
1944 var content = [];
lrn@chromium.org25156de2010-04-06 13:10:27 +00001945
ager@chromium.org32912102009-01-16 10:38:43 +00001946 // Get the number of referenced objects.
1947 var count = this.mirrors_.length;
lrn@chromium.org25156de2010-04-06 13:10:27 +00001948
ager@chromium.org32912102009-01-16 10:38:43 +00001949 for (var i = 0; i < count; i++) {
1950 content.push(this.serialize_(this.mirrors_[i], false, false));
1951 }
1952
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001953 return content;
ager@chromium.org32912102009-01-16 10:38:43 +00001954}
1955
1956
ager@chromium.org9085a012009-05-11 19:22:57 +00001957JSONProtocolSerializer.prototype.includeSource_ = function() {
1958 return this.options_ && this.options_.includeSource;
1959}
1960
1961
ager@chromium.org3e875802009-06-29 08:26:34 +00001962JSONProtocolSerializer.prototype.inlineRefs_ = function() {
1963 return this.options_ && this.options_.inlineRefs;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001964}
1965
1966
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001967JSONProtocolSerializer.prototype.maxStringLength_ = function() {
1968 if (IS_UNDEFINED(this.options_) ||
1969 IS_UNDEFINED(this.options_.maxStringLength)) {
1970 return kMaxProtocolStringLength;
1971 }
1972 return this.options_.maxStringLength;
1973}
1974
1975
ager@chromium.org32912102009-01-16 10:38:43 +00001976JSONProtocolSerializer.prototype.add_ = function(mirror) {
1977 // If this mirror is already in the list just return.
1978 for (var i = 0; i < this.mirrors_.length; i++) {
1979 if (this.mirrors_[i] === mirror) {
1980 return;
1981 }
1982 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00001983
ager@chromium.org32912102009-01-16 10:38:43 +00001984 // Add the mirror to the list of mirrors to be serialized.
1985 this.mirrors_.push(mirror);
1986}
1987
1988
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001989/**
1990 * Formats mirror object to protocol reference object with some data that can
1991 * be used to display the value in debugger.
1992 * @param {Mirror} mirror Mirror to serialize.
1993 * @return {Object} Protocol reference object.
1994 */
lrn@chromium.org25156de2010-04-06 13:10:27 +00001995JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001996 function(mirror) {
1997 var o = {};
1998 o.ref = mirror.handle();
1999 o.type = mirror.type();
2000 switch (mirror.type()) {
2001 case UNDEFINED_TYPE:
2002 case NULL_TYPE:
2003 case BOOLEAN_TYPE:
2004 case NUMBER_TYPE:
2005 o.value = mirror.value();
2006 break;
2007 case STRING_TYPE:
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002008 o.value = mirror.getTruncatedValue(this.maxStringLength_());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002009 break;
2010 case FUNCTION_TYPE:
2011 o.name = mirror.name();
2012 o.inferredName = mirror.inferredName();
2013 if (mirror.script()) {
2014 o.scriptId = mirror.script().id();
2015 }
2016 break;
2017 case ERROR_TYPE:
2018 case REGEXP_TYPE:
2019 o.value = mirror.toText();
2020 break;
2021 case OBJECT_TYPE:
2022 o.className = mirror.className();
2023 break;
2024 }
2025 return o;
2026};
2027
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002028
ager@chromium.org32912102009-01-16 10:38:43 +00002029JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
2030 details) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00002031 // If serializing a reference to a mirror just return the reference and add
2032 // the mirror to the referenced mirrors.
2033 if (reference &&
ager@chromium.org9085a012009-05-11 19:22:57 +00002034 (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
ager@chromium.org3e875802009-06-29 08:26:34 +00002035 if (this.inlineRefs_() && mirror.isValue()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002036 return this.serializeReferenceWithDisplayData_(mirror);
2037 } else {
2038 this.add_(mirror);
2039 return {'ref' : mirror.handle()};
2040 }
ager@chromium.org32912102009-01-16 10:38:43 +00002041 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002042
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002043 // Collect the JSON property/value pairs.
2044 var content = {};
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002045
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002046 // Add the mirror handle.
ager@chromium.org9085a012009-05-11 19:22:57 +00002047 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002048 content.handle = mirror.handle();
ager@chromium.org32912102009-01-16 10:38:43 +00002049 }
2050
2051 // Always add the type.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002052 content.type = mirror.type();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002053
2054 switch (mirror.type()) {
2055 case UNDEFINED_TYPE:
2056 case NULL_TYPE:
2057 // Undefined and null are represented just by their type.
2058 break;
2059
2060 case BOOLEAN_TYPE:
2061 // Boolean values are simply represented by their value.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002062 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002063 break;
2064
2065 case NUMBER_TYPE:
2066 // Number values are simply represented by their value.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002067 content.value = NumberToJSON_(mirror.value());
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002068 break;
2069
2070 case STRING_TYPE:
2071 // String values might have their value cropped to keep down size.
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002072 if (this.maxStringLength_() != -1 &&
2073 mirror.length() > this.maxStringLength_()) {
2074 var str = mirror.getTruncatedValue(this.maxStringLength_());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002075 content.value = str;
2076 content.fromIndex = 0;
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00002077 content.toIndex = this.maxStringLength_();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002078 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002079 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002080 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002081 content.length = mirror.length();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002082 break;
2083
2084 case OBJECT_TYPE:
2085 case FUNCTION_TYPE:
2086 case ERROR_TYPE:
2087 case REGEXP_TYPE:
2088 // Add object representation.
ager@chromium.org32912102009-01-16 10:38:43 +00002089 this.serializeObject_(mirror, content, details);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002090 break;
2091
2092 case PROPERTY_TYPE:
ager@chromium.org32912102009-01-16 10:38:43 +00002093 throw new Error('PropertyMirror cannot be serialized independeltly')
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002094 break;
2095
2096 case FRAME_TYPE:
2097 // Add object representation.
2098 this.serializeFrame_(mirror, content);
2099 break;
2100
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002101 case SCOPE_TYPE:
2102 // Add object representation.
2103 this.serializeScope_(mirror, content);
2104 break;
2105
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002106 case SCRIPT_TYPE:
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002107 // Script is represented by id, name and source attributes.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002108 if (mirror.name()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002109 content.name = mirror.name();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002110 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002111 content.id = mirror.id();
2112 content.lineOffset = mirror.lineOffset();
2113 content.columnOffset = mirror.columnOffset();
2114 content.lineCount = mirror.lineCount();
ager@chromium.org9085a012009-05-11 19:22:57 +00002115 if (mirror.data()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002116 content.data = mirror.data();
ager@chromium.org9085a012009-05-11 19:22:57 +00002117 }
2118 if (this.includeSource_()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002119 content.source = mirror.source();
ager@chromium.org9085a012009-05-11 19:22:57 +00002120 } else {
2121 var sourceStart = mirror.source().substring(0, 80);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002122 content.sourceStart = sourceStart;
ager@chromium.org9085a012009-05-11 19:22:57 +00002123 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002124 content.sourceLength = mirror.source().length;
2125 content.scriptType = mirror.scriptType();
ager@chromium.orge2902be2009-06-08 12:21:35 +00002126 content.compilationType = mirror.compilationType();
sgjesse@chromium.org636edf42009-06-18 14:43:07 +00002127 // For compilation type eval emit information on the script from which
2128 // eval was called if a script is present.
2129 if (mirror.compilationType() == 1 &&
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002130 mirror.evalFromScript()) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00002131 content.evalFromScript =
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002132 this.serializeReference(mirror.evalFromScript());
ager@chromium.orge2902be2009-06-08 12:21:35 +00002133 var evalFromLocation = mirror.evalFromLocation()
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002134 if (evalFromLocation) {
2135 content.evalFromLocation = { line: evalFromLocation.line,
2136 column: evalFromLocation.column };
2137 }
sgjesse@chromium.org98180592009-12-02 08:17:28 +00002138 if (mirror.evalFromFunctionName()) {
2139 content.evalFromFunctionName = mirror.evalFromFunctionName();
2140 }
ager@chromium.orge2902be2009-06-08 12:21:35 +00002141 }
ager@chromium.org9085a012009-05-11 19:22:57 +00002142 if (mirror.context()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002143 content.context = this.serializeReference(mirror.context());
ager@chromium.org9085a012009-05-11 19:22:57 +00002144 }
2145 break;
2146
2147 case CONTEXT_TYPE:
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002148 content.data = mirror.data();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002149 break;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002150 }
2151
2152 // Always add the text representation.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002153 content.text = mirror.toText();
lrn@chromium.org25156de2010-04-06 13:10:27 +00002154
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002155 // Create and return the JSON string.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002156 return content;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002157}
2158
2159
ager@chromium.org32912102009-01-16 10:38:43 +00002160/**
2161 * Serialize object information to the following JSON format.
2162 *
2163 * {"className":"<class name>",
2164 * "constructorFunction":{"ref":<number>},
2165 * "protoObject":{"ref":<number>},
2166 * "prototypeObject":{"ref":<number>},
2167 * "namedInterceptor":<boolean>,
2168 * "indexedInterceptor":<boolean>,
2169 * "properties":[<properties>]}
2170 */
2171JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
2172 details) {
2173 // Add general object properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002174 content.className = mirror.className();
2175 content.constructorFunction =
2176 this.serializeReference(mirror.constructorFunction());
2177 content.protoObject = this.serializeReference(mirror.protoObject());
2178 content.prototypeObject = this.serializeReference(mirror.prototypeObject());
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002179
ager@chromium.org32912102009-01-16 10:38:43 +00002180 // Add flags to indicate whether there are interceptors.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002181 if (mirror.hasNamedInterceptor()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002182 content.namedInterceptor = true;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002183 }
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002184 if (mirror.hasIndexedInterceptor()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002185 content.indexedInterceptor = true;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002186 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002187
ager@chromium.org32912102009-01-16 10:38:43 +00002188 // Add function specific properties.
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002189 if (mirror.isFunction()) {
2190 // Add function specific properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002191 content.name = mirror.name();
ager@chromium.org9085a012009-05-11 19:22:57 +00002192 if (!IS_UNDEFINED(mirror.inferredName())) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002193 content.inferredName = mirror.inferredName();
ager@chromium.org9085a012009-05-11 19:22:57 +00002194 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002195 content.resolved = mirror.resolved();
ager@chromium.org32912102009-01-16 10:38:43 +00002196 if (mirror.resolved()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002197 content.source = mirror.source();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002198 }
2199 if (mirror.script()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002200 content.script = this.serializeReference(mirror.script());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002201 content.scriptId = mirror.script().id();
lrn@chromium.org25156de2010-04-06 13:10:27 +00002202
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002203 serializeLocationFields(mirror.sourceLocation(), content);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002204 }
ager@chromium.org32912102009-01-16 10:38:43 +00002205 }
2206
2207 // Add date specific properties.
2208 if (mirror.isDate()) {
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002209 // Add date specific properties.
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002210 content.value = mirror.value();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002211 }
ager@chromium.org32912102009-01-16 10:38:43 +00002212
2213 // Add actual properties - named properties followed by indexed properties.
2214 var propertyNames = mirror.propertyNames(PropertyKind.Named);
2215 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed);
2216 var p = new Array(propertyNames.length + propertyIndexes.length);
2217 for (var i = 0; i < propertyNames.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002218 var propertyMirror = mirror.property(propertyNames[i]);
2219 p[i] = this.serializeProperty_(propertyMirror);
ager@chromium.org32912102009-01-16 10:38:43 +00002220 if (details) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002221 this.add_(propertyMirror.value());
ager@chromium.org32912102009-01-16 10:38:43 +00002222 }
2223 }
2224 for (var i = 0; i < propertyIndexes.length; i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002225 var propertyMirror = mirror.property(propertyIndexes[i]);
2226 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror);
ager@chromium.org32912102009-01-16 10:38:43 +00002227 if (details) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002228 this.add_(propertyMirror.value());
ager@chromium.org32912102009-01-16 10:38:43 +00002229 }
2230 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002231 content.properties = p;
ager@chromium.org32912102009-01-16 10:38:43 +00002232}
2233
2234
2235/**
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002236 * Serialize location information to the following JSON format:
2237 *
2238 * "position":"<position>",
2239 * "line":"<line>",
2240 * "column":"<column>",
lrn@chromium.org25156de2010-04-06 13:10:27 +00002241 *
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002242 * @param {SourceLocation} location The location to serialize, may be undefined.
2243 */
2244function serializeLocationFields (location, content) {
2245 if (!location) {
2246 return;
lrn@chromium.org25156de2010-04-06 13:10:27 +00002247 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002248 content.position = location.position;
2249 var line = location.line;
2250 if (!IS_UNDEFINED(line)) {
2251 content.line = line;
2252 }
2253 var column = location.column;
2254 if (!IS_UNDEFINED(column)) {
2255 content.column = column;
2256 }
2257}
2258
2259
2260/**
ager@chromium.org32912102009-01-16 10:38:43 +00002261 * Serialize property information to the following JSON format for building the
2262 * array of properties.
2263 *
2264 * {"name":"<property name>",
2265 * "attributes":<number>,
2266 * "propertyType":<number>,
2267 * "ref":<number>}
2268 *
2269 * If the attribute for the property is PropertyAttribute.None it is not added.
2270 * If the propertyType for the property is PropertyType.Normal it is not added.
2271 * Here are a couple of examples.
2272 *
2273 * {"name":"hello","ref":1}
2274 * {"name":"length","attributes":7,"propertyType":3,"ref":2}
2275 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002276 * @param {PropertyMirror} propertyMirror The property to serialize.
2277 * @returns {Object} Protocol object representing the property.
ager@chromium.org32912102009-01-16 10:38:43 +00002278 */
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002279JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
2280 var result = {};
lrn@chromium.org25156de2010-04-06 13:10:27 +00002281
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002282 result.name = propertyMirror.name();
2283 var propertyValue = propertyMirror.value();
ager@chromium.org3e875802009-06-29 08:26:34 +00002284 if (this.inlineRefs_() && propertyValue.isValue()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002285 result.value = this.serializeReferenceWithDisplayData_(propertyValue);
2286 } else {
2287 if (propertyMirror.attributes() != PropertyAttribute.None) {
2288 result.attributes = propertyMirror.attributes();
2289 }
2290 if (propertyMirror.propertyType() != PropertyType.Normal) {
2291 result.propertyType = propertyMirror.propertyType();
2292 }
2293 result.ref = propertyValue.handle();
ager@chromium.org32912102009-01-16 10:38:43 +00002294 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002295 return result;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002296}
2297
2298
2299JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002300 content.index = mirror.index();
2301 content.receiver = this.serializeReference(mirror.receiver());
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002302 var func = mirror.func();
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002303 content.func = this.serializeReference(func);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002304 if (func.script()) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002305 content.script = this.serializeReference(func.script());
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00002306 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002307 content.constructCall = mirror.isConstructCall();
ager@chromium.org2cc82ae2010-06-14 07:35:38 +00002308 content.atReturn = mirror.isAtReturn();
2309 if (mirror.isAtReturn()) {
2310 content.returnValue = this.serializeReference(mirror.returnValue());
2311 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002312 content.debuggerFrame = mirror.isDebuggerFrame();
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002313 var x = new Array(mirror.argumentCount());
2314 for (var i = 0; i < mirror.argumentCount(); i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002315 var arg = {};
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002316 var argument_name = mirror.argumentName(i)
2317 if (argument_name) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002318 arg.name = argument_name;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002319 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002320 arg.value = this.serializeReference(mirror.argumentValue(i));
2321 x[i] = arg;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002322 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002323 content.arguments = x;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002324 var x = new Array(mirror.localCount());
2325 for (var i = 0; i < mirror.localCount(); i++) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002326 var local = {};
2327 local.name = mirror.localName(i);
2328 local.value = this.serializeReference(mirror.localValue(i));
2329 x[i] = local;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002330 }
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002331 content.locals = x;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002332 serializeLocationFields(mirror.sourceLocation(), content);
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002333 var source_line_text = mirror.sourceLineText();
2334 if (!IS_UNDEFINED(source_line_text)) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002335 content.sourceLineText = source_line_text;
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002336 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002337
ager@chromium.org5aa501c2009-06-23 07:57:28 +00002338 content.scopes = [];
2339 for (var i = 0; i < mirror.scopeCount(); i++) {
2340 var scope = mirror.scope(i);
2341 content.scopes.push({
2342 type: scope.scopeType(),
2343 index: i
2344 });
2345 }
christian.plesner.hansen@gmail.comaca49682009-01-07 14:29:04 +00002346}
2347
2348
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002349JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
2350 content.index = mirror.scopeIndex();
2351 content.frameIndex = mirror.frameIndex();
2352 content.type = mirror.scopeType();
ager@chromium.org3e875802009-06-29 08:26:34 +00002353 content.object = this.inlineRefs_() ?
2354 this.serializeValue(mirror.scopeObject()) :
2355 this.serializeReference(mirror.scopeObject());
ager@chromium.orgeadaf222009-06-16 09:43:10 +00002356}
2357
2358
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002359/**
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002360 * Convert a number to a protocol value. For all finite numbers the number
2361 * itself is returned. For non finite numbers NaN, Infinite and
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002362 * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002363 * (not including the quotes) is returned.
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002364 *
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002365 * @param {number} value The number value to convert to a protocol value.
2366 * @returns {number|string} Protocol value.
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002367 */
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002368function NumberToJSON_(value) {
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002369 if (isNaN(value)) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002370 return 'NaN';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002371 }
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002372 if (!NUMBER_IS_FINITE(value)) {
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002373 if (value > 0) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002374 return 'Infinity';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002375 } else {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002376 return '-Infinity';
sgjesse@chromium.org715915b2009-01-19 16:08:47 +00002377 }
2378 }
lrn@chromium.org25156de2010-04-06 13:10:27 +00002379 return value;
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00002380}