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. 29var next_handle_ = 0; 30var next_transient_handle_ = -1; 31 32// Mirror cache. 33var mirror_cache_ = []; 34 35 36/** 37 * Clear the mirror handle cache. 38 */ 39function 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 */ 53function 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 */ 109function 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 */ 119function 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 */ 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. 147var UNDEFINED_TYPE = 'undefined'; 148var NULL_TYPE = 'null'; 149var BOOLEAN_TYPE = 'boolean'; 150var NUMBER_TYPE = 'number'; 151var STRING_TYPE = 'string'; 152var OBJECT_TYPE = 'object'; 153var FUNCTION_TYPE = 'function'; 154var REGEXP_TYPE = 'regexp'; 155var ERROR_TYPE = 'error'; 156var PROPERTY_TYPE = 'property'; 157var FRAME_TYPE = 'frame'; 158var SCRIPT_TYPE = 'script'; 159var CONTEXT_TYPE = 'context'; 160var SCOPE_TYPE = 'scope'; 161 162// Maximum length when sending strings through the JSON protocol. 163var kMaxProtocolStringLength = 80; 164 165// Different kind of properties. 166var PropertyKind = {}; 167PropertyKind.Named = 1; 168PropertyKind.Indexed = 2; 169 170 171// A copy of the PropertyType enum from global.h 172var PropertyType = {}; 173PropertyType.Normal = 0; 174PropertyType.Field = 1; 175PropertyType.ConstantFunction = 2; 176PropertyType.Callbacks = 3; 177PropertyType.Handler = 4; 178PropertyType.Interceptor = 5; 179PropertyType.MapTransition = 6; 180PropertyType.ExternalArrayTransition = 7; 181PropertyType.ConstantTransition = 8; 182PropertyType.NullDescriptor = 9; 183 184 185// Different attributes for a property. 186var PropertyAttribute = {}; 187PropertyAttribute.None = NONE; 188PropertyAttribute.ReadOnly = READ_ONLY; 189PropertyAttribute.DontEnum = DONT_ENUM; 190PropertyAttribute.DontDelete = DONT_DELETE; 191 192 193// A copy of the scope types from runtime.cc. 194var 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 */ 226function Mirror(type) { 227 this.type_ = type; 228} 229 230 231Mirror.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 */ 240Mirror.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 */ 249Mirror.prototype.isUndefined = function() { 250 return this instanceof UndefinedMirror; 251}; 252 253 254/** 255 * Check whether the mirror reflects the null value. 256 * @returns {boolean} True if the mirror reflects the null value 257 */ 258Mirror.prototype.isNull = function() { 259 return this instanceof NullMirror; 260}; 261 262 263/** 264 * Check whether the mirror reflects a boolean value. 265 * @returns {boolean} True if the mirror reflects a boolean value 266 */ 267Mirror.prototype.isBoolean = function() { 268 return this instanceof BooleanMirror; 269}; 270 271 272/** 273 * Check whether the mirror reflects a number value. 274 * @returns {boolean} True if the mirror reflects a number value 275 */ 276Mirror.prototype.isNumber = function() { 277 return this instanceof NumberMirror; 278}; 279 280 281/** 282 * Check whether the mirror reflects a string value. 283 * @returns {boolean} True if the mirror reflects a string value 284 */ 285Mirror.prototype.isString = function() { 286 return this instanceof StringMirror; 287}; 288 289 290/** 291 * Check whether the mirror reflects an object. 292 * @returns {boolean} True if the mirror reflects an object 293 */ 294Mirror.prototype.isObject = function() { 295 return this instanceof ObjectMirror; 296}; 297 298 299/** 300 * Check whether the mirror reflects a function. 301 * @returns {boolean} True if the mirror reflects a function 302 */ 303Mirror.prototype.isFunction = function() { 304 return this instanceof FunctionMirror; 305}; 306 307 308/** 309 * Check whether the mirror reflects an unresolved function. 310 * @returns {boolean} True if the mirror reflects an unresolved function 311 */ 312Mirror.prototype.isUnresolvedFunction = function() { 313 return this instanceof UnresolvedFunctionMirror; 314}; 315 316 317/** 318 * Check whether the mirror reflects an array. 319 * @returns {boolean} True if the mirror reflects an array 320 */ 321Mirror.prototype.isArray = function() { 322 return this instanceof ArrayMirror; 323}; 324 325 326/** 327 * Check whether the mirror reflects a date. 328 * @returns {boolean} True if the mirror reflects a date 329 */ 330Mirror.prototype.isDate = function() { 331 return this instanceof DateMirror; 332}; 333 334 335/** 336 * Check whether the mirror reflects a regular expression. 337 * @returns {boolean} True if the mirror reflects a regular expression 338 */ 339Mirror.prototype.isRegExp = function() { 340 return this instanceof RegExpMirror; 341}; 342 343 344/** 345 * Check whether the mirror reflects an error. 346 * @returns {boolean} True if the mirror reflects an error 347 */ 348Mirror.prototype.isError = function() { 349 return this instanceof ErrorMirror; 350}; 351 352 353/** 354 * Check whether the mirror reflects a property. 355 * @returns {boolean} True if the mirror reflects a property 356 */ 357Mirror.prototype.isProperty = function() { 358 return this instanceof PropertyMirror; 359}; 360 361 362/** 363 * Check whether the mirror reflects a stack frame. 364 * @returns {boolean} True if the mirror reflects a stack frame 365 */ 366Mirror.prototype.isFrame = function() { 367 return this instanceof FrameMirror; 368}; 369 370 371/** 372 * Check whether the mirror reflects a script. 373 * @returns {boolean} True if the mirror reflects a script 374 */ 375Mirror.prototype.isScript = function() { 376 return this instanceof ScriptMirror; 377}; 378 379 380/** 381 * Check whether the mirror reflects a context. 382 * @returns {boolean} True if the mirror reflects a context 383 */ 384Mirror.prototype.isContext = function() { 385 return this instanceof ContextMirror; 386}; 387 388 389/** 390 * Check whether the mirror reflects a scope. 391 * @returns {boolean} True if the mirror reflects a scope 392 */ 393Mirror.prototype.isScope = function() { 394 return this instanceof ScopeMirror; 395}; 396 397 398/** 399 * Allocate a handle id for this object. 400 */ 401Mirror.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 */ 410Mirror.prototype.allocateTransientHandle_ = function() { 411 this.handle_ = next_transient_handle_--; 412}; 413 414 415Mirror.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 */ 430function 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} 439inherits(ValueMirror, Mirror); 440 441 442Mirror.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 */ 451ValueMirror.prototype.isPrimitive = function() { 452 var type = this.type(); 453 return type === 'undefined' || 454 type === 'null' || 455 type === 'boolean' || 456 type === 'number' || 457 type === 'string'; 458}; 459 460 461/** 462 * Get the actual value reflected by this mirror. 463 * @return {value} The value reflected by this mirror 464 */ 465ValueMirror.prototype.value = function() { 466 return this.value_; 467}; 468 469 470/** 471 * Mirror object for Undefined. 472 * @constructor 473 * @extends ValueMirror 474 */ 475function UndefinedMirror() { 476 %_CallFunction(this, UNDEFINED_TYPE, void 0, ValueMirror); 477} 478inherits(UndefinedMirror, ValueMirror); 479 480 481UndefinedMirror.prototype.toText = function() { 482 return 'undefined'; 483}; 484 485 486/** 487 * Mirror object for null. 488 * @constructor 489 * @extends ValueMirror 490 */ 491function NullMirror() { 492 %_CallFunction(this, NULL_TYPE, null, ValueMirror); 493} 494inherits(NullMirror, ValueMirror); 495 496 497NullMirror.prototype.toText = function() { 498 return 'null'; 499}; 500 501 502/** 503 * Mirror object for boolean values. 504 * @param {boolean} value The boolean value reflected by this mirror 505 * @constructor 506 * @extends ValueMirror 507 */ 508function BooleanMirror(value) { 509 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror); 510} 511inherits(BooleanMirror, ValueMirror); 512 513 514BooleanMirror.prototype.toText = function() { 515 return this.value_ ? 'true' : 'false'; 516}; 517 518 519/** 520 * Mirror object for number values. 521 * @param {number} value The number value reflected by this mirror 522 * @constructor 523 * @extends ValueMirror 524 */ 525function NumberMirror(value) { 526 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror); 527} 528inherits(NumberMirror, ValueMirror); 529 530 531NumberMirror.prototype.toText = function() { 532 return %NumberToString(this.value_); 533}; 534 535 536/** 537 * Mirror object for string values. 538 * @param {string} value The string value reflected by this mirror 539 * @constructor 540 * @extends ValueMirror 541 */ 542function StringMirror(value) { 543 %_CallFunction(this, STRING_TYPE, value, ValueMirror); 544} 545inherits(StringMirror, ValueMirror); 546 547 548StringMirror.prototype.length = function() { 549 return this.value_.length; 550}; 551 552StringMirror.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 560StringMirror.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 */ 573function ObjectMirror(value, type, transient) { 574 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror); 575} 576inherits(ObjectMirror, ValueMirror); 577 578 579ObjectMirror.prototype.className = function() { 580 return %_ClassOf(this.value_); 581}; 582 583 584ObjectMirror.prototype.constructorFunction = function() { 585 return MakeMirror(%DebugGetProperty(this.value_, 'constructor')); 586}; 587 588 589ObjectMirror.prototype.prototypeObject = function() { 590 return MakeMirror(%DebugGetProperty(this.value_, 'prototype')); 591}; 592 593 594ObjectMirror.prototype.protoObject = function() { 595 return MakeMirror(%DebugGetPrototype(this.value_)); 596}; 597 598 599ObjectMirror.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 606ObjectMirror.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 */ 621ObjectMirror.prototype.propertyNames = function(kind, limit) { 622 // Find kind and limit and allocate array for the result 623 kind = kind || PropertyKind.Named | PropertyKind.Indexed; 624 625 var propertyNames; 626 var elementNames; 627 var total = 0; 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 */ 693ObjectMirror.prototype.properties = function(kind, limit) { 694 var names = this.propertyNames(kind, limit); 695 var properties = new Array(names.length); 696 for (var i = 0; i < names.length; i++) { 697 properties[i] = this.property(names[i]); 698 } 699 700 return properties; 701}; 702 703 704ObjectMirror.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 */ 722ObjectMirror.prototype.lookupProperty = function(value) { 723 var properties = this.properties(); 724 725 // Look for property value in properties. 726 for (var i = 0; i < properties.length; i++) { 727 728 // Skip properties which are defined through assessors. 729 var property = properties[i]; 730 if (property.propertyType() != PropertyType.Callbacks) { 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 */ 748ObjectMirror.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 762ObjectMirror.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 */ 783function FunctionMirror(value) { 784 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror); 785 this.resolved_ = true; 786} 787inherits(FunctionMirror, ObjectMirror); 788 789 790/** 791 * Returns whether the function is resolved. 792 * @return {boolean} True if the function is resolved. Unresolved functions can 793 * only originate as functions from stack frames 794 */ 795FunctionMirror.prototype.resolved = function() { 796 return this.resolved_; 797}; 798 799 800/** 801 * Returns the name of the function. 802 * @return {string} Name of the function 803 */ 804FunctionMirror.prototype.name = function() { 805 return %FunctionGetName(this.value_); 806}; 807 808 809/** 810 * Returns the inferred name of the function. 811 * @return {string} Name of the function 812 */ 813FunctionMirror.prototype.inferredName = function() { 814 return %FunctionGetInferredName(this.value_); 815}; 816 817 818/** 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 */ 823FunctionMirror.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 */ 837FunctionMirror.prototype.script = function() { 838 // Return script if function is resolved. Otherwise just fall through 839 // to return undefined. 840 if (this.resolved()) { 841 var script = %FunctionGetScript(this.value_); 842 if (script) { 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 */ 854FunctionMirror.prototype.sourcePosition_ = function() { 855 // Return script if function is resolved. Otherwise just fall through 856 // to return undefined. 857 if (this.resolved()) { 858 return %FunctionGetScriptSourcePosition(this.value_); 859 } 860}; 861 862 863/** 864 * Returns the script source location object for the function. Only makes sense 865 * for functions which has a script defined. 866 * @return {Location or undefined} in-script location for the function begin 867 */ 868FunctionMirror.prototype.sourceLocation = function() { 869 if (this.resolved() && this.script()) { 870 return this.script().locationFromPosition(this.sourcePosition_(), 871 true); 872 } 873}; 874 875 876/** 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 */ 882FunctionMirror.prototype.constructedBy = function(opt_max_instances) { 883 if (this.resolved()) { 884 // Find all objects constructed from this function. 885 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0); 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 899FunctionMirror.prototype.toText = function() { 900 return this.source(); 901}; 902 903 904/** 905 * Mirror object for unresolved functions. 906 * @param {string} value The name for the unresolved function reflected by this 907 * mirror. 908 * @constructor 909 * @extends ObjectMirror 910 */ 911function UnresolvedFunctionMirror(value) { 912 // Construct this using the ValueMirror as an unresolved function is not a 913 // real object but just a string. 914 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror); 915 this.propertyCount_ = 0; 916 this.elementCount_ = 0; 917 this.resolved_ = false; 918} 919inherits(UnresolvedFunctionMirror, FunctionMirror); 920 921 922UnresolvedFunctionMirror.prototype.className = function() { 923 return 'Function'; 924}; 925 926 927UnresolvedFunctionMirror.prototype.constructorFunction = function() { 928 return GetUndefinedMirror(); 929}; 930 931 932UnresolvedFunctionMirror.prototype.prototypeObject = function() { 933 return GetUndefinedMirror(); 934}; 935 936 937UnresolvedFunctionMirror.prototype.protoObject = function() { 938 return GetUndefinedMirror(); 939}; 940 941 942UnresolvedFunctionMirror.prototype.name = function() { 943 return this.value_; 944}; 945 946 947UnresolvedFunctionMirror.prototype.inferredName = function() { 948 return undefined; 949}; 950 951 952UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) { 953 return []; 954}; 955 956 957/** 958 * Mirror object for arrays. 959 * @param {Array} value The Array object reflected by this mirror 960 * @constructor 961 * @extends ObjectMirror 962 */ 963function ArrayMirror(value) { 964 %_CallFunction(this, value, ObjectMirror); 965} 966inherits(ArrayMirror, ObjectMirror); 967 968 969ArrayMirror.prototype.length = function() { 970 return this.value_.length; 971}; 972 973 974ArrayMirror.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 */ 1000function DateMirror(value) { 1001 %_CallFunction(this, value, ObjectMirror); 1002} 1003inherits(DateMirror, ObjectMirror); 1004 1005 1006DateMirror.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 */ 1018function RegExpMirror(value) { 1019 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror); 1020} 1021inherits(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 */ 1028RegExpMirror.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 */ 1037RegExpMirror.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 */ 1046RegExpMirror.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 */ 1055RegExpMirror.prototype.multiline = function() { 1056 return this.value_.multiline; 1057}; 1058 1059 1060RegExpMirror.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 */ 1072function ErrorMirror(value) { 1073 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror); 1074} 1075inherits(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 */ 1082ErrorMirror.prototype.message = function() { 1083 return this.value_.message; 1084}; 1085 1086 1087ErrorMirror.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 */ 1107function 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} 1119inherits(PropertyMirror, Mirror); 1120 1121 1122PropertyMirror.prototype.isReadOnly = function() { 1123 return (this.attributes() & PropertyAttribute.ReadOnly) != 0; 1124}; 1125 1126 1127PropertyMirror.prototype.isEnum = function() { 1128 return (this.attributes() & PropertyAttribute.DontEnum) == 0; 1129}; 1130 1131 1132PropertyMirror.prototype.canDelete = function() { 1133 return (this.attributes() & PropertyAttribute.DontDelete) == 0; 1134}; 1135 1136 1137PropertyMirror.prototype.name = function() { 1138 return this.name_; 1139}; 1140 1141 1142PropertyMirror.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 1152PropertyMirror.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 */ 1161PropertyMirror.prototype.isException = function() { 1162 return this.exception_ ? true : false; 1163}; 1164 1165 1166PropertyMirror.prototype.attributes = function() { 1167 return %DebugPropertyAttributesFromDetails(this.details_); 1168}; 1169 1170 1171PropertyMirror.prototype.propertyType = function() { 1172 return %DebugPropertyTypeFromDetails(this.details_); 1173}; 1174 1175 1176PropertyMirror.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 */ 1185PropertyMirror.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 */ 1194PropertyMirror.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 */ 1204PropertyMirror.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 */ 1218PropertyMirror.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 */ 1233PropertyMirror.prototype.isNative = function() { 1234 return (this.propertyType() == PropertyType.Interceptor) || 1235 ((this.propertyType() == PropertyType.Callbacks) && 1236 !this.hasGetter() && !this.hasSetter()); 1237}; 1238 1239 1240var kFrameDetailsFrameIdIndex = 0; 1241var kFrameDetailsReceiverIndex = 1; 1242var kFrameDetailsFunctionIndex = 2; 1243var kFrameDetailsArgumentCountIndex = 3; 1244var kFrameDetailsLocalCountIndex = 4; 1245var kFrameDetailsSourcePositionIndex = 5; 1246var kFrameDetailsConstructCallIndex = 6; 1247var kFrameDetailsAtReturnIndex = 7; 1248var kFrameDetailsFlagsIndex = 8; 1249var kFrameDetailsFirstDynamicIndex = 9; 1250 1251var kFrameDetailsNameIndex = 0; 1252var kFrameDetailsValueIndex = 1; 1253var kFrameDetailsNameValueSize = 2; 1254 1255var kFrameDetailsFlagDebuggerFrameMask = 1 << 0; 1256var kFrameDetailsFlagOptimizedFrameMask = 1 << 1; 1257var 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 */ 1279function FrameDetails(break_id, index) { 1280 this.break_id_ = break_id; 1281 this.details_ = %GetFrameDetails(break_id, index); 1282} 1283 1284 1285FrameDetails.prototype.frameId = function() { 1286 %CheckExecutionState(this.break_id_); 1287 return this.details_[kFrameDetailsFrameIdIndex]; 1288}; 1289 1290 1291FrameDetails.prototype.receiver = function() { 1292 %CheckExecutionState(this.break_id_); 1293 return this.details_[kFrameDetailsReceiverIndex]; 1294}; 1295 1296 1297FrameDetails.prototype.func = function() { 1298 %CheckExecutionState(this.break_id_); 1299 return this.details_[kFrameDetailsFunctionIndex]; 1300}; 1301 1302 1303FrameDetails.prototype.isConstructCall = function() { 1304 %CheckExecutionState(this.break_id_); 1305 return this.details_[kFrameDetailsConstructCallIndex]; 1306}; 1307 1308 1309FrameDetails.prototype.isAtReturn = function() { 1310 %CheckExecutionState(this.break_id_); 1311 return this.details_[kFrameDetailsAtReturnIndex]; 1312}; 1313 1314 1315FrameDetails.prototype.isDebuggerFrame = function() { 1316 %CheckExecutionState(this.break_id_); 1317 var f = kFrameDetailsFlagDebuggerFrameMask; 1318 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1319}; 1320 1321 1322FrameDetails.prototype.isOptimizedFrame = function() { 1323 %CheckExecutionState(this.break_id_); 1324 var f = kFrameDetailsFlagOptimizedFrameMask; 1325 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1326}; 1327 1328 1329FrameDetails.prototype.isInlinedFrame = function() { 1330 return this.inlinedFrameIndex() > 0; 1331}; 1332 1333 1334FrameDetails.prototype.inlinedFrameIndex = function() { 1335 %CheckExecutionState(this.break_id_); 1336 var f = kFrameDetailsFlagInlinedFrameIndexMask; 1337 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2; 1338}; 1339 1340 1341FrameDetails.prototype.argumentCount = function() { 1342 %CheckExecutionState(this.break_id_); 1343 return this.details_[kFrameDetailsArgumentCountIndex]; 1344}; 1345 1346 1347FrameDetails.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 1357FrameDetails.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 1367FrameDetails.prototype.localCount = function() { 1368 %CheckExecutionState(this.break_id_); 1369 return this.details_[kFrameDetailsLocalCountIndex]; 1370}; 1371 1372 1373FrameDetails.prototype.sourcePosition = function() { 1374 %CheckExecutionState(this.break_id_); 1375 return this.details_[kFrameDetailsSourcePositionIndex]; 1376}; 1377 1378 1379FrameDetails.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 1391FrameDetails.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 1403FrameDetails.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 1414FrameDetails.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 */ 1427function 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} 1433inherits(FrameMirror, Mirror); 1434 1435 1436FrameMirror.prototype.index = function() { 1437 return this.index_; 1438}; 1439 1440 1441FrameMirror.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 1456FrameMirror.prototype.receiver = function() { 1457 return MakeMirror(this.details_.receiver()); 1458}; 1459 1460 1461FrameMirror.prototype.isConstructCall = function() { 1462 return this.details_.isConstructCall(); 1463}; 1464 1465 1466FrameMirror.prototype.isAtReturn = function() { 1467 return this.details_.isAtReturn(); 1468}; 1469 1470 1471FrameMirror.prototype.isDebuggerFrame = function() { 1472 return this.details_.isDebuggerFrame(); 1473}; 1474 1475 1476FrameMirror.prototype.isOptimizedFrame = function() { 1477 return this.details_.isOptimizedFrame(); 1478}; 1479 1480 1481FrameMirror.prototype.isInlinedFrame = function() { 1482 return this.details_.isInlinedFrame(); 1483}; 1484 1485 1486FrameMirror.prototype.inlinedFrameIndex = function() { 1487 return this.details_.inlinedFrameIndex(); 1488}; 1489 1490 1491FrameMirror.prototype.argumentCount = function() { 1492 return this.details_.argumentCount(); 1493}; 1494 1495 1496FrameMirror.prototype.argumentName = function(index) { 1497 return this.details_.argumentName(index); 1498}; 1499 1500 1501FrameMirror.prototype.argumentValue = function(index) { 1502 return MakeMirror(this.details_.argumentValue(index)); 1503}; 1504 1505 1506FrameMirror.prototype.localCount = function() { 1507 return this.details_.localCount(); 1508}; 1509 1510 1511FrameMirror.prototype.localName = function(index) { 1512 return this.details_.localName(index); 1513}; 1514 1515 1516FrameMirror.prototype.localValue = function(index) { 1517 return MakeMirror(this.details_.localValue(index)); 1518}; 1519 1520 1521FrameMirror.prototype.returnValue = function() { 1522 return MakeMirror(this.details_.returnValue()); 1523}; 1524 1525 1526FrameMirror.prototype.sourcePosition = function() { 1527 return this.details_.sourcePosition(); 1528}; 1529 1530 1531FrameMirror.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 1539FrameMirror.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 1549FrameMirror.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 1559FrameMirror.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 1569FrameMirror.prototype.scopeCount = function() { 1570 return this.details_.scopeCount(); 1571}; 1572 1573 1574FrameMirror.prototype.scope = function(index) { 1575 return new ScopeMirror(this, index); 1576}; 1577 1578 1579FrameMirror.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 1591FrameMirror.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 1670FrameMirror.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 1702FrameMirror.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 1720FrameMirror.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 1735var kScopeDetailsTypeIndex = 0; 1736var kScopeDetailsObjectIndex = 1; 1737 1738function 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 1747ScopeDetails.prototype.type = function() { 1748 %CheckExecutionState(this.break_id_); 1749 return this.details_[kScopeDetailsTypeIndex]; 1750}; 1751 1752 1753ScopeDetails.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 */ 1766function 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} 1772inherits(ScopeMirror, Mirror); 1773 1774 1775ScopeMirror.prototype.frameIndex = function() { 1776 return this.frame_index_; 1777}; 1778 1779 1780ScopeMirror.prototype.scopeIndex = function() { 1781 return this.scope_index_; 1782}; 1783 1784 1785ScopeMirror.prototype.scopeType = function() { 1786 return this.details_.type(); 1787}; 1788 1789 1790ScopeMirror.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 */ 1806function ScriptMirror(script) { 1807 %_CallFunction(this, SCRIPT_TYPE, Mirror); 1808 this.script_ = script; 1809 this.context_ = new ContextMirror(script.context_data); 1810 this.allocateHandle_(); 1811} 1812inherits(ScriptMirror, Mirror); 1813 1814 1815ScriptMirror.prototype.value = function() { 1816 return this.script_; 1817}; 1818 1819 1820ScriptMirror.prototype.name = function() { 1821 return this.script_.name || this.script_.nameOrSourceURL(); 1822}; 1823 1824 1825ScriptMirror.prototype.id = function() { 1826 return this.script_.id; 1827}; 1828 1829 1830ScriptMirror.prototype.source = function() { 1831 return this.script_.source; 1832}; 1833 1834 1835ScriptMirror.prototype.setSource = function(source) { 1836 %DebugSetScriptSource(this.script_, source); 1837}; 1838 1839 1840ScriptMirror.prototype.lineOffset = function() { 1841 return this.script_.line_offset; 1842}; 1843 1844 1845ScriptMirror.prototype.columnOffset = function() { 1846 return this.script_.column_offset; 1847}; 1848 1849 1850ScriptMirror.prototype.data = function() { 1851 return this.script_.data; 1852}; 1853 1854 1855ScriptMirror.prototype.scriptType = function() { 1856 return this.script_.type; 1857}; 1858 1859 1860ScriptMirror.prototype.compilationType = function() { 1861 return this.script_.compilation_type; 1862}; 1863 1864 1865ScriptMirror.prototype.lineCount = function() { 1866 return this.script_.lineCount(); 1867}; 1868 1869 1870ScriptMirror.prototype.locationFromPosition = function( 1871 position, include_resource_offset) { 1872 return this.script_.locationFromPosition(position, include_resource_offset); 1873}; 1874 1875 1876ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) { 1877 return this.script_.sourceSlice(opt_from_line, opt_to_line); 1878}; 1879 1880 1881ScriptMirror.prototype.context = function() { 1882 return this.context_; 1883}; 1884 1885 1886ScriptMirror.prototype.evalFromScript = function() { 1887 return MakeMirror(this.script_.eval_from_script); 1888}; 1889 1890 1891ScriptMirror.prototype.evalFromFunctionName = function() { 1892 return MakeMirror(this.script_.eval_from_function_name); 1893}; 1894 1895 1896ScriptMirror.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 1905ScriptMirror.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 */ 1927function ContextMirror(data) { 1928 %_CallFunction(this, CONTEXT_TYPE, Mirror); 1929 this.data_ = data; 1930 this.allocateHandle_(); 1931} 1932inherits(ContextMirror, Mirror); 1933 1934 1935ContextMirror.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 */ 1949function 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 */ 1960function 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 */ 1974JSONProtocolSerializer.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 */ 1986JSONProtocolSerializer.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 */ 1999JSONProtocolSerializer.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 2014JSONProtocolSerializer.prototype.includeSource_ = function() { 2015 return this.options_ && this.options_.includeSource; 2016}; 2017 2018 2019JSONProtocolSerializer.prototype.inlineRefs_ = function() { 2020 return this.options_ && this.options_.inlineRefs; 2021}; 2022 2023 2024JSONProtocolSerializer.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 2033JSONProtocolSerializer.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 */ 2052JSONProtocolSerializer.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 2086JSONProtocolSerializer.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 */ 2228JSONProtocolSerializer.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 */ 2301function 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 */ 2336JSONProtocolSerializer.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 2356JSONProtocolSerializer.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 2406JSONProtocolSerializer.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 */ 2425function 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