1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Handle id counters. 29 var next_handle_ = 0; 30 var next_transient_handle_ = -1; 31 32 // Mirror cache. 33 var mirror_cache_ = []; 34 35 36 /** 37 * Clear the mirror handle cache. 38 */ 39 function ClearMirrorCache() { 40 next_handle_ = 0; 41 mirror_cache_ = []; 42 } 43 44 45 /** 46 * Returns the mirror for a specified value or object. 47 * 48 * @param {value or Object} value the value or object to retreive the mirror for 49 * @param {boolean} transient indicate whether this object is transient and 50 * should not be added to the mirror cache. The default is not transient. 51 * @returns {Mirror} the mirror reflects the passed value or object 52 */ 53 function MakeMirror(value, opt_transient) { 54 var mirror; 55 56 // Look for non transient mirrors in the mirror cache. 57 if (!opt_transient) { 58 for (id in mirror_cache_) { 59 mirror = mirror_cache_[id]; 60 if (mirror.value() === value) { 61 return mirror; 62 } 63 // Special check for NaN as NaN == NaN is false. 64 if (mirror.isNumber() && isNaN(mirror.value()) && 65 typeof value == 'number' && isNaN(value)) { 66 return mirror; 67 } 68 } 69 } 70 71 if (IS_UNDEFINED(value)) { 72 mirror = new UndefinedMirror(); 73 } else if (IS_NULL(value)) { 74 mirror = new NullMirror(); 75 } else if (IS_BOOLEAN(value)) { 76 mirror = new BooleanMirror(value); 77 } else if (IS_NUMBER(value)) { 78 mirror = new NumberMirror(value); 79 } else if (IS_STRING(value)) { 80 mirror = new StringMirror(value); 81 } else if (IS_ARRAY(value)) { 82 mirror = new ArrayMirror(value); 83 } else if (IS_DATE(value)) { 84 mirror = new DateMirror(value); 85 } else if (IS_FUNCTION(value)) { 86 mirror = new FunctionMirror(value); 87 } else if (IS_REGEXP(value)) { 88 mirror = new RegExpMirror(value); 89 } else if (IS_ERROR(value)) { 90 mirror = new ErrorMirror(value); 91 } else if (IS_SCRIPT(value)) { 92 mirror = new ScriptMirror(value); 93 } else { 94 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient); 95 } 96 97 mirror_cache_[mirror.handle()] = mirror; 98 return mirror; 99 } 100 101 102 /** 103 * Returns the mirror for a specified mirror handle. 104 * 105 * @param {number} handle the handle to find the mirror for 106 * @returns {Mirror or undefiend} the mirror with the requested handle or 107 * undefined if no mirror with the requested handle was found 108 */ 109 function LookupMirror(handle) { 110 return mirror_cache_[handle]; 111 } 112 113 114 /** 115 * Returns the mirror for the undefined value. 116 * 117 * @returns {Mirror} the mirror reflects the undefined value 118 */ 119 function GetUndefinedMirror() { 120 return MakeMirror(void 0); 121 } 122 123 124 /** 125 * Inherit the prototype methods from one constructor into another. 126 * 127 * The Function.prototype.inherits from lang.js rewritten as a standalone 128 * function (not on Function.prototype). NOTE: If this file is to be loaded 129 * during bootstrapping this function needs to be revritten using some native 130 * functions as prototype setup using normal JavaScript does not work as 131 * expected during bootstrapping (see mirror.js in r114903). 132 * 133 * @param {function} ctor Constructor function which needs to inherit the 134 * prototype 135 * @param {function} superCtor Constructor function to inherit prototype from 136 */ 137 function inherits(ctor, superCtor) { 138 var tempCtor = function(){}; 139 tempCtor.prototype = superCtor.prototype; 140 ctor.super_ = superCtor.prototype; 141 ctor.prototype = new tempCtor(); 142 ctor.prototype.constructor = ctor; 143 } 144 145 146 // Type names of the different mirrors. 147 var UNDEFINED_TYPE = 'undefined'; 148 var NULL_TYPE = 'null'; 149 var BOOLEAN_TYPE = 'boolean'; 150 var NUMBER_TYPE = 'number'; 151 var STRING_TYPE = 'string'; 152 var OBJECT_TYPE = 'object'; 153 var FUNCTION_TYPE = 'function'; 154 var REGEXP_TYPE = 'regexp'; 155 var ERROR_TYPE = 'error'; 156 var PROPERTY_TYPE = 'property'; 157 var FRAME_TYPE = 'frame'; 158 var SCRIPT_TYPE = 'script'; 159 var CONTEXT_TYPE = 'context'; 160 var SCOPE_TYPE = 'scope'; 161 162 // Maximum length when sending strings through the JSON protocol. 163 var kMaxProtocolStringLength = 80; 164 165 // Different kind of properties. 166 var PropertyKind = {}; 167 PropertyKind.Named = 1; 168 PropertyKind.Indexed = 2; 169 170 171 // A copy of the PropertyType enum from global.h 172 var PropertyType = {}; 173 PropertyType.Normal = 0; 174 PropertyType.Field = 1; 175 PropertyType.ConstantFunction = 2; 176 PropertyType.Callbacks = 3; 177 PropertyType.Handler = 4; 178 PropertyType.Interceptor = 5; 179 PropertyType.MapTransition = 6; 180 PropertyType.ExternalArrayTransition = 7; 181 PropertyType.ConstantTransition = 8; 182 PropertyType.NullDescriptor = 9; 183 184 185 // Different attributes for a property. 186 var PropertyAttribute = {}; 187 PropertyAttribute.None = NONE; 188 PropertyAttribute.ReadOnly = READ_ONLY; 189 PropertyAttribute.DontEnum = DONT_ENUM; 190 PropertyAttribute.DontDelete = DONT_DELETE; 191 192 193 // A copy of the scope types from runtime.cc. 194 var ScopeType = { Global: 0, 195 Local: 1, 196 With: 2, 197 Closure: 3, 198 Catch: 4, 199 Block: 5 }; 200 201 202 // Mirror hierarchy: 203 // - Mirror 204 // - ValueMirror 205 // - UndefinedMirror 206 // - NullMirror 207 // - NumberMirror 208 // - StringMirror 209 // - ObjectMirror 210 // - FunctionMirror 211 // - UnresolvedFunctionMirror 212 // - ArrayMirror 213 // - DateMirror 214 // - RegExpMirror 215 // - ErrorMirror 216 // - PropertyMirror 217 // - FrameMirror 218 // - ScriptMirror 219 220 221 /** 222 * Base class for all mirror objects. 223 * @param {string} type The type of the mirror 224 * @constructor 225 */ 226 function Mirror(type) { 227 this.type_ = type; 228 } 229 230 231 Mirror.prototype.type = function() { 232 return this.type_; 233 }; 234 235 236 /** 237 * Check whether the mirror reflects a value. 238 * @returns {boolean} True if the mirror reflects a value. 239 */ 240 Mirror.prototype.isValue = function() { 241 return this instanceof ValueMirror; 242 }; 243 244 245 /** 246 * Check whether the mirror reflects the undefined value. 247 * @returns {boolean} True if the mirror reflects the undefined value. 248 */ 249 Mirror.prototype.isUndefined = function() { 250 return this instanceof UndefinedMirror; 251 }; 252 253 254 /** 255 * Check whether the mirror reflects the null value. 256 * @returns {boolean} True if the mirror reflects the null value 257 */ 258 Mirror.prototype.isNull = function() { 259 return this instanceof NullMirror; 260 }; 261 262 263 /** 264 * Check whether the mirror reflects a boolean value. 265 * @returns {boolean} True if the mirror reflects a boolean value 266 */ 267 Mirror.prototype.isBoolean = function() { 268 return this instanceof BooleanMirror; 269 }; 270 271 272 /** 273 * Check whether the mirror reflects a number value. 274 * @returns {boolean} True if the mirror reflects a number value 275 */ 276 Mirror.prototype.isNumber = function() { 277 return this instanceof NumberMirror; 278 }; 279 280 281 /** 282 * Check whether the mirror reflects a string value. 283 * @returns {boolean} True if the mirror reflects a string value 284 */ 285 Mirror.prototype.isString = function() { 286 return this instanceof StringMirror; 287 }; 288 289 290 /** 291 * Check whether the mirror reflects an object. 292 * @returns {boolean} True if the mirror reflects an object 293 */ 294 Mirror.prototype.isObject = function() { 295 return this instanceof ObjectMirror; 296 }; 297 298 299 /** 300 * Check whether the mirror reflects a function. 301 * @returns {boolean} True if the mirror reflects a function 302 */ 303 Mirror.prototype.isFunction = function() { 304 return this instanceof FunctionMirror; 305 }; 306 307 308 /** 309 * Check whether the mirror reflects an unresolved function. 310 * @returns {boolean} True if the mirror reflects an unresolved function 311 */ 312 Mirror.prototype.isUnresolvedFunction = function() { 313 return this instanceof UnresolvedFunctionMirror; 314 }; 315 316 317 /** 318 * Check whether the mirror reflects an array. 319 * @returns {boolean} True if the mirror reflects an array 320 */ 321 Mirror.prototype.isArray = function() { 322 return this instanceof ArrayMirror; 323 }; 324 325 326 /** 327 * Check whether the mirror reflects a date. 328 * @returns {boolean} True if the mirror reflects a date 329 */ 330 Mirror.prototype.isDate = function() { 331 return this instanceof DateMirror; 332 }; 333 334 335 /** 336 * Check whether the mirror reflects a regular expression. 337 * @returns {boolean} True if the mirror reflects a regular expression 338 */ 339 Mirror.prototype.isRegExp = function() { 340 return this instanceof RegExpMirror; 341 }; 342 343 344 /** 345 * Check whether the mirror reflects an error. 346 * @returns {boolean} True if the mirror reflects an error 347 */ 348 Mirror.prototype.isError = function() { 349 return this instanceof ErrorMirror; 350 }; 351 352 353 /** 354 * Check whether the mirror reflects a property. 355 * @returns {boolean} True if the mirror reflects a property 356 */ 357 Mirror.prototype.isProperty = function() { 358 return this instanceof PropertyMirror; 359 }; 360 361 362 /** 363 * Check whether the mirror reflects a stack frame. 364 * @returns {boolean} True if the mirror reflects a stack frame 365 */ 366 Mirror.prototype.isFrame = function() { 367 return this instanceof FrameMirror; 368 }; 369 370 371 /** 372 * Check whether the mirror reflects a script. 373 * @returns {boolean} True if the mirror reflects a script 374 */ 375 Mirror.prototype.isScript = function() { 376 return this instanceof ScriptMirror; 377 }; 378 379 380 /** 381 * Check whether the mirror reflects a context. 382 * @returns {boolean} True if the mirror reflects a context 383 */ 384 Mirror.prototype.isContext = function() { 385 return this instanceof ContextMirror; 386 }; 387 388 389 /** 390 * Check whether the mirror reflects a scope. 391 * @returns {boolean} True if the mirror reflects a scope 392 */ 393 Mirror.prototype.isScope = function() { 394 return this instanceof ScopeMirror; 395 }; 396 397 398 /** 399 * Allocate a handle id for this object. 400 */ 401 Mirror.prototype.allocateHandle_ = function() { 402 this.handle_ = next_handle_++; 403 }; 404 405 406 /** 407 * Allocate a transient handle id for this object. Transient handles are 408 * negative. 409 */ 410 Mirror.prototype.allocateTransientHandle_ = function() { 411 this.handle_ = next_transient_handle_--; 412 }; 413 414 415 Mirror.prototype.toText = function() { 416 // Simpel to text which is used when on specialization in subclass. 417 return "#<" + this.constructor.name + ">"; 418 }; 419 420 421 /** 422 * Base class for all value mirror objects. 423 * @param {string} type The type of the mirror 424 * @param {value} value The value reflected by this mirror 425 * @param {boolean} transient indicate whether this object is transient with a 426 * transient handle 427 * @constructor 428 * @extends Mirror 429 */ 430 function ValueMirror(type, value, transient) { 431 %_CallFunction(this, type, Mirror); 432 this.value_ = value; 433 if (!transient) { 434 this.allocateHandle_(); 435 } else { 436 this.allocateTransientHandle_(); 437 } 438 } 439 inherits(ValueMirror, Mirror); 440 441 442 Mirror.prototype.handle = function() { 443 return this.handle_; 444 }; 445 446 447 /** 448 * Check whether this is a primitive value. 449 * @return {boolean} True if the mirror reflects a primitive value 450 */ 451 ValueMirror.prototype.isPrimitive = function() { 452 var type = this.type(); 453 return type === 'undefined' || 454 type === 'null' || 455 type === 'boolean' || 456 type === 'number' || 457 type === 'string'; 458 }; 459 460 461 /** 462 * Get the actual value reflected by this mirror. 463 * @return {value} The value reflected by this mirror 464 */ 465 ValueMirror.prototype.value = function() { 466 return this.value_; 467 }; 468 469 470 /** 471 * Mirror object for Undefined. 472 * @constructor 473 * @extends ValueMirror 474 */ 475 function UndefinedMirror() { 476 %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror); 477 } 478 inherits(UndefinedMirror, ValueMirror); 479 480 481 UndefinedMirror.prototype.toText = function() { 482 return 'undefined'; 483 }; 484 485 486 /** 487 * Mirror object for null. 488 * @constructor 489 * @extends ValueMirror 490 */ 491 function NullMirror() { 492 %_CallFunction(this, NULL_TYPE, null, ValueMirror); 493 } 494 inherits(NullMirror, ValueMirror); 495 496 497 NullMirror.prototype.toText = function() { 498 return 'null'; 499 }; 500 501 502 /** 503 * Mirror object for boolean values. 504 * @param {boolean} value The boolean value reflected by this mirror 505 * @constructor 506 * @extends ValueMirror 507 */ 508 function BooleanMirror(value) { 509 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror); 510 } 511 inherits(BooleanMirror, ValueMirror); 512 513 514 BooleanMirror.prototype.toText = function() { 515 return this.value_ ? 'true' : 'false'; 516 }; 517 518 519 /** 520 * Mirror object for number values. 521 * @param {number} value The number value reflected by this mirror 522 * @constructor 523 * @extends ValueMirror 524 */ 525 function NumberMirror(value) { 526 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror); 527 } 528 inherits(NumberMirror, ValueMirror); 529 530 531 NumberMirror.prototype.toText = function() { 532 return %NumberToString(this.value_); 533 }; 534 535 536 /** 537 * Mirror object for string values. 538 * @param {string} value The string value reflected by this mirror 539 * @constructor 540 * @extends ValueMirror 541 */ 542 function StringMirror(value) { 543 %_CallFunction(this, STRING_TYPE, value, ValueMirror); 544 } 545 inherits(StringMirror, ValueMirror); 546 547 548 StringMirror.prototype.length = function() { 549 return this.value_.length; 550 }; 551 552 StringMirror.prototype.getTruncatedValue = function(maxLength) { 553 if (maxLength != -1 && this.length() > maxLength) { 554 return this.value_.substring(0, maxLength) + 555 '... (length: ' + this.length() + ')'; 556 } 557 return this.value_; 558 }; 559 560 StringMirror.prototype.toText = function() { 561 return this.getTruncatedValue(kMaxProtocolStringLength); 562 }; 563 564 565 /** 566 * Mirror object for objects. 567 * @param {object} value The object reflected by this mirror 568 * @param {boolean} transient indicate whether this object is transient with a 569 * transient handle 570 * @constructor 571 * @extends ValueMirror 572 */ 573 function ObjectMirror(value, type, transient) { 574 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror); 575 } 576 inherits(ObjectMirror, ValueMirror); 577 578 579 ObjectMirror.prototype.className = function() { 580 return %_ClassOf(this.value_); 581 }; 582 583 584 ObjectMirror.prototype.constructorFunction = function() { 585 return MakeMirror(%DebugGetProperty(this.value_, 'constructor')); 586 }; 587 588 589 ObjectMirror.prototype.prototypeObject = function() { 590 return MakeMirror(%DebugGetProperty(this.value_, 'prototype')); 591 }; 592 593 594 ObjectMirror.prototype.protoObject = function() { 595 return MakeMirror(%DebugGetPrototype(this.value_)); 596 }; 597 598 599 ObjectMirror.prototype.hasNamedInterceptor = function() { 600 // Get information on interceptors for this object. 601 var x = %GetInterceptorInfo(this.value_); 602 return (x & 2) != 0; 603 }; 604 605 606 ObjectMirror.prototype.hasIndexedInterceptor = function() { 607 // Get information on interceptors for this object. 608 var x = %GetInterceptorInfo(this.value_); 609 return (x & 1) != 0; 610 }; 611 612 613 /** 614 * Return the property names for this object. 615 * @param {number} kind Indicate whether named, indexed or both kinds of 616 * properties are requested 617 * @param {number} limit Limit the number of names returend to the specified 618 value 619 * @return {Array} Property names for this object 620 */ 621 ObjectMirror.prototype.propertyNames = function(kind, limit) { 622 // Find kind and limit and allocate array for the result 623 kind = kind || PropertyKind.Named | PropertyKind.Indexed; 624 625 var propertyNames; 626 var elementNames; 627 var total = 0; 628 629 // Find all the named properties. 630 if (kind & PropertyKind.Named) { 631 // Get the local property names. 632 propertyNames = %GetLocalPropertyNames(this.value_); 633 total += propertyNames.length; 634 635 // Get names for named interceptor properties if any. 636 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) { 637 var namedInterceptorNames = 638 %GetNamedInterceptorPropertyNames(this.value_); 639 if (namedInterceptorNames) { 640 propertyNames = propertyNames.concat(namedInterceptorNames); 641 total += namedInterceptorNames.length; 642 } 643 } 644 } 645 646 // Find all the indexed properties. 647 if (kind & PropertyKind.Indexed) { 648 // Get the local element names. 649 elementNames = %GetLocalElementNames(this.value_); 650 total += elementNames.length; 651 652 // Get names for indexed interceptor properties. 653 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) { 654 var indexedInterceptorNames = 655 %GetIndexedInterceptorElementNames(this.value_); 656 if (indexedInterceptorNames) { 657 elementNames = elementNames.concat(indexedInterceptorNames); 658 total += indexedInterceptorNames.length; 659 } 660 } 661 } 662 limit = Math.min(limit || total, total); 663 664 var names = new Array(limit); 665 var index = 0; 666 667 // Copy names for named properties. 668 if (kind & PropertyKind.Named) { 669 for (var i = 0; index < limit && i < propertyNames.length; i++) { 670 names[index++] = propertyNames[i]; 671 } 672 } 673 674 // Copy names for indexed properties. 675 if (kind & PropertyKind.Indexed) { 676 for (var i = 0; index < limit && i < elementNames.length; i++) { 677 names[index++] = elementNames[i]; 678 } 679 } 680 681 return names; 682 }; 683 684 685 /** 686 * Return the properties for this object as an array of PropertyMirror objects. 687 * @param {number} kind Indicate whether named, indexed or both kinds of 688 * properties are requested 689 * @param {number} limit Limit the number of properties returend to the 690 specified value 691 * @return {Array} Property mirrors for this object 692 */ 693 ObjectMirror.prototype.properties = function(kind, limit) { 694 var names = this.propertyNames(kind, limit); 695 var properties = new Array(names.length); 696 for (var i = 0; i < names.length; i++) { 697 properties[i] = this.property(names[i]); 698 } 699 700 return properties; 701 }; 702 703 704 ObjectMirror.prototype.property = function(name) { 705 var details = %DebugGetPropertyDetails(this.value_, %ToString(name)); 706 if (details) { 707 return new PropertyMirror(this, name, details); 708 } 709 710 // Nothing found. 711 return GetUndefinedMirror(); 712 }; 713 714 715 716 /** 717 * Try to find a property from its value. 718 * @param {Mirror} value The property value to look for 719 * @return {PropertyMirror} The property with the specified value. If no 720 * property was found with the specified value UndefinedMirror is returned 721 */ 722 ObjectMirror.prototype.lookupProperty = function(value) { 723 var properties = this.properties(); 724 725 // Look for property value in properties. 726 for (var i = 0; i < properties.length; i++) { 727 728 // Skip properties which are defined through assessors. 729 var property = properties[i]; 730 if (property.propertyType() != PropertyType.Callbacks) { 731 if (%_ObjectEquals(property.value_, value.value_)) { 732 return property; 733 } 734 } 735 } 736 737 // Nothing found. 738 return GetUndefinedMirror(); 739 }; 740 741 742 /** 743 * Returns objects which has direct references to this object 744 * @param {number} opt_max_objects Optional parameter specifying the maximum 745 * number of referencing objects to return. 746 * @return {Array} The objects which has direct references to this object. 747 */ 748 ObjectMirror.prototype.referencedBy = function(opt_max_objects) { 749 // Find all objects with direct references to this object. 750 var result = %DebugReferencedBy(this.value_, 751 Mirror.prototype, opt_max_objects || 0); 752 753 // Make mirrors for all the references found. 754 for (var i = 0; i < result.length; i++) { 755 result[i] = MakeMirror(result[i]); 756 } 757 758 return result; 759 }; 760 761 762 ObjectMirror.prototype.toText = function() { 763 var name; 764 var ctor = this.constructorFunction(); 765 if (!ctor.isFunction()) { 766 name = this.className(); 767 } else { 768 name = ctor.name(); 769 if (!name) { 770 name = this.className(); 771 } 772 } 773 return '#<' + name + '>'; 774 }; 775 776 777 /** 778 * Mirror object for functions. 779 * @param {function} value The function object reflected by this mirror. 780 * @constructor 781 * @extends ObjectMirror 782 */ 783 function FunctionMirror(value) { 784 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror); 785 this.resolved_ = true; 786 } 787 inherits(FunctionMirror, ObjectMirror); 788 789 790 /** 791 * Returns whether the function is resolved. 792 * @return {boolean} True if the function is resolved. Unresolved functions can 793 * only originate as functions from stack frames 794 */ 795 FunctionMirror.prototype.resolved = function() { 796 return this.resolved_; 797 }; 798 799 800 /** 801 * Returns the name of the function. 802 * @return {string} Name of the function 803 */ 804 FunctionMirror.prototype.name = function() { 805 return %FunctionGetName(this.value_); 806 }; 807 808 809 /** 810 * Returns the inferred name of the function. 811 * @return {string} Name of the function 812 */ 813 FunctionMirror.prototype.inferredName = function() { 814 return %FunctionGetInferredName(this.value_); 815 }; 816 817 818 /** 819 * Returns the source code for the function. 820 * @return {string or undefined} The source code for the function. If the 821 * function is not resolved undefined will be returned. 822 */ 823 FunctionMirror.prototype.source = function() { 824 // Return source if function is resolved. Otherwise just fall through to 825 // return undefined. 826 if (this.resolved()) { 827 return builtins.FunctionSourceString(this.value_); 828 } 829 }; 830 831 832 /** 833 * Returns the script object for the function. 834 * @return {ScriptMirror or undefined} Script object for the function or 835 * undefined if the function has no script 836 */ 837 FunctionMirror.prototype.script = function() { 838 // Return script if function is resolved. Otherwise just fall through 839 // to return undefined. 840 if (this.resolved()) { 841 var script = %FunctionGetScript(this.value_); 842 if (script) { 843 return MakeMirror(script); 844 } 845 } 846 }; 847 848 849 /** 850 * Returns the script source position for the function. Only makes sense 851 * for functions which has a script defined. 852 * @return {Number or undefined} in-script position for the function 853 */ 854 FunctionMirror.prototype.sourcePosition_ = function() { 855 // Return script if function is resolved. Otherwise just fall through 856 // to return undefined. 857 if (this.resolved()) { 858 return %FunctionGetScriptSourcePosition(this.value_); 859 } 860 }; 861 862 863 /** 864 * Returns the script source location object for the function. Only makes sense 865 * for functions which has a script defined. 866 * @return {Location or undefined} in-script location for the function begin 867 */ 868 FunctionMirror.prototype.sourceLocation = function() { 869 if (this.resolved() && this.script()) { 870 return this.script().locationFromPosition(this.sourcePosition_(), 871 true); 872 } 873 }; 874 875 876 /** 877 * Returns objects constructed by this function. 878 * @param {number} opt_max_instances Optional parameter specifying the maximum 879 * number of instances to return. 880 * @return {Array or undefined} The objects constructed by this function. 881 */ 882 FunctionMirror.prototype.constructedBy = function(opt_max_instances) { 883 if (this.resolved()) { 884 // Find all objects constructed from this function. 885 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0); 886 887 // Make mirrors for all the instances found. 888 for (var i = 0; i < result.length; i++) { 889 result[i] = MakeMirror(result[i]); 890 } 891 892 return result; 893 } else { 894 return []; 895 } 896 }; 897 898 899 FunctionMirror.prototype.toText = function() { 900 return this.source(); 901 }; 902 903 904 /** 905 * Mirror object for unresolved functions. 906 * @param {string} value The name for the unresolved function reflected by this 907 * mirror. 908 * @constructor 909 * @extends ObjectMirror 910 */ 911 function UnresolvedFunctionMirror(value) { 912 // Construct this using the ValueMirror as an unresolved function is not a 913 // real object but just a string. 914 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror); 915 this.propertyCount_ = 0; 916 this.elementCount_ = 0; 917 this.resolved_ = false; 918 } 919 inherits(UnresolvedFunctionMirror, FunctionMirror); 920 921 922 UnresolvedFunctionMirror.prototype.className = function() { 923 return 'Function'; 924 }; 925 926 927 UnresolvedFunctionMirror.prototype.constructorFunction = function() { 928 return GetUndefinedMirror(); 929 }; 930 931 932 UnresolvedFunctionMirror.prototype.prototypeObject = function() { 933 return GetUndefinedMirror(); 934 }; 935 936 937 UnresolvedFunctionMirror.prototype.protoObject = function() { 938 return GetUndefinedMirror(); 939 }; 940 941 942 UnresolvedFunctionMirror.prototype.name = function() { 943 return this.value_; 944 }; 945 946 947 UnresolvedFunctionMirror.prototype.inferredName = function() { 948 return undefined; 949 }; 950 951 952 UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) { 953 return []; 954 }; 955 956 957 /** 958 * Mirror object for arrays. 959 * @param {Array} value The Array object reflected by this mirror 960 * @constructor 961 * @extends ObjectMirror 962 */ 963 function ArrayMirror(value) { 964 %_CallFunction(this, value, ObjectMirror); 965 } 966 inherits(ArrayMirror, ObjectMirror); 967 968 969 ArrayMirror.prototype.length = function() { 970 return this.value_.length; 971 }; 972 973 974 ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, 975 opt_to_index) { 976 var from_index = opt_from_index || 0; 977 var to_index = opt_to_index || this.length() - 1; 978 if (from_index > to_index) return new Array(); 979 var values = new Array(to_index - from_index + 1); 980 for (var i = from_index; i <= to_index; i++) { 981 var details = %DebugGetPropertyDetails(this.value_, %ToString(i)); 982 var value; 983 if (details) { 984 value = new PropertyMirror(this, i, details); 985 } else { 986 value = GetUndefinedMirror(); 987 } 988 values[i - from_index] = value; 989 } 990 return values; 991 }; 992 993 994 /** 995 * Mirror object for dates. 996 * @param {Date} value The Date object reflected by this mirror 997 * @constructor 998 * @extends ObjectMirror 999 */ 1000 function DateMirror(value) { 1001 %_CallFunction(this, value, ObjectMirror); 1002 } 1003 inherits(DateMirror, ObjectMirror); 1004 1005 1006 DateMirror.prototype.toText = function() { 1007 var s = JSON.stringify(this.value_); 1008 return s.substring(1, s.length - 1); // cut quotes 1009 }; 1010 1011 1012 /** 1013 * Mirror object for regular expressions. 1014 * @param {RegExp} value The RegExp object reflected by this mirror 1015 * @constructor 1016 * @extends ObjectMirror 1017 */ 1018 function RegExpMirror(value) { 1019 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror); 1020 } 1021 inherits(RegExpMirror, ObjectMirror); 1022 1023 1024 /** 1025 * Returns the source to the regular expression. 1026 * @return {string or undefined} The source to the regular expression 1027 */ 1028 RegExpMirror.prototype.source = function() { 1029 return this.value_.source; 1030 }; 1031 1032 1033 /** 1034 * Returns whether this regular expression has the global (g) flag set. 1035 * @return {boolean} Value of the global flag 1036 */ 1037 RegExpMirror.prototype.global = function() { 1038 return this.value_.global; 1039 }; 1040 1041 1042 /** 1043 * Returns whether this regular expression has the ignore case (i) flag set. 1044 * @return {boolean} Value of the ignore case flag 1045 */ 1046 RegExpMirror.prototype.ignoreCase = function() { 1047 return this.value_.ignoreCase; 1048 }; 1049 1050 1051 /** 1052 * Returns whether this regular expression has the multiline (m) flag set. 1053 * @return {boolean} Value of the multiline flag 1054 */ 1055 RegExpMirror.prototype.multiline = function() { 1056 return this.value_.multiline; 1057 }; 1058 1059 1060 RegExpMirror.prototype.toText = function() { 1061 // Simpel to text which is used when on specialization in subclass. 1062 return "/" + this.source() + "/"; 1063 }; 1064 1065 1066 /** 1067 * Mirror object for error objects. 1068 * @param {Error} value The error object reflected by this mirror 1069 * @constructor 1070 * @extends ObjectMirror 1071 */ 1072 function ErrorMirror(value) { 1073 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror); 1074 } 1075 inherits(ErrorMirror, ObjectMirror); 1076 1077 1078 /** 1079 * Returns the message for this eror object. 1080 * @return {string or undefined} The message for this eror object 1081 */ 1082 ErrorMirror.prototype.message = function() { 1083 return this.value_.message; 1084 }; 1085 1086 1087 ErrorMirror.prototype.toText = function() { 1088 // Use the same text representation as in messages.js. 1089 var text; 1090 try { 1091 str = %_CallFunction(this.value_, builtins.ErrorToString); 1092 } catch (e) { 1093 str = '#<Error>'; 1094 } 1095 return str; 1096 }; 1097 1098 1099 /** 1100 * Base mirror object for properties. 1101 * @param {ObjectMirror} mirror The mirror object having this property 1102 * @param {string} name The name of the property 1103 * @param {Array} details Details about the property 1104 * @constructor 1105 * @extends Mirror 1106 */ 1107 function PropertyMirror(mirror, name, details) { 1108 %_CallFunction(this, PROPERTY_TYPE, Mirror); 1109 this.mirror_ = mirror; 1110 this.name_ = name; 1111 this.value_ = details[0]; 1112 this.details_ = details[1]; 1113 if (details.length > 2) { 1114 this.exception_ = details[2]; 1115 this.getter_ = details[3]; 1116 this.setter_ = details[4]; 1117 } 1118 } 1119 inherits(PropertyMirror, Mirror); 1120 1121 1122 PropertyMirror.prototype.isReadOnly = function() { 1123 return (this.attributes() & PropertyAttribute.ReadOnly) != 0; 1124 }; 1125 1126 1127 PropertyMirror.prototype.isEnum = function() { 1128 return (this.attributes() & PropertyAttribute.DontEnum) == 0; 1129 }; 1130 1131 1132 PropertyMirror.prototype.canDelete = function() { 1133 return (this.attributes() & PropertyAttribute.DontDelete) == 0; 1134 }; 1135 1136 1137 PropertyMirror.prototype.name = function() { 1138 return this.name_; 1139 }; 1140 1141 1142 PropertyMirror.prototype.isIndexed = function() { 1143 for (var i = 0; i < this.name_.length; i++) { 1144 if (this.name_[i] < '0' || '9' < this.name_[i]) { 1145 return false; 1146 } 1147 } 1148 return true; 1149 }; 1150 1151 1152 PropertyMirror.prototype.value = function() { 1153 return MakeMirror(this.value_, false); 1154 }; 1155 1156 1157 /** 1158 * Returns whether this property value is an exception. 1159 * @return {booolean} True if this property value is an exception 1160 */ 1161 PropertyMirror.prototype.isException = function() { 1162 return this.exception_ ? true : false; 1163 }; 1164 1165 1166 PropertyMirror.prototype.attributes = function() { 1167 return %DebugPropertyAttributesFromDetails(this.details_); 1168 }; 1169 1170 1171 PropertyMirror.prototype.propertyType = function() { 1172 return %DebugPropertyTypeFromDetails(this.details_); 1173 }; 1174 1175 1176 PropertyMirror.prototype.insertionIndex = function() { 1177 return %DebugPropertyIndexFromDetails(this.details_); 1178 }; 1179 1180 1181 /** 1182 * Returns whether this property has a getter defined through __defineGetter__. 1183 * @return {booolean} True if this property has a getter 1184 */ 1185 PropertyMirror.prototype.hasGetter = function() { 1186 return this.getter_ ? true : false; 1187 }; 1188 1189 1190 /** 1191 * Returns whether this property has a setter defined through __defineSetter__. 1192 * @return {booolean} True if this property has a setter 1193 */ 1194 PropertyMirror.prototype.hasSetter = function() { 1195 return this.setter_ ? true : false; 1196 }; 1197 1198 1199 /** 1200 * Returns the getter for this property defined through __defineGetter__. 1201 * @return {Mirror} FunctionMirror reflecting the getter function or 1202 * UndefinedMirror if there is no getter for this property 1203 */ 1204 PropertyMirror.prototype.getter = function() { 1205 if (this.hasGetter()) { 1206 return MakeMirror(this.getter_); 1207 } else { 1208 return GetUndefinedMirror(); 1209 } 1210 }; 1211 1212 1213 /** 1214 * Returns the setter for this property defined through __defineSetter__. 1215 * @return {Mirror} FunctionMirror reflecting the setter function or 1216 * UndefinedMirror if there is no setter for this property 1217 */ 1218 PropertyMirror.prototype.setter = function() { 1219 if (this.hasSetter()) { 1220 return MakeMirror(this.setter_); 1221 } else { 1222 return GetUndefinedMirror(); 1223 } 1224 }; 1225 1226 1227 /** 1228 * Returns whether this property is natively implemented by the host or a set 1229 * through JavaScript code. 1230 * @return {boolean} True if the property is 1231 * UndefinedMirror if there is no setter for this property 1232 */ 1233 PropertyMirror.prototype.isNative = function() { 1234 return (this.propertyType() == PropertyType.Interceptor) || 1235 ((this.propertyType() == PropertyType.Callbacks) && 1236 !this.hasGetter() && !this.hasSetter()); 1237 }; 1238 1239 1240 var kFrameDetailsFrameIdIndex = 0; 1241 var kFrameDetailsReceiverIndex = 1; 1242 var kFrameDetailsFunctionIndex = 2; 1243 var kFrameDetailsArgumentCountIndex = 3; 1244 var kFrameDetailsLocalCountIndex = 4; 1245 var kFrameDetailsSourcePositionIndex = 5; 1246 var kFrameDetailsConstructCallIndex = 6; 1247 var kFrameDetailsAtReturnIndex = 7; 1248 var kFrameDetailsFlagsIndex = 8; 1249 var kFrameDetailsFirstDynamicIndex = 9; 1250 1251 var kFrameDetailsNameIndex = 0; 1252 var kFrameDetailsValueIndex = 1; 1253 var kFrameDetailsNameValueSize = 2; 1254 1255 var kFrameDetailsFlagDebuggerFrameMask = 1 << 0; 1256 var kFrameDetailsFlagOptimizedFrameMask = 1 << 1; 1257 var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2; 1258 1259 /** 1260 * Wrapper for the frame details information retreived from the VM. The frame 1261 * details from the VM is an array with the following content. See runtime.cc 1262 * Runtime_GetFrameDetails. 1263 * 0: Id 1264 * 1: Receiver 1265 * 2: Function 1266 * 3: Argument count 1267 * 4: Local count 1268 * 5: Source position 1269 * 6: Construct call 1270 * 7: Is at return 1271 * 8: Flags (debugger frame, optimized frame, inlined frame index) 1272 * Arguments name, value 1273 * Locals name, value 1274 * Return value if any 1275 * @param {number} break_id Current break id 1276 * @param {number} index Frame number 1277 * @constructor 1278 */ 1279 function FrameDetails(break_id, index) { 1280 this.break_id_ = break_id; 1281 this.details_ = %GetFrameDetails(break_id, index); 1282 } 1283 1284 1285 FrameDetails.prototype.frameId = function() { 1286 %CheckExecutionState(this.break_id_); 1287 return this.details_[kFrameDetailsFrameIdIndex]; 1288 }; 1289 1290 1291 FrameDetails.prototype.receiver = function() { 1292 %CheckExecutionState(this.break_id_); 1293 return this.details_[kFrameDetailsReceiverIndex]; 1294 }; 1295 1296 1297 FrameDetails.prototype.func = function() { 1298 %CheckExecutionState(this.break_id_); 1299 return this.details_[kFrameDetailsFunctionIndex]; 1300 }; 1301 1302 1303 FrameDetails.prototype.isConstructCall = function() { 1304 %CheckExecutionState(this.break_id_); 1305 return this.details_[kFrameDetailsConstructCallIndex]; 1306 }; 1307 1308 1309 FrameDetails.prototype.isAtReturn = function() { 1310 %CheckExecutionState(this.break_id_); 1311 return this.details_[kFrameDetailsAtReturnIndex]; 1312 }; 1313 1314 1315 FrameDetails.prototype.isDebuggerFrame = function() { 1316 %CheckExecutionState(this.break_id_); 1317 var f = kFrameDetailsFlagDebuggerFrameMask; 1318 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1319 }; 1320 1321 1322 FrameDetails.prototype.isOptimizedFrame = function() { 1323 %CheckExecutionState(this.break_id_); 1324 var f = kFrameDetailsFlagOptimizedFrameMask; 1325 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1326 }; 1327 1328 1329 FrameDetails.prototype.isInlinedFrame = function() { 1330 return this.inlinedFrameIndex() > 0; 1331 }; 1332 1333 1334 FrameDetails.prototype.inlinedFrameIndex = function() { 1335 %CheckExecutionState(this.break_id_); 1336 var f = kFrameDetailsFlagInlinedFrameIndexMask; 1337 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2; 1338 }; 1339 1340 1341 FrameDetails.prototype.argumentCount = function() { 1342 %CheckExecutionState(this.break_id_); 1343 return this.details_[kFrameDetailsArgumentCountIndex]; 1344 }; 1345 1346 1347 FrameDetails.prototype.argumentName = function(index) { 1348 %CheckExecutionState(this.break_id_); 1349 if (index >= 0 && index < this.argumentCount()) { 1350 return this.details_[kFrameDetailsFirstDynamicIndex + 1351 index * kFrameDetailsNameValueSize + 1352 kFrameDetailsNameIndex]; 1353 } 1354 }; 1355 1356 1357 FrameDetails.prototype.argumentValue = function(index) { 1358 %CheckExecutionState(this.break_id_); 1359 if (index >= 0 && index < this.argumentCount()) { 1360 return this.details_[kFrameDetailsFirstDynamicIndex + 1361 index * kFrameDetailsNameValueSize + 1362 kFrameDetailsValueIndex]; 1363 } 1364 }; 1365 1366 1367 FrameDetails.prototype.localCount = function() { 1368 %CheckExecutionState(this.break_id_); 1369 return this.details_[kFrameDetailsLocalCountIndex]; 1370 }; 1371 1372 1373 FrameDetails.prototype.sourcePosition = function() { 1374 %CheckExecutionState(this.break_id_); 1375 return this.details_[kFrameDetailsSourcePositionIndex]; 1376 }; 1377 1378 1379 FrameDetails.prototype.localName = function(index) { 1380 %CheckExecutionState(this.break_id_); 1381 if (index >= 0 && index < this.localCount()) { 1382 var locals_offset = kFrameDetailsFirstDynamicIndex + 1383 this.argumentCount() * kFrameDetailsNameValueSize; 1384 return this.details_[locals_offset + 1385 index * kFrameDetailsNameValueSize + 1386 kFrameDetailsNameIndex]; 1387 } 1388 }; 1389 1390 1391 FrameDetails.prototype.localValue = function(index) { 1392 %CheckExecutionState(this.break_id_); 1393 if (index >= 0 && index < this.localCount()) { 1394 var locals_offset = kFrameDetailsFirstDynamicIndex + 1395 this.argumentCount() * kFrameDetailsNameValueSize; 1396 return this.details_[locals_offset + 1397 index * kFrameDetailsNameValueSize + 1398 kFrameDetailsValueIndex]; 1399 } 1400 }; 1401 1402 1403 FrameDetails.prototype.returnValue = function() { 1404 %CheckExecutionState(this.break_id_); 1405 var return_value_offset = 1406 kFrameDetailsFirstDynamicIndex + 1407 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize; 1408 if (this.details_[kFrameDetailsAtReturnIndex]) { 1409 return this.details_[return_value_offset]; 1410 } 1411 }; 1412 1413 1414 FrameDetails.prototype.scopeCount = function() { 1415 return %GetScopeCount(this.break_id_, this.frameId()); 1416 }; 1417 1418 1419 /** 1420 * Mirror object for stack frames. 1421 * @param {number} break_id The break id in the VM for which this frame is 1422 valid 1423 * @param {number} index The frame index (top frame is index 0) 1424 * @constructor 1425 * @extends Mirror 1426 */ 1427 function FrameMirror(break_id, index) { 1428 %_CallFunction(this, FRAME_TYPE, Mirror); 1429 this.break_id_ = break_id; 1430 this.index_ = index; 1431 this.details_ = new FrameDetails(break_id, index); 1432 } 1433 inherits(FrameMirror, Mirror); 1434 1435 1436 FrameMirror.prototype.index = function() { 1437 return this.index_; 1438 }; 1439 1440 1441 FrameMirror.prototype.func = function() { 1442 // Get the function for this frame from the VM. 1443 var f = this.details_.func(); 1444 1445 // Create a function mirror. NOTE: MakeMirror cannot be used here as the 1446 // value returned from the VM might be a string if the function for the 1447 // frame is unresolved. 1448 if (IS_FUNCTION(f)) { 1449 return MakeMirror(f); 1450 } else { 1451 return new UnresolvedFunctionMirror(f); 1452 } 1453 }; 1454 1455 1456 FrameMirror.prototype.receiver = function() { 1457 return MakeMirror(this.details_.receiver()); 1458 }; 1459 1460 1461 FrameMirror.prototype.isConstructCall = function() { 1462 return this.details_.isConstructCall(); 1463 }; 1464 1465 1466 FrameMirror.prototype.isAtReturn = function() { 1467 return this.details_.isAtReturn(); 1468 }; 1469 1470 1471 FrameMirror.prototype.isDebuggerFrame = function() { 1472 return this.details_.isDebuggerFrame(); 1473 }; 1474 1475 1476 FrameMirror.prototype.isOptimizedFrame = function() { 1477 return this.details_.isOptimizedFrame(); 1478 }; 1479 1480 1481 FrameMirror.prototype.isInlinedFrame = function() { 1482 return this.details_.isInlinedFrame(); 1483 }; 1484 1485 1486 FrameMirror.prototype.inlinedFrameIndex = function() { 1487 return this.details_.inlinedFrameIndex(); 1488 }; 1489 1490 1491 FrameMirror.prototype.argumentCount = function() { 1492 return this.details_.argumentCount(); 1493 }; 1494 1495 1496 FrameMirror.prototype.argumentName = function(index) { 1497 return this.details_.argumentName(index); 1498 }; 1499 1500 1501 FrameMirror.prototype.argumentValue = function(index) { 1502 return MakeMirror(this.details_.argumentValue(index)); 1503 }; 1504 1505 1506 FrameMirror.prototype.localCount = function() { 1507 return this.details_.localCount(); 1508 }; 1509 1510 1511 FrameMirror.prototype.localName = function(index) { 1512 return this.details_.localName(index); 1513 }; 1514 1515 1516 FrameMirror.prototype.localValue = function(index) { 1517 return MakeMirror(this.details_.localValue(index)); 1518 }; 1519 1520 1521 FrameMirror.prototype.returnValue = function() { 1522 return MakeMirror(this.details_.returnValue()); 1523 }; 1524 1525 1526 FrameMirror.prototype.sourcePosition = function() { 1527 return this.details_.sourcePosition(); 1528 }; 1529 1530 1531 FrameMirror.prototype.sourceLocation = function() { 1532 if (this.func().resolved() && this.func().script()) { 1533 return this.func().script().locationFromPosition(this.sourcePosition(), 1534 true); 1535 } 1536 }; 1537 1538 1539 FrameMirror.prototype.sourceLine = function() { 1540 if (this.func().resolved()) { 1541 var location = this.sourceLocation(); 1542 if (location) { 1543 return location.line; 1544 } 1545 } 1546 }; 1547 1548 1549 FrameMirror.prototype.sourceColumn = function() { 1550 if (this.func().resolved()) { 1551 var location = this.sourceLocation(); 1552 if (location) { 1553 return location.column; 1554 } 1555 } 1556 }; 1557 1558 1559 FrameMirror.prototype.sourceLineText = function() { 1560 if (this.func().resolved()) { 1561 var location = this.sourceLocation(); 1562 if (location) { 1563 return location.sourceText(); 1564 } 1565 } 1566 }; 1567 1568 1569 FrameMirror.prototype.scopeCount = function() { 1570 return this.details_.scopeCount(); 1571 }; 1572 1573 1574 FrameMirror.prototype.scope = function(index) { 1575 return new ScopeMirror(this, index); 1576 }; 1577 1578 1579 FrameMirror.prototype.evaluate = function(source, disable_break, 1580 opt_context_object) { 1581 var result = %DebugEvaluate(this.break_id_, 1582 this.details_.frameId(), 1583 this.details_.inlinedFrameIndex(), 1584 source, 1585 Boolean(disable_break), 1586 opt_context_object); 1587 return MakeMirror(result); 1588 }; 1589 1590 1591 FrameMirror.prototype.invocationText = function() { 1592 // Format frame invoaction (receiver, function and arguments). 1593 var result = ''; 1594 var func = this.func(); 1595 var receiver = this.receiver(); 1596 if (this.isConstructCall()) { 1597 // For constructor frames display new followed by the function name. 1598 result += 'new '; 1599 result += func.name() ? func.name() : '[anonymous]'; 1600 } else if (this.isDebuggerFrame()) { 1601 result += '[debugger]'; 1602 } else { 1603 // If the receiver has a className which is 'global' don't display it. 1604 var display_receiver = 1605 !receiver.className || (receiver.className() != 'global'); 1606 if (display_receiver) { 1607 result += receiver.toText(); 1608 } 1609 // Try to find the function as a property in the receiver. Include the 1610 // prototype chain in the lookup. 1611 var property = GetUndefinedMirror(); 1612 if (receiver.isObject()) { 1613 for (var r = receiver; 1614 !r.isNull() && property.isUndefined(); 1615 r = r.protoObject()) { 1616 property = r.lookupProperty(func); 1617 } 1618 } 1619 if (!property.isUndefined()) { 1620 // The function invoked was found on the receiver. Use the property name 1621 // for the backtrace. 1622 if (!property.isIndexed()) { 1623 if (display_receiver) { 1624 result += '.'; 1625 } 1626 result += property.name(); 1627 } else { 1628 result += '['; 1629 result += property.name(); 1630 result += ']'; 1631 } 1632 // Also known as - if the name in the function doesn't match the name 1633 // under which it was looked up. 1634 if (func.name() && func.name() != property.name()) { 1635 result += '(aka ' + func.name() + ')'; 1636 } 1637 } else { 1638 // The function invoked was not found on the receiver. Use the function 1639 // name if available for the backtrace. 1640 if (display_receiver) { 1641 result += '.'; 1642 } 1643 result += func.name() ? func.name() : '[anonymous]'; 1644 } 1645 } 1646 1647 // Render arguments for normal frames. 1648 if (!this.isDebuggerFrame()) { 1649 result += '('; 1650 for (var i = 0; i < this.argumentCount(); i++) { 1651 if (i != 0) result += ', '; 1652 if (this.argumentName(i)) { 1653 result += this.argumentName(i); 1654 result += '='; 1655 } 1656 result += this.argumentValue(i).toText(); 1657 } 1658 result += ')'; 1659 } 1660 1661 if (this.isAtReturn()) { 1662 result += ' returning '; 1663 result += this.returnValue().toText(); 1664 } 1665 1666 return result; 1667 }; 1668 1669 1670 FrameMirror.prototype.sourceAndPositionText = function() { 1671 // Format source and position. 1672 var result = ''; 1673 var func = this.func(); 1674 if (func.resolved()) { 1675 if (func.script()) { 1676 if (func.script().name()) { 1677 result += func.script().name(); 1678 } else { 1679 result += '[unnamed]'; 1680 } 1681 if (!this.isDebuggerFrame()) { 1682 var location = this.sourceLocation(); 1683 result += ' line '; 1684 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?'; 1685 result += ' column '; 1686 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?'; 1687 if (!IS_UNDEFINED(this.sourcePosition())) { 1688 result += ' (position ' + (this.sourcePosition() + 1) + ')'; 1689 } 1690 } 1691 } else { 1692 result += '[no source]'; 1693 } 1694 } else { 1695 result += '[unresolved]'; 1696 } 1697 1698 return result; 1699 }; 1700 1701 1702 FrameMirror.prototype.localsText = function() { 1703 // Format local variables. 1704 var result = ''; 1705 var locals_count = this.localCount(); 1706 if (locals_count > 0) { 1707 for (var i = 0; i < locals_count; ++i) { 1708 result += ' var '; 1709 result += this.localName(i); 1710 result += ' = '; 1711 result += this.localValue(i).toText(); 1712 if (i < locals_count - 1) result += '\n'; 1713 } 1714 } 1715 1716 return result; 1717 }; 1718 1719 1720 FrameMirror.prototype.toText = function(opt_locals) { 1721 var result = ''; 1722 result += '#' + (this.index() <= 9 ? '0' : '') + this.index(); 1723 result += ' '; 1724 result += this.invocationText(); 1725 result += ' '; 1726 result += this.sourceAndPositionText(); 1727 if (opt_locals) { 1728 result += '\n'; 1729 result += this.localsText(); 1730 } 1731 return result; 1732 }; 1733 1734 1735 var kScopeDetailsTypeIndex = 0; 1736 var kScopeDetailsObjectIndex = 1; 1737 1738 function ScopeDetails(frame, index) { 1739 this.break_id_ = frame.break_id_; 1740 this.details_ = %GetScopeDetails(frame.break_id_, 1741 frame.details_.frameId(), 1742 frame.details_.inlinedFrameIndex(), 1743 index); 1744 } 1745 1746 1747 ScopeDetails.prototype.type = function() { 1748 %CheckExecutionState(this.break_id_); 1749 return this.details_[kScopeDetailsTypeIndex]; 1750 }; 1751 1752 1753 ScopeDetails.prototype.object = function() { 1754 %CheckExecutionState(this.break_id_); 1755 return this.details_[kScopeDetailsObjectIndex]; 1756 }; 1757 1758 1759 /** 1760 * Mirror object for scope. 1761 * @param {FrameMirror} frame The frame this scope is a part of 1762 * @param {number} index The scope index in the frame 1763 * @constructor 1764 * @extends Mirror 1765 */ 1766 function ScopeMirror(frame, index) { 1767 %_CallFunction(this, SCOPE_TYPE, Mirror); 1768 this.frame_index_ = frame.index_; 1769 this.scope_index_ = index; 1770 this.details_ = new ScopeDetails(frame, index); 1771 } 1772 inherits(ScopeMirror, Mirror); 1773 1774 1775 ScopeMirror.prototype.frameIndex = function() { 1776 return this.frame_index_; 1777 }; 1778 1779 1780 ScopeMirror.prototype.scopeIndex = function() { 1781 return this.scope_index_; 1782 }; 1783 1784 1785 ScopeMirror.prototype.scopeType = function() { 1786 return this.details_.type(); 1787 }; 1788 1789 1790 ScopeMirror.prototype.scopeObject = function() { 1791 // For local and closure scopes create a transient mirror as these objects are 1792 // created on the fly materializing the local or closure scopes and 1793 // therefore will not preserve identity. 1794 var transient = this.scopeType() == ScopeType.Local || 1795 this.scopeType() == ScopeType.Closure; 1796 return MakeMirror(this.details_.object(), transient); 1797 }; 1798 1799 1800 /** 1801 * Mirror object for script source. 1802 * @param {Script} script The script object 1803 * @constructor 1804 * @extends Mirror 1805 */ 1806 function ScriptMirror(script) { 1807 %_CallFunction(this, SCRIPT_TYPE, Mirror); 1808 this.script_ = script; 1809 this.context_ = new ContextMirror(script.context_data); 1810 this.allocateHandle_(); 1811 } 1812 inherits(ScriptMirror, Mirror); 1813 1814 1815 ScriptMirror.prototype.value = function() { 1816 return this.script_; 1817 }; 1818 1819 1820 ScriptMirror.prototype.name = function() { 1821 return this.script_.name || this.script_.nameOrSourceURL(); 1822 }; 1823 1824 1825 ScriptMirror.prototype.id = function() { 1826 return this.script_.id; 1827 }; 1828 1829 1830 ScriptMirror.prototype.source = function() { 1831 return this.script_.source; 1832 }; 1833 1834 1835 ScriptMirror.prototype.setSource = function(source) { 1836 %DebugSetScriptSource(this.script_, source); 1837 }; 1838 1839 1840 ScriptMirror.prototype.lineOffset = function() { 1841 return this.script_.line_offset; 1842 }; 1843 1844 1845 ScriptMirror.prototype.columnOffset = function() { 1846 return this.script_.column_offset; 1847 }; 1848 1849 1850 ScriptMirror.prototype.data = function() { 1851 return this.script_.data; 1852 }; 1853 1854 1855 ScriptMirror.prototype.scriptType = function() { 1856 return this.script_.type; 1857 }; 1858 1859 1860 ScriptMirror.prototype.compilationType = function() { 1861 return this.script_.compilation_type; 1862 }; 1863 1864 1865 ScriptMirror.prototype.lineCount = function() { 1866 return this.script_.lineCount(); 1867 }; 1868 1869 1870 ScriptMirror.prototype.locationFromPosition = function( 1871 position, include_resource_offset) { 1872 return this.script_.locationFromPosition(position, include_resource_offset); 1873 }; 1874 1875 1876 ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) { 1877 return this.script_.sourceSlice(opt_from_line, opt_to_line); 1878 }; 1879 1880 1881 ScriptMirror.prototype.context = function() { 1882 return this.context_; 1883 }; 1884 1885 1886 ScriptMirror.prototype.evalFromScript = function() { 1887 return MakeMirror(this.script_.eval_from_script); 1888 }; 1889 1890 1891 ScriptMirror.prototype.evalFromFunctionName = function() { 1892 return MakeMirror(this.script_.eval_from_function_name); 1893 }; 1894 1895 1896 ScriptMirror.prototype.evalFromLocation = function() { 1897 var eval_from_script = this.evalFromScript(); 1898 if (!eval_from_script.isUndefined()) { 1899 var position = this.script_.eval_from_script_position; 1900 return eval_from_script.locationFromPosition(position, true); 1901 } 1902 }; 1903 1904 1905 ScriptMirror.prototype.toText = function() { 1906 var result = ''; 1907 result += this.name(); 1908 result += ' (lines: '; 1909 if (this.lineOffset() > 0) { 1910 result += this.lineOffset(); 1911 result += '-'; 1912 result += this.lineOffset() + this.lineCount() - 1; 1913 } else { 1914 result += this.lineCount(); 1915 } 1916 result += ')'; 1917 return result; 1918 }; 1919 1920 1921 /** 1922 * Mirror object for context. 1923 * @param {Object} data The context data 1924 * @constructor 1925 * @extends Mirror 1926 */ 1927 function ContextMirror(data) { 1928 %_CallFunction(this, CONTEXT_TYPE, Mirror); 1929 this.data_ = data; 1930 this.allocateHandle_(); 1931 } 1932 inherits(ContextMirror, Mirror); 1933 1934 1935 ContextMirror.prototype.data = function() { 1936 return this.data_; 1937 }; 1938 1939 1940 /** 1941 * Returns a mirror serializer 1942 * 1943 * @param {boolean} details Set to true to include details 1944 * @param {Object} options Options comtrolling the serialization 1945 * The following options can be set: 1946 * includeSource: include ths full source of scripts 1947 * @returns {MirrorSerializer} mirror serializer 1948 */ 1949 function MakeMirrorSerializer(details, options) { 1950 return new JSONProtocolSerializer(details, options); 1951 } 1952 1953 1954 /** 1955 * Object for serializing a mirror objects and its direct references. 1956 * @param {boolean} details Indicates whether to include details for the mirror 1957 * serialized 1958 * @constructor 1959 */ 1960 function JSONProtocolSerializer(details, options) { 1961 this.details_ = details; 1962 this.options_ = options; 1963 this.mirrors_ = [ ]; 1964 } 1965 1966 1967 /** 1968 * Returns a serialization of an object reference. The referenced object are 1969 * added to the serialization state. 1970 * 1971 * @param {Mirror} mirror The mirror to serialize 1972 * @returns {String} JSON serialization 1973 */ 1974 JSONProtocolSerializer.prototype.serializeReference = function(mirror) { 1975 return this.serialize_(mirror, true, true); 1976 }; 1977 1978 1979 /** 1980 * Returns a serialization of an object value. The referenced objects are 1981 * added to the serialization state. 1982 * 1983 * @param {Mirror} mirror The mirror to serialize 1984 * @returns {String} JSON serialization 1985 */ 1986 JSONProtocolSerializer.prototype.serializeValue = function(mirror) { 1987 var json = this.serialize_(mirror, false, true); 1988 return json; 1989 }; 1990 1991 1992 /** 1993 * Returns a serialization of all the objects referenced. 1994 * 1995 * @param {Mirror} mirror The mirror to serialize. 1996 * @returns {Array.<Object>} Array of the referenced objects converted to 1997 * protcol objects. 1998 */ 1999 JSONProtocolSerializer.prototype.serializeReferencedObjects = function() { 2000 // Collect the protocol representation of the referenced objects in an array. 2001 var content = []; 2002 2003 // Get the number of referenced objects. 2004 var count = this.mirrors_.length; 2005 2006 for (var i = 0; i < count; i++) { 2007 content.push(this.serialize_(this.mirrors_[i], false, false)); 2008 } 2009 2010 return content; 2011 }; 2012 2013 2014 JSONProtocolSerializer.prototype.includeSource_ = function() { 2015 return this.options_ && this.options_.includeSource; 2016 }; 2017 2018 2019 JSONProtocolSerializer.prototype.inlineRefs_ = function() { 2020 return this.options_ && this.options_.inlineRefs; 2021 }; 2022 2023 2024 JSONProtocolSerializer.prototype.maxStringLength_ = function() { 2025 if (IS_UNDEFINED(this.options_) || 2026 IS_UNDEFINED(this.options_.maxStringLength)) { 2027 return kMaxProtocolStringLength; 2028 } 2029 return this.options_.maxStringLength; 2030 }; 2031 2032 2033 JSONProtocolSerializer.prototype.add_ = function(mirror) { 2034 // If this mirror is already in the list just return. 2035 for (var i = 0; i < this.mirrors_.length; i++) { 2036 if (this.mirrors_[i] === mirror) { 2037 return; 2038 } 2039 } 2040 2041 // Add the mirror to the list of mirrors to be serialized. 2042 this.mirrors_.push(mirror); 2043 }; 2044 2045 2046 /** 2047 * Formats mirror object to protocol reference object with some data that can 2048 * be used to display the value in debugger. 2049 * @param {Mirror} mirror Mirror to serialize. 2050 * @return {Object} Protocol reference object. 2051 */ 2052 JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ = 2053 function(mirror) { 2054 var o = {}; 2055 o.ref = mirror.handle(); 2056 o.type = mirror.type(); 2057 switch (mirror.type()) { 2058 case UNDEFINED_TYPE: 2059 case NULL_TYPE: 2060 case BOOLEAN_TYPE: 2061 case NUMBER_TYPE: 2062 o.value = mirror.value(); 2063 break; 2064 case STRING_TYPE: 2065 o.value = mirror.getTruncatedValue(this.maxStringLength_()); 2066 break; 2067 case FUNCTION_TYPE: 2068 o.name = mirror.name(); 2069 o.inferredName = mirror.inferredName(); 2070 if (mirror.script()) { 2071 o.scriptId = mirror.script().id(); 2072 } 2073 break; 2074 case ERROR_TYPE: 2075 case REGEXP_TYPE: 2076 o.value = mirror.toText(); 2077 break; 2078 case OBJECT_TYPE: 2079 o.className = mirror.className(); 2080 break; 2081 } 2082 return o; 2083 }; 2084 2085 2086 JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference, 2087 details) { 2088 // If serializing a reference to a mirror just return the reference and add 2089 // the mirror to the referenced mirrors. 2090 if (reference && 2091 (mirror.isValue() || mirror.isScript() || mirror.isContext())) { 2092 if (this.inlineRefs_() && mirror.isValue()) { 2093 return this.serializeReferenceWithDisplayData_(mirror); 2094 } else { 2095 this.add_(mirror); 2096 return {'ref' : mirror.handle()}; 2097 } 2098 } 2099 2100 // Collect the JSON property/value pairs. 2101 var content = {}; 2102 2103 // Add the mirror handle. 2104 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) { 2105 content.handle = mirror.handle(); 2106 } 2107 2108 // Always add the type. 2109 content.type = mirror.type(); 2110 2111 switch (mirror.type()) { 2112 case UNDEFINED_TYPE: 2113 case NULL_TYPE: 2114 // Undefined and null are represented just by their type. 2115 break; 2116 2117 case BOOLEAN_TYPE: 2118 // Boolean values are simply represented by their value. 2119 content.value = mirror.value(); 2120 break; 2121 2122 case NUMBER_TYPE: 2123 // Number values are simply represented by their value. 2124 content.value = NumberToJSON_(mirror.value()); 2125 break; 2126 2127 case STRING_TYPE: 2128 // String values might have their value cropped to keep down size. 2129 if (this.maxStringLength_() != -1 && 2130 mirror.length() > this.maxStringLength_()) { 2131 var str = mirror.getTruncatedValue(this.maxStringLength_()); 2132 content.value = str; 2133 content.fromIndex = 0; 2134 content.toIndex = this.maxStringLength_(); 2135 } else { 2136 content.value = mirror.value(); 2137 } 2138 content.length = mirror.length(); 2139 break; 2140 2141 case OBJECT_TYPE: 2142 case FUNCTION_TYPE: 2143 case ERROR_TYPE: 2144 case REGEXP_TYPE: 2145 // Add object representation. 2146 this.serializeObject_(mirror, content, details); 2147 break; 2148 2149 case PROPERTY_TYPE: 2150 throw new Error('PropertyMirror cannot be serialized independeltly'); 2151 break; 2152 2153 case FRAME_TYPE: 2154 // Add object representation. 2155 this.serializeFrame_(mirror, content); 2156 break; 2157 2158 case SCOPE_TYPE: 2159 // Add object representation. 2160 this.serializeScope_(mirror, content); 2161 break; 2162 2163 case SCRIPT_TYPE: 2164 // Script is represented by id, name and source attributes. 2165 if (mirror.name()) { 2166 content.name = mirror.name(); 2167 } 2168 content.id = mirror.id(); 2169 content.lineOffset = mirror.lineOffset(); 2170 content.columnOffset = mirror.columnOffset(); 2171 content.lineCount = mirror.lineCount(); 2172 if (mirror.data()) { 2173 content.data = mirror.data(); 2174 } 2175 if (this.includeSource_()) { 2176 content.source = mirror.source(); 2177 } else { 2178 var sourceStart = mirror.source().substring(0, 80); 2179 content.sourceStart = sourceStart; 2180 } 2181 content.sourceLength = mirror.source().length; 2182 content.scriptType = mirror.scriptType(); 2183 content.compilationType = mirror.compilationType(); 2184 // For compilation type eval emit information on the script from which 2185 // eval was called if a script is present. 2186 if (mirror.compilationType() == 1 && 2187 mirror.evalFromScript()) { 2188 content.evalFromScript = 2189 this.serializeReference(mirror.evalFromScript()); 2190 var evalFromLocation = mirror.evalFromLocation(); 2191 if (evalFromLocation) { 2192 content.evalFromLocation = { line: evalFromLocation.line, 2193 column: evalFromLocation.column }; 2194 } 2195 if (mirror.evalFromFunctionName()) { 2196 content.evalFromFunctionName = mirror.evalFromFunctionName(); 2197 } 2198 } 2199 if (mirror.context()) { 2200 content.context = this.serializeReference(mirror.context()); 2201 } 2202 break; 2203 2204 case CONTEXT_TYPE: 2205 content.data = mirror.data(); 2206 break; 2207 } 2208 2209 // Always add the text representation. 2210 content.text = mirror.toText(); 2211 2212 // Create and return the JSON string. 2213 return content; 2214 }; 2215 2216 2217 /** 2218 * Serialize object information to the following JSON format. 2219 * 2220 * {"className":"<class name>", 2221 * "constructorFunction":{"ref":<number>}, 2222 * "protoObject":{"ref":<number>}, 2223 * "prototypeObject":{"ref":<number>}, 2224 * "namedInterceptor":<boolean>, 2225 * "indexedInterceptor":<boolean>, 2226 * "properties":[<properties>]} 2227 */ 2228 JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, 2229 details) { 2230 // Add general object properties. 2231 content.className = mirror.className(); 2232 content.constructorFunction = 2233 this.serializeReference(mirror.constructorFunction()); 2234 content.protoObject = this.serializeReference(mirror.protoObject()); 2235 content.prototypeObject = this.serializeReference(mirror.prototypeObject()); 2236 2237 // Add flags to indicate whether there are interceptors. 2238 if (mirror.hasNamedInterceptor()) { 2239 content.namedInterceptor = true; 2240 } 2241 if (mirror.hasIndexedInterceptor()) { 2242 content.indexedInterceptor = true; 2243 } 2244 2245 // Add function specific properties. 2246 if (mirror.isFunction()) { 2247 // Add function specific properties. 2248 content.name = mirror.name(); 2249 if (!IS_UNDEFINED(mirror.inferredName())) { 2250 content.inferredName = mirror.inferredName(); 2251 } 2252 content.resolved = mirror.resolved(); 2253 if (mirror.resolved()) { 2254 content.source = mirror.source(); 2255 } 2256 if (mirror.script()) { 2257 content.script = this.serializeReference(mirror.script()); 2258 content.scriptId = mirror.script().id(); 2259 2260 serializeLocationFields(mirror.sourceLocation(), content); 2261 } 2262 } 2263 2264 // Add date specific properties. 2265 if (mirror.isDate()) { 2266 // Add date specific properties. 2267 content.value = mirror.value(); 2268 } 2269 2270 // Add actual properties - named properties followed by indexed properties. 2271 var propertyNames = mirror.propertyNames(PropertyKind.Named); 2272 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed); 2273 var p = new Array(propertyNames.length + propertyIndexes.length); 2274 for (var i = 0; i < propertyNames.length; i++) { 2275 var propertyMirror = mirror.property(propertyNames[i]); 2276 p[i] = this.serializeProperty_(propertyMirror); 2277 if (details) { 2278 this.add_(propertyMirror.value()); 2279 } 2280 } 2281 for (var i = 0; i < propertyIndexes.length; i++) { 2282 var propertyMirror = mirror.property(propertyIndexes[i]); 2283 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror); 2284 if (details) { 2285 this.add_(propertyMirror.value()); 2286 } 2287 } 2288 content.properties = p; 2289 }; 2290 2291 2292 /** 2293 * Serialize location information to the following JSON format: 2294 * 2295 * "position":"<position>", 2296 * "line":"<line>", 2297 * "column":"<column>", 2298 * 2299 * @param {SourceLocation} location The location to serialize, may be undefined. 2300 */ 2301 function serializeLocationFields (location, content) { 2302 if (!location) { 2303 return; 2304 } 2305 content.position = location.position; 2306 var line = location.line; 2307 if (!IS_UNDEFINED(line)) { 2308 content.line = line; 2309 } 2310 var column = location.column; 2311 if (!IS_UNDEFINED(column)) { 2312 content.column = column; 2313 } 2314 } 2315 2316 2317 /** 2318 * Serialize property information to the following JSON format for building the 2319 * array of properties. 2320 * 2321 * {"name":"<property name>", 2322 * "attributes":<number>, 2323 * "propertyType":<number>, 2324 * "ref":<number>} 2325 * 2326 * If the attribute for the property is PropertyAttribute.None it is not added. 2327 * If the propertyType for the property is PropertyType.Normal it is not added. 2328 * Here are a couple of examples. 2329 * 2330 * {"name":"hello","ref":1} 2331 * {"name":"length","attributes":7,"propertyType":3,"ref":2} 2332 * 2333 * @param {PropertyMirror} propertyMirror The property to serialize. 2334 * @returns {Object} Protocol object representing the property. 2335 */ 2336 JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) { 2337 var result = {}; 2338 2339 result.name = propertyMirror.name(); 2340 var propertyValue = propertyMirror.value(); 2341 if (this.inlineRefs_() && propertyValue.isValue()) { 2342 result.value = this.serializeReferenceWithDisplayData_(propertyValue); 2343 } else { 2344 if (propertyMirror.attributes() != PropertyAttribute.None) { 2345 result.attributes = propertyMirror.attributes(); 2346 } 2347 if (propertyMirror.propertyType() != PropertyType.Normal) { 2348 result.propertyType = propertyMirror.propertyType(); 2349 } 2350 result.ref = propertyValue.handle(); 2351 } 2352 return result; 2353 }; 2354 2355 2356 JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) { 2357 content.index = mirror.index(); 2358 content.receiver = this.serializeReference(mirror.receiver()); 2359 var func = mirror.func(); 2360 content.func = this.serializeReference(func); 2361 if (func.script()) { 2362 content.script = this.serializeReference(func.script()); 2363 } 2364 content.constructCall = mirror.isConstructCall(); 2365 content.atReturn = mirror.isAtReturn(); 2366 if (mirror.isAtReturn()) { 2367 content.returnValue = this.serializeReference(mirror.returnValue()); 2368 } 2369 content.debuggerFrame = mirror.isDebuggerFrame(); 2370 var x = new Array(mirror.argumentCount()); 2371 for (var i = 0; i < mirror.argumentCount(); i++) { 2372 var arg = {}; 2373 var argument_name = mirror.argumentName(i); 2374 if (argument_name) { 2375 arg.name = argument_name; 2376 } 2377 arg.value = this.serializeReference(mirror.argumentValue(i)); 2378 x[i] = arg; 2379 } 2380 content.arguments = x; 2381 var x = new Array(mirror.localCount()); 2382 for (var i = 0; i < mirror.localCount(); i++) { 2383 var local = {}; 2384 local.name = mirror.localName(i); 2385 local.value = this.serializeReference(mirror.localValue(i)); 2386 x[i] = local; 2387 } 2388 content.locals = x; 2389 serializeLocationFields(mirror.sourceLocation(), content); 2390 var source_line_text = mirror.sourceLineText(); 2391 if (!IS_UNDEFINED(source_line_text)) { 2392 content.sourceLineText = source_line_text; 2393 } 2394 2395 content.scopes = []; 2396 for (var i = 0; i < mirror.scopeCount(); i++) { 2397 var scope = mirror.scope(i); 2398 content.scopes.push({ 2399 type: scope.scopeType(), 2400 index: i 2401 }); 2402 } 2403 }; 2404 2405 2406 JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) { 2407 content.index = mirror.scopeIndex(); 2408 content.frameIndex = mirror.frameIndex(); 2409 content.type = mirror.scopeType(); 2410 content.object = this.inlineRefs_() ? 2411 this.serializeValue(mirror.scopeObject()) : 2412 this.serializeReference(mirror.scopeObject()); 2413 }; 2414 2415 2416 /** 2417 * Convert a number to a protocol value. For all finite numbers the number 2418 * itself is returned. For non finite numbers NaN, Infinite and 2419 * -Infinite the string representation "NaN", "Infinite" or "-Infinite" 2420 * (not including the quotes) is returned. 2421 * 2422 * @param {number} value The number value to convert to a protocol value. 2423 * @returns {number|string} Protocol value. 2424 */ 2425 function NumberToJSON_(value) { 2426 if (isNaN(value)) { 2427 return 'NaN'; 2428 } 2429 if (!NUMBER_IS_FINITE(value)) { 2430 if (value > 0) { 2431 return 'Infinity'; 2432 } else { 2433 return '-Infinity'; 2434 } 2435 } 2436 return value; 2437 } 2438