1// Copyright 2006-2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Handle id counters. 6var next_handle_ = 0; 7var next_transient_handle_ = -1; 8 9// Mirror cache. 10var mirror_cache_ = []; 11var mirror_cache_enabled_ = true; 12 13 14function ToggleMirrorCache(value) { 15 mirror_cache_enabled_ = value; 16 next_handle_ = 0; 17 mirror_cache_ = []; 18} 19 20 21// Wrapper to check whether an object is a Promise. The call may not work 22// if promises are not enabled. 23// TODO(yangguo): remove try-catch once promises are enabled by default. 24function ObjectIsPromise(value) { 25 try { 26 return IS_SPEC_OBJECT(value) && 27 !IS_UNDEFINED(%DebugGetProperty(value, builtins.promiseStatus)); 28 } catch (e) { 29 return false; 30 } 31} 32 33 34/** 35 * Returns the mirror for a specified value or object. 36 * 37 * @param {value or Object} value the value or object to retreive the mirror for 38 * @param {boolean} transient indicate whether this object is transient and 39 * should not be added to the mirror cache. The default is not transient. 40 * @returns {Mirror} the mirror reflects the passed value or object 41 */ 42function MakeMirror(value, opt_transient) { 43 var mirror; 44 45 // Look for non transient mirrors in the mirror cache. 46 if (!opt_transient && mirror_cache_enabled_) { 47 for (id in mirror_cache_) { 48 mirror = mirror_cache_[id]; 49 if (mirror.value() === value) { 50 return mirror; 51 } 52 // Special check for NaN as NaN == NaN is false. 53 if (mirror.isNumber() && isNaN(mirror.value()) && 54 typeof value == 'number' && isNaN(value)) { 55 return mirror; 56 } 57 } 58 } 59 60 if (IS_UNDEFINED(value)) { 61 mirror = new UndefinedMirror(); 62 } else if (IS_NULL(value)) { 63 mirror = new NullMirror(); 64 } else if (IS_BOOLEAN(value)) { 65 mirror = new BooleanMirror(value); 66 } else if (IS_NUMBER(value)) { 67 mirror = new NumberMirror(value); 68 } else if (IS_STRING(value)) { 69 mirror = new StringMirror(value); 70 } else if (IS_SYMBOL(value)) { 71 mirror = new SymbolMirror(value); 72 } else if (IS_ARRAY(value)) { 73 mirror = new ArrayMirror(value); 74 } else if (IS_DATE(value)) { 75 mirror = new DateMirror(value); 76 } else if (IS_FUNCTION(value)) { 77 mirror = new FunctionMirror(value); 78 } else if (IS_REGEXP(value)) { 79 mirror = new RegExpMirror(value); 80 } else if (IS_ERROR(value)) { 81 mirror = new ErrorMirror(value); 82 } else if (IS_SCRIPT(value)) { 83 mirror = new ScriptMirror(value); 84 } else if (IS_MAP(value) || IS_WEAKMAP(value)) { 85 mirror = new MapMirror(value); 86 } else if (IS_SET(value) || IS_WEAKSET(value)) { 87 mirror = new SetMirror(value); 88 } else if (ObjectIsPromise(value)) { 89 mirror = new PromiseMirror(value); 90 } else if (IS_GENERATOR(value)) { 91 mirror = new GeneratorMirror(value); 92 } else { 93 mirror = new ObjectMirror(value, OBJECT_TYPE, opt_transient); 94 } 95 96 if (mirror_cache_enabled_) mirror_cache_[mirror.handle()] = mirror; 97 return mirror; 98} 99 100 101/** 102 * Returns the mirror for a specified mirror handle. 103 * 104 * @param {number} handle the handle to find the mirror for 105 * @returns {Mirror or undefiend} the mirror with the requested handle or 106 * undefined if no mirror with the requested handle was found 107 */ 108function LookupMirror(handle) { 109 if (!mirror_cache_enabled_) throw new Error("Mirror cache is disabled"); 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(UNDEFINED); 121} 122 123 124/** 125 * Inherit the prototype methods from one constructor into another. 126 * 127 * The Function.prototype.inherits from lang.js rewritten as a standalone 128 * function (not on Function.prototype). NOTE: If this file is to be loaded 129 * during bootstrapping this function needs to be revritten using some native 130 * functions as prototype setup using normal JavaScript does not work as 131 * expected during bootstrapping (see mirror.js in r114903). 132 * 133 * @param {function} ctor Constructor function which needs to inherit the 134 * prototype 135 * @param {function} superCtor Constructor function to inherit prototype from 136 */ 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 SYMBOL_TYPE = 'symbol'; 153var OBJECT_TYPE = 'object'; 154var FUNCTION_TYPE = 'function'; 155var REGEXP_TYPE = 'regexp'; 156var ERROR_TYPE = 'error'; 157var PROPERTY_TYPE = 'property'; 158var INTERNAL_PROPERTY_TYPE = 'internalProperty'; 159var FRAME_TYPE = 'frame'; 160var SCRIPT_TYPE = 'script'; 161var CONTEXT_TYPE = 'context'; 162var SCOPE_TYPE = 'scope'; 163var PROMISE_TYPE = 'promise'; 164var MAP_TYPE = 'map'; 165var SET_TYPE = 'set'; 166var GENERATOR_TYPE = 'generator'; 167 168// Maximum length when sending strings through the JSON protocol. 169var kMaxProtocolStringLength = 80; 170 171// Different kind of properties. 172var PropertyKind = {}; 173PropertyKind.Named = 1; 174PropertyKind.Indexed = 2; 175 176 177// A copy of the PropertyType enum from property-details.h 178var PropertyType = {}; 179PropertyType.Normal = 0; 180PropertyType.Field = 1; 181PropertyType.Constant = 2; 182PropertyType.Callbacks = 3; 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// - SymbolMirror 210// - ObjectMirror 211// - FunctionMirror 212// - UnresolvedFunctionMirror 213// - ArrayMirror 214// - DateMirror 215// - RegExpMirror 216// - ErrorMirror 217// - PromiseMirror 218// - MapMirror 219// - SetMirror 220// - GeneratorMirror 221// - PropertyMirror 222// - InternalPropertyMirror 223// - FrameMirror 224// - ScriptMirror 225 226 227/** 228 * Base class for all mirror objects. 229 * @param {string} type The type of the mirror 230 * @constructor 231 */ 232function Mirror(type) { 233 this.type_ = type; 234} 235 236 237Mirror.prototype.type = function() { 238 return this.type_; 239}; 240 241 242/** 243 * Check whether the mirror reflects a value. 244 * @returns {boolean} True if the mirror reflects a value. 245 */ 246Mirror.prototype.isValue = function() { 247 return this instanceof ValueMirror; 248}; 249 250 251/** 252 * Check whether the mirror reflects the undefined value. 253 * @returns {boolean} True if the mirror reflects the undefined value. 254 */ 255Mirror.prototype.isUndefined = function() { 256 return this instanceof UndefinedMirror; 257}; 258 259 260/** 261 * Check whether the mirror reflects the null value. 262 * @returns {boolean} True if the mirror reflects the null value 263 */ 264Mirror.prototype.isNull = function() { 265 return this instanceof NullMirror; 266}; 267 268 269/** 270 * Check whether the mirror reflects a boolean value. 271 * @returns {boolean} True if the mirror reflects a boolean value 272 */ 273Mirror.prototype.isBoolean = function() { 274 return this instanceof BooleanMirror; 275}; 276 277 278/** 279 * Check whether the mirror reflects a number value. 280 * @returns {boolean} True if the mirror reflects a number value 281 */ 282Mirror.prototype.isNumber = function() { 283 return this instanceof NumberMirror; 284}; 285 286 287/** 288 * Check whether the mirror reflects a string value. 289 * @returns {boolean} True if the mirror reflects a string value 290 */ 291Mirror.prototype.isString = function() { 292 return this instanceof StringMirror; 293}; 294 295 296/** 297 * Check whether the mirror reflects a symbol. 298 * @returns {boolean} True if the mirror reflects a symbol 299 */ 300Mirror.prototype.isSymbol = function() { 301 return this instanceof SymbolMirror; 302}; 303 304 305/** 306 * Check whether the mirror reflects an object. 307 * @returns {boolean} True if the mirror reflects an object 308 */ 309Mirror.prototype.isObject = function() { 310 return this instanceof ObjectMirror; 311}; 312 313 314/** 315 * Check whether the mirror reflects a function. 316 * @returns {boolean} True if the mirror reflects a function 317 */ 318Mirror.prototype.isFunction = function() { 319 return this instanceof FunctionMirror; 320}; 321 322 323/** 324 * Check whether the mirror reflects an unresolved function. 325 * @returns {boolean} True if the mirror reflects an unresolved function 326 */ 327Mirror.prototype.isUnresolvedFunction = function() { 328 return this instanceof UnresolvedFunctionMirror; 329}; 330 331 332/** 333 * Check whether the mirror reflects an array. 334 * @returns {boolean} True if the mirror reflects an array 335 */ 336Mirror.prototype.isArray = function() { 337 return this instanceof ArrayMirror; 338}; 339 340 341/** 342 * Check whether the mirror reflects a date. 343 * @returns {boolean} True if the mirror reflects a date 344 */ 345Mirror.prototype.isDate = function() { 346 return this instanceof DateMirror; 347}; 348 349 350/** 351 * Check whether the mirror reflects a regular expression. 352 * @returns {boolean} True if the mirror reflects a regular expression 353 */ 354Mirror.prototype.isRegExp = function() { 355 return this instanceof RegExpMirror; 356}; 357 358 359/** 360 * Check whether the mirror reflects an error. 361 * @returns {boolean} True if the mirror reflects an error 362 */ 363Mirror.prototype.isError = function() { 364 return this instanceof ErrorMirror; 365}; 366 367 368/** 369 * Check whether the mirror reflects a promise. 370 * @returns {boolean} True if the mirror reflects a promise 371 */ 372Mirror.prototype.isPromise = function() { 373 return this instanceof PromiseMirror; 374}; 375 376 377/** 378 * Check whether the mirror reflects a generator object. 379 * @returns {boolean} True if the mirror reflects a generator object 380 */ 381Mirror.prototype.isGenerator = function() { 382 return this instanceof GeneratorMirror; 383}; 384 385 386/** 387 * Check whether the mirror reflects a property. 388 * @returns {boolean} True if the mirror reflects a property 389 */ 390Mirror.prototype.isProperty = function() { 391 return this instanceof PropertyMirror; 392}; 393 394 395/** 396 * Check whether the mirror reflects an internal property. 397 * @returns {boolean} True if the mirror reflects an internal property 398 */ 399Mirror.prototype.isInternalProperty = function() { 400 return this instanceof InternalPropertyMirror; 401}; 402 403 404/** 405 * Check whether the mirror reflects a stack frame. 406 * @returns {boolean} True if the mirror reflects a stack frame 407 */ 408Mirror.prototype.isFrame = function() { 409 return this instanceof FrameMirror; 410}; 411 412 413/** 414 * Check whether the mirror reflects a script. 415 * @returns {boolean} True if the mirror reflects a script 416 */ 417Mirror.prototype.isScript = function() { 418 return this instanceof ScriptMirror; 419}; 420 421 422/** 423 * Check whether the mirror reflects a context. 424 * @returns {boolean} True if the mirror reflects a context 425 */ 426Mirror.prototype.isContext = function() { 427 return this instanceof ContextMirror; 428}; 429 430 431/** 432 * Check whether the mirror reflects a scope. 433 * @returns {boolean} True if the mirror reflects a scope 434 */ 435Mirror.prototype.isScope = function() { 436 return this instanceof ScopeMirror; 437}; 438 439 440/** 441 * Check whether the mirror reflects a map. 442 * @returns {boolean} True if the mirror reflects a map 443 */ 444Mirror.prototype.isMap = function() { 445 return this instanceof MapMirror; 446}; 447 448 449/** 450 * Check whether the mirror reflects a set. 451 * @returns {boolean} True if the mirror reflects a set 452 */ 453Mirror.prototype.isSet = function() { 454 return this instanceof SetMirror; 455}; 456 457 458/** 459 * Allocate a handle id for this object. 460 */ 461Mirror.prototype.allocateHandle_ = function() { 462 if (mirror_cache_enabled_) this.handle_ = next_handle_++; 463}; 464 465 466/** 467 * Allocate a transient handle id for this object. Transient handles are 468 * negative. 469 */ 470Mirror.prototype.allocateTransientHandle_ = function() { 471 this.handle_ = next_transient_handle_--; 472}; 473 474 475Mirror.prototype.toText = function() { 476 // Simpel to text which is used when on specialization in subclass. 477 return "#<" + this.constructor.name + ">"; 478}; 479 480 481/** 482 * Base class for all value mirror objects. 483 * @param {string} type The type of the mirror 484 * @param {value} value The value reflected by this mirror 485 * @param {boolean} transient indicate whether this object is transient with a 486 * transient handle 487 * @constructor 488 * @extends Mirror 489 */ 490function ValueMirror(type, value, transient) { 491 %_CallFunction(this, type, Mirror); 492 this.value_ = value; 493 if (!transient) { 494 this.allocateHandle_(); 495 } else { 496 this.allocateTransientHandle_(); 497 } 498} 499inherits(ValueMirror, Mirror); 500 501 502Mirror.prototype.handle = function() { 503 return this.handle_; 504}; 505 506 507/** 508 * Check whether this is a primitive value. 509 * @return {boolean} True if the mirror reflects a primitive value 510 */ 511ValueMirror.prototype.isPrimitive = function() { 512 var type = this.type(); 513 return type === 'undefined' || 514 type === 'null' || 515 type === 'boolean' || 516 type === 'number' || 517 type === 'string' || 518 type === 'symbol'; 519}; 520 521 522/** 523 * Get the actual value reflected by this mirror. 524 * @return {value} The value reflected by this mirror 525 */ 526ValueMirror.prototype.value = function() { 527 return this.value_; 528}; 529 530 531/** 532 * Mirror object for Undefined. 533 * @constructor 534 * @extends ValueMirror 535 */ 536function UndefinedMirror() { 537 %_CallFunction(this, UNDEFINED_TYPE, UNDEFINED, ValueMirror); 538} 539inherits(UndefinedMirror, ValueMirror); 540 541 542UndefinedMirror.prototype.toText = function() { 543 return 'undefined'; 544}; 545 546 547/** 548 * Mirror object for null. 549 * @constructor 550 * @extends ValueMirror 551 */ 552function NullMirror() { 553 %_CallFunction(this, NULL_TYPE, null, ValueMirror); 554} 555inherits(NullMirror, ValueMirror); 556 557 558NullMirror.prototype.toText = function() { 559 return 'null'; 560}; 561 562 563/** 564 * Mirror object for boolean values. 565 * @param {boolean} value The boolean value reflected by this mirror 566 * @constructor 567 * @extends ValueMirror 568 */ 569function BooleanMirror(value) { 570 %_CallFunction(this, BOOLEAN_TYPE, value, ValueMirror); 571} 572inherits(BooleanMirror, ValueMirror); 573 574 575BooleanMirror.prototype.toText = function() { 576 return this.value_ ? 'true' : 'false'; 577}; 578 579 580/** 581 * Mirror object for number values. 582 * @param {number} value The number value reflected by this mirror 583 * @constructor 584 * @extends ValueMirror 585 */ 586function NumberMirror(value) { 587 %_CallFunction(this, NUMBER_TYPE, value, ValueMirror); 588} 589inherits(NumberMirror, ValueMirror); 590 591 592NumberMirror.prototype.toText = function() { 593 return %_NumberToString(this.value_); 594}; 595 596 597/** 598 * Mirror object for string values. 599 * @param {string} value The string value reflected by this mirror 600 * @constructor 601 * @extends ValueMirror 602 */ 603function StringMirror(value) { 604 %_CallFunction(this, STRING_TYPE, value, ValueMirror); 605} 606inherits(StringMirror, ValueMirror); 607 608 609StringMirror.prototype.length = function() { 610 return this.value_.length; 611}; 612 613StringMirror.prototype.getTruncatedValue = function(maxLength) { 614 if (maxLength != -1 && this.length() > maxLength) { 615 return this.value_.substring(0, maxLength) + 616 '... (length: ' + this.length() + ')'; 617 } 618 return this.value_; 619}; 620 621StringMirror.prototype.toText = function() { 622 return this.getTruncatedValue(kMaxProtocolStringLength); 623}; 624 625 626/** 627 * Mirror object for a Symbol 628 * @param {Object} value The Symbol 629 * @constructor 630 * @extends Mirror 631 */ 632function SymbolMirror(value) { 633 %_CallFunction(this, SYMBOL_TYPE, value, ValueMirror); 634} 635inherits(SymbolMirror, ValueMirror); 636 637 638SymbolMirror.prototype.description = function() { 639 return %SymbolDescription(%_ValueOf(this.value_)); 640} 641 642 643SymbolMirror.prototype.toText = function() { 644 return %_CallFunction(this.value_, builtins.SymbolToString); 645} 646 647 648/** 649 * Mirror object for objects. 650 * @param {object} value The object reflected by this mirror 651 * @param {boolean} transient indicate whether this object is transient with a 652 * transient handle 653 * @constructor 654 * @extends ValueMirror 655 */ 656function ObjectMirror(value, type, transient) { 657 %_CallFunction(this, type || OBJECT_TYPE, value, transient, ValueMirror); 658} 659inherits(ObjectMirror, ValueMirror); 660 661 662ObjectMirror.prototype.className = function() { 663 return %_ClassOf(this.value_); 664}; 665 666 667ObjectMirror.prototype.constructorFunction = function() { 668 return MakeMirror(%DebugGetProperty(this.value_, 'constructor')); 669}; 670 671 672ObjectMirror.prototype.prototypeObject = function() { 673 return MakeMirror(%DebugGetProperty(this.value_, 'prototype')); 674}; 675 676 677ObjectMirror.prototype.protoObject = function() { 678 return MakeMirror(%DebugGetPrototype(this.value_)); 679}; 680 681 682ObjectMirror.prototype.hasNamedInterceptor = function() { 683 // Get information on interceptors for this object. 684 var x = %GetInterceptorInfo(this.value_); 685 return (x & 2) != 0; 686}; 687 688 689ObjectMirror.prototype.hasIndexedInterceptor = function() { 690 // Get information on interceptors for this object. 691 var x = %GetInterceptorInfo(this.value_); 692 return (x & 1) != 0; 693}; 694 695 696// Get all own property names except for private symbols. 697function TryGetPropertyNames(object) { 698 try { 699 // TODO(yangguo): Should there be a special debugger implementation of 700 // %GetOwnPropertyNames that doesn't perform access checks? 701 return %GetOwnPropertyNames(object, PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL); 702 } catch (e) { 703 // Might have hit a failed access check. 704 return []; 705 } 706} 707 708 709/** 710 * Return the property names for this object. 711 * @param {number} kind Indicate whether named, indexed or both kinds of 712 * properties are requested 713 * @param {number} limit Limit the number of names returend to the specified 714 value 715 * @return {Array} Property names for this object 716 */ 717ObjectMirror.prototype.propertyNames = function(kind, limit) { 718 // Find kind and limit and allocate array for the result 719 kind = kind || PropertyKind.Named | PropertyKind.Indexed; 720 721 var propertyNames; 722 var elementNames; 723 var total = 0; 724 725 // Find all the named properties. 726 if (kind & PropertyKind.Named) { 727 propertyNames = TryGetPropertyNames(this.value_); 728 total += propertyNames.length; 729 730 // Get names for named interceptor properties if any. 731 if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) { 732 var namedInterceptorNames = 733 %GetNamedInterceptorPropertyNames(this.value_); 734 if (namedInterceptorNames) { 735 propertyNames = propertyNames.concat(namedInterceptorNames); 736 total += namedInterceptorNames.length; 737 } 738 } 739 } 740 741 // Find all the indexed properties. 742 if (kind & PropertyKind.Indexed) { 743 // Get own element names. 744 elementNames = %GetOwnElementNames(this.value_); 745 total += elementNames.length; 746 747 // Get names for indexed interceptor properties. 748 if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) { 749 var indexedInterceptorNames = 750 %GetIndexedInterceptorElementNames(this.value_); 751 if (indexedInterceptorNames) { 752 elementNames = elementNames.concat(indexedInterceptorNames); 753 total += indexedInterceptorNames.length; 754 } 755 } 756 } 757 limit = Math.min(limit || total, total); 758 759 var names = new Array(limit); 760 var index = 0; 761 762 // Copy names for named properties. 763 if (kind & PropertyKind.Named) { 764 for (var i = 0; index < limit && i < propertyNames.length; i++) { 765 names[index++] = propertyNames[i]; 766 } 767 } 768 769 // Copy names for indexed properties. 770 if (kind & PropertyKind.Indexed) { 771 for (var i = 0; index < limit && i < elementNames.length; i++) { 772 names[index++] = elementNames[i]; 773 } 774 } 775 776 return names; 777}; 778 779 780/** 781 * Return the properties for this object as an array of PropertyMirror objects. 782 * @param {number} kind Indicate whether named, indexed or both kinds of 783 * properties are requested 784 * @param {number} limit Limit the number of properties returned to the 785 specified value 786 * @return {Array} Property mirrors for this object 787 */ 788ObjectMirror.prototype.properties = function(kind, limit) { 789 var names = this.propertyNames(kind, limit); 790 var properties = new Array(names.length); 791 for (var i = 0; i < names.length; i++) { 792 properties[i] = this.property(names[i]); 793 } 794 795 return properties; 796}; 797 798 799/** 800 * Return the internal properties for this object as an array of 801 * InternalPropertyMirror objects. 802 * @return {Array} Property mirrors for this object 803 */ 804ObjectMirror.prototype.internalProperties = function() { 805 return ObjectMirror.GetInternalProperties(this.value_); 806} 807 808 809ObjectMirror.prototype.property = function(name) { 810 var details = %DebugGetPropertyDetails(this.value_, %ToName(name)); 811 if (details) { 812 return new PropertyMirror(this, name, details); 813 } 814 815 // Nothing found. 816 return GetUndefinedMirror(); 817}; 818 819 820 821/** 822 * Try to find a property from its value. 823 * @param {Mirror} value The property value to look for 824 * @return {PropertyMirror} The property with the specified value. If no 825 * property was found with the specified value UndefinedMirror is returned 826 */ 827ObjectMirror.prototype.lookupProperty = function(value) { 828 var properties = this.properties(); 829 830 // Look for property value in properties. 831 for (var i = 0; i < properties.length; i++) { 832 833 // Skip properties which are defined through assessors. 834 var property = properties[i]; 835 if (property.propertyType() != PropertyType.Callbacks) { 836 if (%_ObjectEquals(property.value_, value.value_)) { 837 return property; 838 } 839 } 840 } 841 842 // Nothing found. 843 return GetUndefinedMirror(); 844}; 845 846 847/** 848 * Returns objects which has direct references to this object 849 * @param {number} opt_max_objects Optional parameter specifying the maximum 850 * number of referencing objects to return. 851 * @return {Array} The objects which has direct references to this object. 852 */ 853ObjectMirror.prototype.referencedBy = function(opt_max_objects) { 854 // Find all objects with direct references to this object. 855 var result = %DebugReferencedBy(this.value_, 856 Mirror.prototype, opt_max_objects || 0); 857 858 // Make mirrors for all the references found. 859 for (var i = 0; i < result.length; i++) { 860 result[i] = MakeMirror(result[i]); 861 } 862 863 return result; 864}; 865 866 867ObjectMirror.prototype.toText = function() { 868 var name; 869 var ctor = this.constructorFunction(); 870 if (!ctor.isFunction()) { 871 name = this.className(); 872 } else { 873 name = ctor.name(); 874 if (!name) { 875 name = this.className(); 876 } 877 } 878 return '#<' + name + '>'; 879}; 880 881 882/** 883 * Return the internal properties of the value, such as [[PrimitiveValue]] of 884 * scalar wrapper objects, properties of the bound function and properties of 885 * the promise. 886 * This method is done static to be accessible from Debug API with the bare 887 * values without mirrors. 888 * @return {Array} array (possibly empty) of InternalProperty instances 889 */ 890ObjectMirror.GetInternalProperties = function(value) { 891 if (IS_STRING_WRAPPER(value) || IS_NUMBER_WRAPPER(value) || 892 IS_BOOLEAN_WRAPPER(value)) { 893 var primitiveValue = %_ValueOf(value); 894 return [new InternalPropertyMirror("[[PrimitiveValue]]", primitiveValue)]; 895 } else if (IS_FUNCTION(value)) { 896 var bindings = %BoundFunctionGetBindings(value); 897 var result = []; 898 if (bindings && IS_ARRAY(bindings)) { 899 result.push(new InternalPropertyMirror("[[TargetFunction]]", 900 bindings[0])); 901 result.push(new InternalPropertyMirror("[[BoundThis]]", bindings[1])); 902 var boundArgs = []; 903 for (var i = 2; i < bindings.length; i++) { 904 boundArgs.push(bindings[i]); 905 } 906 result.push(new InternalPropertyMirror("[[BoundArgs]]", boundArgs)); 907 } 908 return result; 909 } else if (ObjectIsPromise(value)) { 910 var result = []; 911 result.push(new InternalPropertyMirror("[[PromiseStatus]]", 912 PromiseGetStatus_(value))); 913 result.push(new InternalPropertyMirror("[[PromiseValue]]", 914 PromiseGetValue_(value))); 915 return result; 916 } 917 return []; 918} 919 920 921/** 922 * Mirror object for functions. 923 * @param {function} value The function object reflected by this mirror. 924 * @constructor 925 * @extends ObjectMirror 926 */ 927function FunctionMirror(value) { 928 %_CallFunction(this, value, FUNCTION_TYPE, ObjectMirror); 929 this.resolved_ = true; 930} 931inherits(FunctionMirror, ObjectMirror); 932 933 934/** 935 * Returns whether the function is resolved. 936 * @return {boolean} True if the function is resolved. Unresolved functions can 937 * only originate as functions from stack frames 938 */ 939FunctionMirror.prototype.resolved = function() { 940 return this.resolved_; 941}; 942 943 944/** 945 * Returns the name of the function. 946 * @return {string} Name of the function 947 */ 948FunctionMirror.prototype.name = function() { 949 return %FunctionGetName(this.value_); 950}; 951 952 953/** 954 * Returns the inferred name of the function. 955 * @return {string} Name of the function 956 */ 957FunctionMirror.prototype.inferredName = function() { 958 return %FunctionGetInferredName(this.value_); 959}; 960 961 962/** 963 * Returns the source code for the function. 964 * @return {string or undefined} The source code for the function. If the 965 * function is not resolved undefined will be returned. 966 */ 967FunctionMirror.prototype.source = function() { 968 // Return source if function is resolved. Otherwise just fall through to 969 // return undefined. 970 if (this.resolved()) { 971 return builtins.FunctionSourceString(this.value_); 972 } 973}; 974 975 976/** 977 * Returns the script object for the function. 978 * @return {ScriptMirror or undefined} Script object for the function or 979 * undefined if the function has no script 980 */ 981FunctionMirror.prototype.script = function() { 982 // Return script if function is resolved. Otherwise just fall through 983 // to return undefined. 984 if (this.resolved()) { 985 if (this.script_) { 986 return this.script_; 987 } 988 var script = %FunctionGetScript(this.value_); 989 if (script) { 990 return this.script_ = MakeMirror(script); 991 } 992 } 993}; 994 995 996/** 997 * Returns the script source position for the function. Only makes sense 998 * for functions which has a script defined. 999 * @return {Number or undefined} in-script position for the function 1000 */ 1001FunctionMirror.prototype.sourcePosition_ = function() { 1002 // Return position if function is resolved. Otherwise just fall 1003 // through to return undefined. 1004 if (this.resolved()) { 1005 return %FunctionGetScriptSourcePosition(this.value_); 1006 } 1007}; 1008 1009 1010/** 1011 * Returns the script source location object for the function. Only makes sense 1012 * for functions which has a script defined. 1013 * @return {Location or undefined} in-script location for the function begin 1014 */ 1015FunctionMirror.prototype.sourceLocation = function() { 1016 if (this.resolved()) { 1017 var script = this.script(); 1018 if (script) { 1019 return script.locationFromPosition(this.sourcePosition_(), true); 1020 } 1021 } 1022}; 1023 1024 1025/** 1026 * Returns objects constructed by this function. 1027 * @param {number} opt_max_instances Optional parameter specifying the maximum 1028 * number of instances to return. 1029 * @return {Array or undefined} The objects constructed by this function. 1030 */ 1031FunctionMirror.prototype.constructedBy = function(opt_max_instances) { 1032 if (this.resolved()) { 1033 // Find all objects constructed from this function. 1034 var result = %DebugConstructedBy(this.value_, opt_max_instances || 0); 1035 1036 // Make mirrors for all the instances found. 1037 for (var i = 0; i < result.length; i++) { 1038 result[i] = MakeMirror(result[i]); 1039 } 1040 1041 return result; 1042 } else { 1043 return []; 1044 } 1045}; 1046 1047 1048FunctionMirror.prototype.scopeCount = function() { 1049 if (this.resolved()) { 1050 if (IS_UNDEFINED(this.scopeCount_)) { 1051 this.scopeCount_ = %GetFunctionScopeCount(this.value()); 1052 } 1053 return this.scopeCount_; 1054 } else { 1055 return 0; 1056 } 1057}; 1058 1059 1060FunctionMirror.prototype.scope = function(index) { 1061 if (this.resolved()) { 1062 return new ScopeMirror(UNDEFINED, this, index); 1063 } 1064}; 1065 1066 1067FunctionMirror.prototype.toText = function() { 1068 return this.source(); 1069}; 1070 1071 1072/** 1073 * Mirror object for unresolved functions. 1074 * @param {string} value The name for the unresolved function reflected by this 1075 * mirror. 1076 * @constructor 1077 * @extends ObjectMirror 1078 */ 1079function UnresolvedFunctionMirror(value) { 1080 // Construct this using the ValueMirror as an unresolved function is not a 1081 // real object but just a string. 1082 %_CallFunction(this, FUNCTION_TYPE, value, ValueMirror); 1083 this.propertyCount_ = 0; 1084 this.elementCount_ = 0; 1085 this.resolved_ = false; 1086} 1087inherits(UnresolvedFunctionMirror, FunctionMirror); 1088 1089 1090UnresolvedFunctionMirror.prototype.className = function() { 1091 return 'Function'; 1092}; 1093 1094 1095UnresolvedFunctionMirror.prototype.constructorFunction = function() { 1096 return GetUndefinedMirror(); 1097}; 1098 1099 1100UnresolvedFunctionMirror.prototype.prototypeObject = function() { 1101 return GetUndefinedMirror(); 1102}; 1103 1104 1105UnresolvedFunctionMirror.prototype.protoObject = function() { 1106 return GetUndefinedMirror(); 1107}; 1108 1109 1110UnresolvedFunctionMirror.prototype.name = function() { 1111 return this.value_; 1112}; 1113 1114 1115UnresolvedFunctionMirror.prototype.inferredName = function() { 1116 return undefined; 1117}; 1118 1119 1120UnresolvedFunctionMirror.prototype.propertyNames = function(kind, limit) { 1121 return []; 1122}; 1123 1124 1125/** 1126 * Mirror object for arrays. 1127 * @param {Array} value The Array object reflected by this mirror 1128 * @constructor 1129 * @extends ObjectMirror 1130 */ 1131function ArrayMirror(value) { 1132 %_CallFunction(this, value, ObjectMirror); 1133} 1134inherits(ArrayMirror, ObjectMirror); 1135 1136 1137ArrayMirror.prototype.length = function() { 1138 return this.value_.length; 1139}; 1140 1141 1142ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, 1143 opt_to_index) { 1144 var from_index = opt_from_index || 0; 1145 var to_index = opt_to_index || this.length() - 1; 1146 if (from_index > to_index) return new Array(); 1147 var values = new Array(to_index - from_index + 1); 1148 for (var i = from_index; i <= to_index; i++) { 1149 var details = %DebugGetPropertyDetails(this.value_, %ToString(i)); 1150 var value; 1151 if (details) { 1152 value = new PropertyMirror(this, i, details); 1153 } else { 1154 value = GetUndefinedMirror(); 1155 } 1156 values[i - from_index] = value; 1157 } 1158 return values; 1159}; 1160 1161 1162/** 1163 * Mirror object for dates. 1164 * @param {Date} value The Date object reflected by this mirror 1165 * @constructor 1166 * @extends ObjectMirror 1167 */ 1168function DateMirror(value) { 1169 %_CallFunction(this, value, ObjectMirror); 1170} 1171inherits(DateMirror, ObjectMirror); 1172 1173 1174DateMirror.prototype.toText = function() { 1175 var s = JSON.stringify(this.value_); 1176 return s.substring(1, s.length - 1); // cut quotes 1177}; 1178 1179 1180/** 1181 * Mirror object for regular expressions. 1182 * @param {RegExp} value The RegExp object reflected by this mirror 1183 * @constructor 1184 * @extends ObjectMirror 1185 */ 1186function RegExpMirror(value) { 1187 %_CallFunction(this, value, REGEXP_TYPE, ObjectMirror); 1188} 1189inherits(RegExpMirror, ObjectMirror); 1190 1191 1192/** 1193 * Returns the source to the regular expression. 1194 * @return {string or undefined} The source to the regular expression 1195 */ 1196RegExpMirror.prototype.source = function() { 1197 return this.value_.source; 1198}; 1199 1200 1201/** 1202 * Returns whether this regular expression has the global (g) flag set. 1203 * @return {boolean} Value of the global flag 1204 */ 1205RegExpMirror.prototype.global = function() { 1206 return this.value_.global; 1207}; 1208 1209 1210/** 1211 * Returns whether this regular expression has the ignore case (i) flag set. 1212 * @return {boolean} Value of the ignore case flag 1213 */ 1214RegExpMirror.prototype.ignoreCase = function() { 1215 return this.value_.ignoreCase; 1216}; 1217 1218 1219/** 1220 * Returns whether this regular expression has the multiline (m) flag set. 1221 * @return {boolean} Value of the multiline flag 1222 */ 1223RegExpMirror.prototype.multiline = function() { 1224 return this.value_.multiline; 1225}; 1226 1227 1228RegExpMirror.prototype.toText = function() { 1229 // Simpel to text which is used when on specialization in subclass. 1230 return "/" + this.source() + "/"; 1231}; 1232 1233 1234/** 1235 * Mirror object for error objects. 1236 * @param {Error} value The error object reflected by this mirror 1237 * @constructor 1238 * @extends ObjectMirror 1239 */ 1240function ErrorMirror(value) { 1241 %_CallFunction(this, value, ERROR_TYPE, ObjectMirror); 1242} 1243inherits(ErrorMirror, ObjectMirror); 1244 1245 1246/** 1247 * Returns the message for this eror object. 1248 * @return {string or undefined} The message for this eror object 1249 */ 1250ErrorMirror.prototype.message = function() { 1251 return this.value_.message; 1252}; 1253 1254 1255ErrorMirror.prototype.toText = function() { 1256 // Use the same text representation as in messages.js. 1257 var text; 1258 try { 1259 str = %_CallFunction(this.value_, builtins.ErrorToString); 1260 } catch (e) { 1261 str = '#<Error>'; 1262 } 1263 return str; 1264}; 1265 1266 1267/** 1268 * Mirror object for a Promise object. 1269 * @param {Object} value The Promise object 1270 * @constructor 1271 * @extends ObjectMirror 1272 */ 1273function PromiseMirror(value) { 1274 %_CallFunction(this, value, PROMISE_TYPE, ObjectMirror); 1275} 1276inherits(PromiseMirror, ObjectMirror); 1277 1278 1279function PromiseGetStatus_(value) { 1280 var status = %DebugGetProperty(value, builtins.promiseStatus); 1281 if (status == 0) return "pending"; 1282 if (status == 1) return "resolved"; 1283 return "rejected"; 1284} 1285 1286 1287function PromiseGetValue_(value) { 1288 return %DebugGetProperty(value, builtins.promiseValue); 1289} 1290 1291 1292PromiseMirror.prototype.status = function() { 1293 return PromiseGetStatus_(this.value_); 1294}; 1295 1296 1297PromiseMirror.prototype.promiseValue = function() { 1298 return MakeMirror(PromiseGetValue_(this.value_)); 1299}; 1300 1301 1302function MapMirror(value) { 1303 %_CallFunction(this, value, MAP_TYPE, ObjectMirror); 1304} 1305inherits(MapMirror, ObjectMirror); 1306 1307 1308/** 1309 * Returns an array of key/value pairs of a map. 1310 * This will keep keys alive for WeakMaps. 1311 * 1312 * @returns {Array.<Object>} Array of key/value pairs of a map. 1313 */ 1314MapMirror.prototype.entries = function() { 1315 var result = []; 1316 1317 if (IS_WEAKMAP(this.value_)) { 1318 var entries = %GetWeakMapEntries(this.value_); 1319 for (var i = 0; i < entries.length; i += 2) { 1320 result.push({ 1321 key: entries[i], 1322 value: entries[i + 1] 1323 }); 1324 } 1325 return result; 1326 } 1327 1328 var iter = %_CallFunction(this.value_, builtins.MapEntries); 1329 var next; 1330 while (!(next = iter.next()).done) { 1331 result.push({ 1332 key: next.value[0], 1333 value: next.value[1] 1334 }); 1335 } 1336 return result; 1337}; 1338 1339 1340function SetMirror(value) { 1341 %_CallFunction(this, value, SET_TYPE, ObjectMirror); 1342} 1343inherits(SetMirror, ObjectMirror); 1344 1345 1346/** 1347 * Returns an array of elements of a set. 1348 * This will keep elements alive for WeakSets. 1349 * 1350 * @returns {Array.<Object>} Array of elements of a set. 1351 */ 1352SetMirror.prototype.values = function() { 1353 if (IS_WEAKSET(this.value_)) { 1354 return %GetWeakSetValues(this.value_); 1355 } 1356 1357 var result = []; 1358 var iter = %_CallFunction(this.value_, builtins.SetValues); 1359 var next; 1360 while (!(next = iter.next()).done) { 1361 result.push(next.value); 1362 } 1363 return result; 1364}; 1365 1366 1367/** 1368 * Mirror object for a Generator object. 1369 * @param {Object} data The Generator object 1370 * @constructor 1371 * @extends Mirror 1372 */ 1373function GeneratorMirror(value) { 1374 %_CallFunction(this, value, GENERATOR_TYPE, ObjectMirror); 1375} 1376inherits(GeneratorMirror, ObjectMirror); 1377 1378 1379GeneratorMirror.prototype.status = function() { 1380 var continuation = %GeneratorGetContinuation(this.value_); 1381 if (continuation < 0) return "running"; 1382 if (continuation == 0) return "closed"; 1383 return "suspended"; 1384}; 1385 1386 1387GeneratorMirror.prototype.sourcePosition_ = function() { 1388 return %GeneratorGetSourcePosition(this.value_); 1389}; 1390 1391 1392GeneratorMirror.prototype.sourceLocation = function() { 1393 var pos = this.sourcePosition_(); 1394 if (!IS_UNDEFINED(pos)) { 1395 var script = this.func().script(); 1396 if (script) { 1397 return script.locationFromPosition(pos, true); 1398 } 1399 } 1400}; 1401 1402 1403GeneratorMirror.prototype.func = function() { 1404 if (!this.func_) { 1405 this.func_ = MakeMirror(%GeneratorGetFunction(this.value_)); 1406 } 1407 return this.func_; 1408}; 1409 1410 1411GeneratorMirror.prototype.context = function() { 1412 if (!this.context_) { 1413 this.context_ = new ContextMirror(%GeneratorGetContext(this.value_)); 1414 } 1415 return this.context_; 1416}; 1417 1418 1419GeneratorMirror.prototype.receiver = function() { 1420 if (!this.receiver_) { 1421 this.receiver_ = MakeMirror(%GeneratorGetReceiver(this.value_)); 1422 } 1423 return this.receiver_; 1424}; 1425 1426 1427/** 1428 * Base mirror object for properties. 1429 * @param {ObjectMirror} mirror The mirror object having this property 1430 * @param {string} name The name of the property 1431 * @param {Array} details Details about the property 1432 * @constructor 1433 * @extends Mirror 1434 */ 1435function PropertyMirror(mirror, name, details) { 1436 %_CallFunction(this, PROPERTY_TYPE, Mirror); 1437 this.mirror_ = mirror; 1438 this.name_ = name; 1439 this.value_ = details[0]; 1440 this.details_ = details[1]; 1441 this.is_interceptor_ = details[2]; 1442 if (details.length > 3) { 1443 this.exception_ = details[3]; 1444 this.getter_ = details[4]; 1445 this.setter_ = details[5]; 1446 } 1447} 1448inherits(PropertyMirror, Mirror); 1449 1450 1451PropertyMirror.prototype.isReadOnly = function() { 1452 return (this.attributes() & PropertyAttribute.ReadOnly) != 0; 1453}; 1454 1455 1456PropertyMirror.prototype.isEnum = function() { 1457 return (this.attributes() & PropertyAttribute.DontEnum) == 0; 1458}; 1459 1460 1461PropertyMirror.prototype.canDelete = function() { 1462 return (this.attributes() & PropertyAttribute.DontDelete) == 0; 1463}; 1464 1465 1466PropertyMirror.prototype.name = function() { 1467 return this.name_; 1468}; 1469 1470 1471PropertyMirror.prototype.isIndexed = function() { 1472 for (var i = 0; i < this.name_.length; i++) { 1473 if (this.name_[i] < '0' || '9' < this.name_[i]) { 1474 return false; 1475 } 1476 } 1477 return true; 1478}; 1479 1480 1481PropertyMirror.prototype.value = function() { 1482 return MakeMirror(this.value_, false); 1483}; 1484 1485 1486/** 1487 * Returns whether this property value is an exception. 1488 * @return {booolean} True if this property value is an exception 1489 */ 1490PropertyMirror.prototype.isException = function() { 1491 return this.exception_ ? true : false; 1492}; 1493 1494 1495PropertyMirror.prototype.attributes = function() { 1496 return %DebugPropertyAttributesFromDetails(this.details_); 1497}; 1498 1499 1500PropertyMirror.prototype.propertyType = function() { 1501 return %DebugPropertyTypeFromDetails(this.details_); 1502}; 1503 1504 1505PropertyMirror.prototype.insertionIndex = function() { 1506 return %DebugPropertyIndexFromDetails(this.details_); 1507}; 1508 1509 1510/** 1511 * Returns whether this property has a getter defined through __defineGetter__. 1512 * @return {booolean} True if this property has a getter 1513 */ 1514PropertyMirror.prototype.hasGetter = function() { 1515 return this.getter_ ? true : false; 1516}; 1517 1518 1519/** 1520 * Returns whether this property has a setter defined through __defineSetter__. 1521 * @return {booolean} True if this property has a setter 1522 */ 1523PropertyMirror.prototype.hasSetter = function() { 1524 return this.setter_ ? true : false; 1525}; 1526 1527 1528/** 1529 * Returns the getter for this property defined through __defineGetter__. 1530 * @return {Mirror} FunctionMirror reflecting the getter function or 1531 * UndefinedMirror if there is no getter for this property 1532 */ 1533PropertyMirror.prototype.getter = function() { 1534 if (this.hasGetter()) { 1535 return MakeMirror(this.getter_); 1536 } else { 1537 return GetUndefinedMirror(); 1538 } 1539}; 1540 1541 1542/** 1543 * Returns the setter for this property defined through __defineSetter__. 1544 * @return {Mirror} FunctionMirror reflecting the setter function or 1545 * UndefinedMirror if there is no setter for this property 1546 */ 1547PropertyMirror.prototype.setter = function() { 1548 if (this.hasSetter()) { 1549 return MakeMirror(this.setter_); 1550 } else { 1551 return GetUndefinedMirror(); 1552 } 1553}; 1554 1555 1556/** 1557 * Returns whether this property is natively implemented by the host or a set 1558 * through JavaScript code. 1559 * @return {boolean} True if the property is 1560 * UndefinedMirror if there is no setter for this property 1561 */ 1562PropertyMirror.prototype.isNative = function() { 1563 return this.is_interceptor_ || 1564 ((this.propertyType() == PropertyType.Callbacks) && 1565 !this.hasGetter() && !this.hasSetter()); 1566}; 1567 1568 1569/** 1570 * Mirror object for internal properties. Internal property reflects properties 1571 * not accessible from user code such as [[BoundThis]] in bound function. 1572 * Their names are merely symbolic. 1573 * @param {string} name The name of the property 1574 * @param {value} property value 1575 * @constructor 1576 * @extends Mirror 1577 */ 1578function InternalPropertyMirror(name, value) { 1579 %_CallFunction(this, INTERNAL_PROPERTY_TYPE, Mirror); 1580 this.name_ = name; 1581 this.value_ = value; 1582} 1583inherits(InternalPropertyMirror, Mirror); 1584 1585 1586InternalPropertyMirror.prototype.name = function() { 1587 return this.name_; 1588}; 1589 1590 1591InternalPropertyMirror.prototype.value = function() { 1592 return MakeMirror(this.value_, false); 1593}; 1594 1595 1596var kFrameDetailsFrameIdIndex = 0; 1597var kFrameDetailsReceiverIndex = 1; 1598var kFrameDetailsFunctionIndex = 2; 1599var kFrameDetailsArgumentCountIndex = 3; 1600var kFrameDetailsLocalCountIndex = 4; 1601var kFrameDetailsSourcePositionIndex = 5; 1602var kFrameDetailsConstructCallIndex = 6; 1603var kFrameDetailsAtReturnIndex = 7; 1604var kFrameDetailsFlagsIndex = 8; 1605var kFrameDetailsFirstDynamicIndex = 9; 1606 1607var kFrameDetailsNameIndex = 0; 1608var kFrameDetailsValueIndex = 1; 1609var kFrameDetailsNameValueSize = 2; 1610 1611var kFrameDetailsFlagDebuggerFrameMask = 1 << 0; 1612var kFrameDetailsFlagOptimizedFrameMask = 1 << 1; 1613var kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2; 1614 1615/** 1616 * Wrapper for the frame details information retreived from the VM. The frame 1617 * details from the VM is an array with the following content. See runtime.cc 1618 * Runtime_GetFrameDetails. 1619 * 0: Id 1620 * 1: Receiver 1621 * 2: Function 1622 * 3: Argument count 1623 * 4: Local count 1624 * 5: Source position 1625 * 6: Construct call 1626 * 7: Is at return 1627 * 8: Flags (debugger frame, optimized frame, inlined frame index) 1628 * Arguments name, value 1629 * Locals name, value 1630 * Return value if any 1631 * @param {number} break_id Current break id 1632 * @param {number} index Frame number 1633 * @constructor 1634 */ 1635function FrameDetails(break_id, index) { 1636 this.break_id_ = break_id; 1637 this.details_ = %GetFrameDetails(break_id, index); 1638} 1639 1640 1641FrameDetails.prototype.frameId = function() { 1642 %CheckExecutionState(this.break_id_); 1643 return this.details_[kFrameDetailsFrameIdIndex]; 1644}; 1645 1646 1647FrameDetails.prototype.receiver = function() { 1648 %CheckExecutionState(this.break_id_); 1649 return this.details_[kFrameDetailsReceiverIndex]; 1650}; 1651 1652 1653FrameDetails.prototype.func = function() { 1654 %CheckExecutionState(this.break_id_); 1655 return this.details_[kFrameDetailsFunctionIndex]; 1656}; 1657 1658 1659FrameDetails.prototype.isConstructCall = function() { 1660 %CheckExecutionState(this.break_id_); 1661 return this.details_[kFrameDetailsConstructCallIndex]; 1662}; 1663 1664 1665FrameDetails.prototype.isAtReturn = function() { 1666 %CheckExecutionState(this.break_id_); 1667 return this.details_[kFrameDetailsAtReturnIndex]; 1668}; 1669 1670 1671FrameDetails.prototype.isDebuggerFrame = function() { 1672 %CheckExecutionState(this.break_id_); 1673 var f = kFrameDetailsFlagDebuggerFrameMask; 1674 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1675}; 1676 1677 1678FrameDetails.prototype.isOptimizedFrame = function() { 1679 %CheckExecutionState(this.break_id_); 1680 var f = kFrameDetailsFlagOptimizedFrameMask; 1681 return (this.details_[kFrameDetailsFlagsIndex] & f) == f; 1682}; 1683 1684 1685FrameDetails.prototype.isInlinedFrame = function() { 1686 return this.inlinedFrameIndex() > 0; 1687}; 1688 1689 1690FrameDetails.prototype.inlinedFrameIndex = function() { 1691 %CheckExecutionState(this.break_id_); 1692 var f = kFrameDetailsFlagInlinedFrameIndexMask; 1693 return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2; 1694}; 1695 1696 1697FrameDetails.prototype.argumentCount = function() { 1698 %CheckExecutionState(this.break_id_); 1699 return this.details_[kFrameDetailsArgumentCountIndex]; 1700}; 1701 1702 1703FrameDetails.prototype.argumentName = function(index) { 1704 %CheckExecutionState(this.break_id_); 1705 if (index >= 0 && index < this.argumentCount()) { 1706 return this.details_[kFrameDetailsFirstDynamicIndex + 1707 index * kFrameDetailsNameValueSize + 1708 kFrameDetailsNameIndex]; 1709 } 1710}; 1711 1712 1713FrameDetails.prototype.argumentValue = function(index) { 1714 %CheckExecutionState(this.break_id_); 1715 if (index >= 0 && index < this.argumentCount()) { 1716 return this.details_[kFrameDetailsFirstDynamicIndex + 1717 index * kFrameDetailsNameValueSize + 1718 kFrameDetailsValueIndex]; 1719 } 1720}; 1721 1722 1723FrameDetails.prototype.localCount = function() { 1724 %CheckExecutionState(this.break_id_); 1725 return this.details_[kFrameDetailsLocalCountIndex]; 1726}; 1727 1728 1729FrameDetails.prototype.sourcePosition = function() { 1730 %CheckExecutionState(this.break_id_); 1731 return this.details_[kFrameDetailsSourcePositionIndex]; 1732}; 1733 1734 1735FrameDetails.prototype.localName = function(index) { 1736 %CheckExecutionState(this.break_id_); 1737 if (index >= 0 && index < this.localCount()) { 1738 var locals_offset = kFrameDetailsFirstDynamicIndex + 1739 this.argumentCount() * kFrameDetailsNameValueSize; 1740 return this.details_[locals_offset + 1741 index * kFrameDetailsNameValueSize + 1742 kFrameDetailsNameIndex]; 1743 } 1744}; 1745 1746 1747FrameDetails.prototype.localValue = function(index) { 1748 %CheckExecutionState(this.break_id_); 1749 if (index >= 0 && index < this.localCount()) { 1750 var locals_offset = kFrameDetailsFirstDynamicIndex + 1751 this.argumentCount() * kFrameDetailsNameValueSize; 1752 return this.details_[locals_offset + 1753 index * kFrameDetailsNameValueSize + 1754 kFrameDetailsValueIndex]; 1755 } 1756}; 1757 1758 1759FrameDetails.prototype.returnValue = function() { 1760 %CheckExecutionState(this.break_id_); 1761 var return_value_offset = 1762 kFrameDetailsFirstDynamicIndex + 1763 (this.argumentCount() + this.localCount()) * kFrameDetailsNameValueSize; 1764 if (this.details_[kFrameDetailsAtReturnIndex]) { 1765 return this.details_[return_value_offset]; 1766 } 1767}; 1768 1769 1770FrameDetails.prototype.scopeCount = function() { 1771 if (IS_UNDEFINED(this.scopeCount_)) { 1772 this.scopeCount_ = %GetScopeCount(this.break_id_, this.frameId()); 1773 } 1774 return this.scopeCount_; 1775}; 1776 1777 1778FrameDetails.prototype.stepInPositionsImpl = function() { 1779 return %GetStepInPositions(this.break_id_, this.frameId()); 1780}; 1781 1782 1783/** 1784 * Mirror object for stack frames. 1785 * @param {number} break_id The break id in the VM for which this frame is 1786 valid 1787 * @param {number} index The frame index (top frame is index 0) 1788 * @constructor 1789 * @extends Mirror 1790 */ 1791function FrameMirror(break_id, index) { 1792 %_CallFunction(this, FRAME_TYPE, Mirror); 1793 this.break_id_ = break_id; 1794 this.index_ = index; 1795 this.details_ = new FrameDetails(break_id, index); 1796} 1797inherits(FrameMirror, Mirror); 1798 1799 1800FrameMirror.prototype.details = function() { 1801 return this.details_; 1802}; 1803 1804 1805FrameMirror.prototype.index = function() { 1806 return this.index_; 1807}; 1808 1809 1810FrameMirror.prototype.func = function() { 1811 if (this.func_) { 1812 return this.func_; 1813 } 1814 1815 // Get the function for this frame from the VM. 1816 var f = this.details_.func(); 1817 1818 // Create a function mirror. NOTE: MakeMirror cannot be used here as the 1819 // value returned from the VM might be a string if the function for the 1820 // frame is unresolved. 1821 if (IS_FUNCTION(f)) { 1822 return this.func_ = MakeMirror(f); 1823 } else { 1824 return new UnresolvedFunctionMirror(f); 1825 } 1826}; 1827 1828 1829FrameMirror.prototype.receiver = function() { 1830 return MakeMirror(this.details_.receiver()); 1831}; 1832 1833 1834FrameMirror.prototype.isConstructCall = function() { 1835 return this.details_.isConstructCall(); 1836}; 1837 1838 1839FrameMirror.prototype.isAtReturn = function() { 1840 return this.details_.isAtReturn(); 1841}; 1842 1843 1844FrameMirror.prototype.isDebuggerFrame = function() { 1845 return this.details_.isDebuggerFrame(); 1846}; 1847 1848 1849FrameMirror.prototype.isOptimizedFrame = function() { 1850 return this.details_.isOptimizedFrame(); 1851}; 1852 1853 1854FrameMirror.prototype.isInlinedFrame = function() { 1855 return this.details_.isInlinedFrame(); 1856}; 1857 1858 1859FrameMirror.prototype.inlinedFrameIndex = function() { 1860 return this.details_.inlinedFrameIndex(); 1861}; 1862 1863 1864FrameMirror.prototype.argumentCount = function() { 1865 return this.details_.argumentCount(); 1866}; 1867 1868 1869FrameMirror.prototype.argumentName = function(index) { 1870 return this.details_.argumentName(index); 1871}; 1872 1873 1874FrameMirror.prototype.argumentValue = function(index) { 1875 return MakeMirror(this.details_.argumentValue(index)); 1876}; 1877 1878 1879FrameMirror.prototype.localCount = function() { 1880 return this.details_.localCount(); 1881}; 1882 1883 1884FrameMirror.prototype.localName = function(index) { 1885 return this.details_.localName(index); 1886}; 1887 1888 1889FrameMirror.prototype.localValue = function(index) { 1890 return MakeMirror(this.details_.localValue(index)); 1891}; 1892 1893 1894FrameMirror.prototype.returnValue = function() { 1895 return MakeMirror(this.details_.returnValue()); 1896}; 1897 1898 1899FrameMirror.prototype.sourcePosition = function() { 1900 return this.details_.sourcePosition(); 1901}; 1902 1903 1904FrameMirror.prototype.sourceLocation = function() { 1905 var func = this.func(); 1906 if (func.resolved()) { 1907 var script = func.script(); 1908 if (script) { 1909 return script.locationFromPosition(this.sourcePosition(), true); 1910 } 1911 } 1912}; 1913 1914 1915FrameMirror.prototype.sourceLine = function() { 1916 var location = this.sourceLocation(); 1917 if (location) { 1918 return location.line; 1919 } 1920}; 1921 1922 1923FrameMirror.prototype.sourceColumn = function() { 1924 var location = this.sourceLocation(); 1925 if (location) { 1926 return location.column; 1927 } 1928}; 1929 1930 1931FrameMirror.prototype.sourceLineText = function() { 1932 var location = this.sourceLocation(); 1933 if (location) { 1934 return location.sourceText(); 1935 } 1936}; 1937 1938 1939FrameMirror.prototype.scopeCount = function() { 1940 return this.details_.scopeCount(); 1941}; 1942 1943 1944FrameMirror.prototype.scope = function(index) { 1945 return new ScopeMirror(this, UNDEFINED, index); 1946}; 1947 1948 1949FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) { 1950 var scopeDetails = %GetAllScopesDetails(this.break_id_, 1951 this.details_.frameId(), 1952 this.details_.inlinedFrameIndex(), 1953 !!opt_ignore_nested_scopes); 1954 var result = []; 1955 for (var i = 0; i < scopeDetails.length; ++i) { 1956 result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i])); 1957 } 1958 return result; 1959}; 1960 1961 1962FrameMirror.prototype.stepInPositions = function() { 1963 var script = this.func().script(); 1964 var funcOffset = this.func().sourcePosition_(); 1965 1966 var stepInRaw = this.details_.stepInPositionsImpl(); 1967 var result = []; 1968 if (stepInRaw) { 1969 for (var i = 0; i < stepInRaw.length; i++) { 1970 var posStruct = {}; 1971 var offset = script.locationFromPosition(funcOffset + stepInRaw[i], 1972 true); 1973 serializeLocationFields(offset, posStruct); 1974 var item = { 1975 position: posStruct 1976 }; 1977 result.push(item); 1978 } 1979 } 1980 1981 return result; 1982}; 1983 1984 1985FrameMirror.prototype.evaluate = function(source, disable_break, 1986 opt_context_object) { 1987 return MakeMirror(%DebugEvaluate(this.break_id_, 1988 this.details_.frameId(), 1989 this.details_.inlinedFrameIndex(), 1990 source, 1991 Boolean(disable_break), 1992 opt_context_object)); 1993}; 1994 1995 1996FrameMirror.prototype.invocationText = function() { 1997 // Format frame invoaction (receiver, function and arguments). 1998 var result = ''; 1999 var func = this.func(); 2000 var receiver = this.receiver(); 2001 if (this.isConstructCall()) { 2002 // For constructor frames display new followed by the function name. 2003 result += 'new '; 2004 result += func.name() ? func.name() : '[anonymous]'; 2005 } else if (this.isDebuggerFrame()) { 2006 result += '[debugger]'; 2007 } else { 2008 // If the receiver has a className which is 'global' don't display it. 2009 var display_receiver = 2010 !receiver.className || (receiver.className() != 'global'); 2011 if (display_receiver) { 2012 result += receiver.toText(); 2013 } 2014 // Try to find the function as a property in the receiver. Include the 2015 // prototype chain in the lookup. 2016 var property = GetUndefinedMirror(); 2017 if (receiver.isObject()) { 2018 for (var r = receiver; 2019 !r.isNull() && property.isUndefined(); 2020 r = r.protoObject()) { 2021 property = r.lookupProperty(func); 2022 } 2023 } 2024 if (!property.isUndefined()) { 2025 // The function invoked was found on the receiver. Use the property name 2026 // for the backtrace. 2027 if (!property.isIndexed()) { 2028 if (display_receiver) { 2029 result += '.'; 2030 } 2031 result += property.name(); 2032 } else { 2033 result += '['; 2034 result += property.name(); 2035 result += ']'; 2036 } 2037 // Also known as - if the name in the function doesn't match the name 2038 // under which it was looked up. 2039 if (func.name() && func.name() != property.name()) { 2040 result += '(aka ' + func.name() + ')'; 2041 } 2042 } else { 2043 // The function invoked was not found on the receiver. Use the function 2044 // name if available for the backtrace. 2045 if (display_receiver) { 2046 result += '.'; 2047 } 2048 result += func.name() ? func.name() : '[anonymous]'; 2049 } 2050 } 2051 2052 // Render arguments for normal frames. 2053 if (!this.isDebuggerFrame()) { 2054 result += '('; 2055 for (var i = 0; i < this.argumentCount(); i++) { 2056 if (i != 0) result += ', '; 2057 if (this.argumentName(i)) { 2058 result += this.argumentName(i); 2059 result += '='; 2060 } 2061 result += this.argumentValue(i).toText(); 2062 } 2063 result += ')'; 2064 } 2065 2066 if (this.isAtReturn()) { 2067 result += ' returning '; 2068 result += this.returnValue().toText(); 2069 } 2070 2071 return result; 2072}; 2073 2074 2075FrameMirror.prototype.sourceAndPositionText = function() { 2076 // Format source and position. 2077 var result = ''; 2078 var func = this.func(); 2079 if (func.resolved()) { 2080 var script = func.script(); 2081 if (script) { 2082 if (script.name()) { 2083 result += script.name(); 2084 } else { 2085 result += '[unnamed]'; 2086 } 2087 if (!this.isDebuggerFrame()) { 2088 var location = this.sourceLocation(); 2089 result += ' line '; 2090 result += !IS_UNDEFINED(location) ? (location.line + 1) : '?'; 2091 result += ' column '; 2092 result += !IS_UNDEFINED(location) ? (location.column + 1) : '?'; 2093 if (!IS_UNDEFINED(this.sourcePosition())) { 2094 result += ' (position ' + (this.sourcePosition() + 1) + ')'; 2095 } 2096 } 2097 } else { 2098 result += '[no source]'; 2099 } 2100 } else { 2101 result += '[unresolved]'; 2102 } 2103 2104 return result; 2105}; 2106 2107 2108FrameMirror.prototype.localsText = function() { 2109 // Format local variables. 2110 var result = ''; 2111 var locals_count = this.localCount(); 2112 if (locals_count > 0) { 2113 for (var i = 0; i < locals_count; ++i) { 2114 result += ' var '; 2115 result += this.localName(i); 2116 result += ' = '; 2117 result += this.localValue(i).toText(); 2118 if (i < locals_count - 1) result += '\n'; 2119 } 2120 } 2121 2122 return result; 2123}; 2124 2125 2126FrameMirror.prototype.restart = function() { 2127 var result = %LiveEditRestartFrame(this.break_id_, this.index_); 2128 if (IS_UNDEFINED(result)) { 2129 result = "Failed to find requested frame"; 2130 } 2131 return result; 2132}; 2133 2134 2135FrameMirror.prototype.toText = function(opt_locals) { 2136 var result = ''; 2137 result += '#' + (this.index() <= 9 ? '0' : '') + this.index(); 2138 result += ' '; 2139 result += this.invocationText(); 2140 result += ' '; 2141 result += this.sourceAndPositionText(); 2142 if (opt_locals) { 2143 result += '\n'; 2144 result += this.localsText(); 2145 } 2146 return result; 2147}; 2148 2149 2150var kScopeDetailsTypeIndex = 0; 2151var kScopeDetailsObjectIndex = 1; 2152 2153function ScopeDetails(frame, fun, index, opt_details) { 2154 if (frame) { 2155 this.break_id_ = frame.break_id_; 2156 this.details_ = opt_details || 2157 %GetScopeDetails(frame.break_id_, 2158 frame.details_.frameId(), 2159 frame.details_.inlinedFrameIndex(), 2160 index); 2161 this.frame_id_ = frame.details_.frameId(); 2162 this.inlined_frame_id_ = frame.details_.inlinedFrameIndex(); 2163 } else { 2164 this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index); 2165 this.fun_value_ = fun.value(); 2166 this.break_id_ = undefined; 2167 } 2168 this.index_ = index; 2169} 2170 2171 2172ScopeDetails.prototype.type = function() { 2173 if (!IS_UNDEFINED(this.break_id_)) { 2174 %CheckExecutionState(this.break_id_); 2175 } 2176 return this.details_[kScopeDetailsTypeIndex]; 2177}; 2178 2179 2180ScopeDetails.prototype.object = function() { 2181 if (!IS_UNDEFINED(this.break_id_)) { 2182 %CheckExecutionState(this.break_id_); 2183 } 2184 return this.details_[kScopeDetailsObjectIndex]; 2185}; 2186 2187 2188ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) { 2189 var raw_res; 2190 if (!IS_UNDEFINED(this.break_id_)) { 2191 %CheckExecutionState(this.break_id_); 2192 raw_res = %SetScopeVariableValue(this.break_id_, this.frame_id_, 2193 this.inlined_frame_id_, this.index_, name, new_value); 2194 } else { 2195 raw_res = %SetScopeVariableValue(this.fun_value_, null, null, this.index_, 2196 name, new_value); 2197 } 2198 if (!raw_res) { 2199 throw new Error("Failed to set variable value"); 2200 } 2201}; 2202 2203 2204/** 2205 * Mirror object for scope of frame or function. Either frame or function must 2206 * be specified. 2207 * @param {FrameMirror} frame The frame this scope is a part of 2208 * @param {FunctionMirror} function The function this scope is a part of 2209 * @param {number} index The scope index in the frame 2210 * @param {Array=} opt_details Raw scope details data 2211 * @constructor 2212 * @extends Mirror 2213 */ 2214function ScopeMirror(frame, function, index, opt_details) { 2215 %_CallFunction(this, SCOPE_TYPE, Mirror); 2216 if (frame) { 2217 this.frame_index_ = frame.index_; 2218 } else { 2219 this.frame_index_ = undefined; 2220 } 2221 this.scope_index_ = index; 2222 this.details_ = new ScopeDetails(frame, function, index, opt_details); 2223} 2224inherits(ScopeMirror, Mirror); 2225 2226 2227ScopeMirror.prototype.details = function() { 2228 return this.details_; 2229}; 2230 2231 2232ScopeMirror.prototype.frameIndex = function() { 2233 return this.frame_index_; 2234}; 2235 2236 2237ScopeMirror.prototype.scopeIndex = function() { 2238 return this.scope_index_; 2239}; 2240 2241 2242ScopeMirror.prototype.scopeType = function() { 2243 return this.details_.type(); 2244}; 2245 2246 2247ScopeMirror.prototype.scopeObject = function() { 2248 // For local and closure scopes create a transient mirror as these objects are 2249 // created on the fly materializing the local or closure scopes and 2250 // therefore will not preserve identity. 2251 var transient = this.scopeType() == ScopeType.Local || 2252 this.scopeType() == ScopeType.Closure; 2253 return MakeMirror(this.details_.object(), transient); 2254}; 2255 2256 2257ScopeMirror.prototype.setVariableValue = function(name, new_value) { 2258 this.details_.setVariableValueImpl(name, new_value); 2259}; 2260 2261 2262/** 2263 * Mirror object for script source. 2264 * @param {Script} script The script object 2265 * @constructor 2266 * @extends Mirror 2267 */ 2268function ScriptMirror(script) { 2269 %_CallFunction(this, SCRIPT_TYPE, Mirror); 2270 this.script_ = script; 2271 this.context_ = new ContextMirror(script.context_data); 2272 this.allocateHandle_(); 2273} 2274inherits(ScriptMirror, Mirror); 2275 2276 2277ScriptMirror.prototype.value = function() { 2278 return this.script_; 2279}; 2280 2281 2282ScriptMirror.prototype.name = function() { 2283 return this.script_.name || this.script_.nameOrSourceURL(); 2284}; 2285 2286 2287ScriptMirror.prototype.id = function() { 2288 return this.script_.id; 2289}; 2290 2291 2292ScriptMirror.prototype.source = function() { 2293 return this.script_.source; 2294}; 2295 2296 2297ScriptMirror.prototype.setSource = function(source) { 2298 %DebugSetScriptSource(this.script_, source); 2299}; 2300 2301 2302ScriptMirror.prototype.lineOffset = function() { 2303 return this.script_.line_offset; 2304}; 2305 2306 2307ScriptMirror.prototype.columnOffset = function() { 2308 return this.script_.column_offset; 2309}; 2310 2311 2312ScriptMirror.prototype.data = function() { 2313 return this.script_.data; 2314}; 2315 2316 2317ScriptMirror.prototype.scriptType = function() { 2318 return this.script_.type; 2319}; 2320 2321 2322ScriptMirror.prototype.compilationType = function() { 2323 return this.script_.compilation_type; 2324}; 2325 2326 2327ScriptMirror.prototype.lineCount = function() { 2328 return this.script_.lineCount(); 2329}; 2330 2331 2332ScriptMirror.prototype.locationFromPosition = function( 2333 position, include_resource_offset) { 2334 return this.script_.locationFromPosition(position, include_resource_offset); 2335}; 2336 2337 2338ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) { 2339 return this.script_.sourceSlice(opt_from_line, opt_to_line); 2340}; 2341 2342 2343ScriptMirror.prototype.context = function() { 2344 return this.context_; 2345}; 2346 2347 2348ScriptMirror.prototype.evalFromScript = function() { 2349 return MakeMirror(this.script_.eval_from_script); 2350}; 2351 2352 2353ScriptMirror.prototype.evalFromFunctionName = function() { 2354 return MakeMirror(this.script_.eval_from_function_name); 2355}; 2356 2357 2358ScriptMirror.prototype.evalFromLocation = function() { 2359 var eval_from_script = this.evalFromScript(); 2360 if (!eval_from_script.isUndefined()) { 2361 var position = this.script_.eval_from_script_position; 2362 return eval_from_script.locationFromPosition(position, true); 2363 } 2364}; 2365 2366 2367ScriptMirror.prototype.toText = function() { 2368 var result = ''; 2369 result += this.name(); 2370 result += ' (lines: '; 2371 if (this.lineOffset() > 0) { 2372 result += this.lineOffset(); 2373 result += '-'; 2374 result += this.lineOffset() + this.lineCount() - 1; 2375 } else { 2376 result += this.lineCount(); 2377 } 2378 result += ')'; 2379 return result; 2380}; 2381 2382 2383/** 2384 * Mirror object for context. 2385 * @param {Object} data The context data 2386 * @constructor 2387 * @extends Mirror 2388 */ 2389function ContextMirror(data) { 2390 %_CallFunction(this, CONTEXT_TYPE, Mirror); 2391 this.data_ = data; 2392 this.allocateHandle_(); 2393} 2394inherits(ContextMirror, Mirror); 2395 2396 2397ContextMirror.prototype.data = function() { 2398 return this.data_; 2399}; 2400 2401 2402/** 2403 * Returns a mirror serializer 2404 * 2405 * @param {boolean} details Set to true to include details 2406 * @param {Object} options Options comtrolling the serialization 2407 * The following options can be set: 2408 * includeSource: include ths full source of scripts 2409 * @returns {MirrorSerializer} mirror serializer 2410 */ 2411function MakeMirrorSerializer(details, options) { 2412 return new JSONProtocolSerializer(details, options); 2413} 2414 2415 2416/** 2417 * Object for serializing a mirror objects and its direct references. 2418 * @param {boolean} details Indicates whether to include details for the mirror 2419 * serialized 2420 * @constructor 2421 */ 2422function JSONProtocolSerializer(details, options) { 2423 this.details_ = details; 2424 this.options_ = options; 2425 this.mirrors_ = [ ]; 2426} 2427 2428 2429/** 2430 * Returns a serialization of an object reference. The referenced object are 2431 * added to the serialization state. 2432 * 2433 * @param {Mirror} mirror The mirror to serialize 2434 * @returns {String} JSON serialization 2435 */ 2436JSONProtocolSerializer.prototype.serializeReference = function(mirror) { 2437 return this.serialize_(mirror, true, true); 2438}; 2439 2440 2441/** 2442 * Returns a serialization of an object value. The referenced objects are 2443 * added to the serialization state. 2444 * 2445 * @param {Mirror} mirror The mirror to serialize 2446 * @returns {String} JSON serialization 2447 */ 2448JSONProtocolSerializer.prototype.serializeValue = function(mirror) { 2449 var json = this.serialize_(mirror, false, true); 2450 return json; 2451}; 2452 2453 2454/** 2455 * Returns a serialization of all the objects referenced. 2456 * 2457 * @param {Mirror} mirror The mirror to serialize. 2458 * @returns {Array.<Object>} Array of the referenced objects converted to 2459 * protcol objects. 2460 */ 2461JSONProtocolSerializer.prototype.serializeReferencedObjects = function() { 2462 // Collect the protocol representation of the referenced objects in an array. 2463 var content = []; 2464 2465 // Get the number of referenced objects. 2466 var count = this.mirrors_.length; 2467 2468 for (var i = 0; i < count; i++) { 2469 content.push(this.serialize_(this.mirrors_[i], false, false)); 2470 } 2471 2472 return content; 2473}; 2474 2475 2476JSONProtocolSerializer.prototype.includeSource_ = function() { 2477 return this.options_ && this.options_.includeSource; 2478}; 2479 2480 2481JSONProtocolSerializer.prototype.inlineRefs_ = function() { 2482 return this.options_ && this.options_.inlineRefs; 2483}; 2484 2485 2486JSONProtocolSerializer.prototype.maxStringLength_ = function() { 2487 if (IS_UNDEFINED(this.options_) || 2488 IS_UNDEFINED(this.options_.maxStringLength)) { 2489 return kMaxProtocolStringLength; 2490 } 2491 return this.options_.maxStringLength; 2492}; 2493 2494 2495JSONProtocolSerializer.prototype.add_ = function(mirror) { 2496 // If this mirror is already in the list just return. 2497 for (var i = 0; i < this.mirrors_.length; i++) { 2498 if (this.mirrors_[i] === mirror) { 2499 return; 2500 } 2501 } 2502 2503 // Add the mirror to the list of mirrors to be serialized. 2504 this.mirrors_.push(mirror); 2505}; 2506 2507 2508/** 2509 * Formats mirror object to protocol reference object with some data that can 2510 * be used to display the value in debugger. 2511 * @param {Mirror} mirror Mirror to serialize. 2512 * @return {Object} Protocol reference object. 2513 */ 2514JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ = 2515 function(mirror) { 2516 var o = {}; 2517 o.ref = mirror.handle(); 2518 o.type = mirror.type(); 2519 switch (mirror.type()) { 2520 case UNDEFINED_TYPE: 2521 case NULL_TYPE: 2522 case BOOLEAN_TYPE: 2523 case NUMBER_TYPE: 2524 o.value = mirror.value(); 2525 break; 2526 case STRING_TYPE: 2527 o.value = mirror.getTruncatedValue(this.maxStringLength_()); 2528 break; 2529 case SYMBOL_TYPE: 2530 o.description = mirror.description(); 2531 break; 2532 case FUNCTION_TYPE: 2533 o.name = mirror.name(); 2534 o.inferredName = mirror.inferredName(); 2535 if (mirror.script()) { 2536 o.scriptId = mirror.script().id(); 2537 } 2538 break; 2539 case ERROR_TYPE: 2540 case REGEXP_TYPE: 2541 o.value = mirror.toText(); 2542 break; 2543 case OBJECT_TYPE: 2544 o.className = mirror.className(); 2545 break; 2546 } 2547 return o; 2548}; 2549 2550 2551JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference, 2552 details) { 2553 // If serializing a reference to a mirror just return the reference and add 2554 // the mirror to the referenced mirrors. 2555 if (reference && 2556 (mirror.isValue() || mirror.isScript() || mirror.isContext())) { 2557 if (this.inlineRefs_() && mirror.isValue()) { 2558 return this.serializeReferenceWithDisplayData_(mirror); 2559 } else { 2560 this.add_(mirror); 2561 return {'ref' : mirror.handle()}; 2562 } 2563 } 2564 2565 // Collect the JSON property/value pairs. 2566 var content = {}; 2567 2568 // Add the mirror handle. 2569 if (mirror.isValue() || mirror.isScript() || mirror.isContext()) { 2570 content.handle = mirror.handle(); 2571 } 2572 2573 // Always add the type. 2574 content.type = mirror.type(); 2575 2576 switch (mirror.type()) { 2577 case UNDEFINED_TYPE: 2578 case NULL_TYPE: 2579 // Undefined and null are represented just by their type. 2580 break; 2581 2582 case BOOLEAN_TYPE: 2583 // Boolean values are simply represented by their value. 2584 content.value = mirror.value(); 2585 break; 2586 2587 case NUMBER_TYPE: 2588 // Number values are simply represented by their value. 2589 content.value = NumberToJSON_(mirror.value()); 2590 break; 2591 2592 case STRING_TYPE: 2593 // String values might have their value cropped to keep down size. 2594 if (this.maxStringLength_() != -1 && 2595 mirror.length() > this.maxStringLength_()) { 2596 var str = mirror.getTruncatedValue(this.maxStringLength_()); 2597 content.value = str; 2598 content.fromIndex = 0; 2599 content.toIndex = this.maxStringLength_(); 2600 } else { 2601 content.value = mirror.value(); 2602 } 2603 content.length = mirror.length(); 2604 break; 2605 2606 case SYMBOL_TYPE: 2607 content.description = mirror.description(); 2608 break; 2609 2610 case OBJECT_TYPE: 2611 case FUNCTION_TYPE: 2612 case ERROR_TYPE: 2613 case REGEXP_TYPE: 2614 case PROMISE_TYPE: 2615 case GENERATOR_TYPE: 2616 // Add object representation. 2617 this.serializeObject_(mirror, content, details); 2618 break; 2619 2620 case PROPERTY_TYPE: 2621 case INTERNAL_PROPERTY_TYPE: 2622 throw new Error('PropertyMirror cannot be serialized independently'); 2623 break; 2624 2625 case FRAME_TYPE: 2626 // Add object representation. 2627 this.serializeFrame_(mirror, content); 2628 break; 2629 2630 case SCOPE_TYPE: 2631 // Add object representation. 2632 this.serializeScope_(mirror, content); 2633 break; 2634 2635 case SCRIPT_TYPE: 2636 // Script is represented by id, name and source attributes. 2637 if (mirror.name()) { 2638 content.name = mirror.name(); 2639 } 2640 content.id = mirror.id(); 2641 content.lineOffset = mirror.lineOffset(); 2642 content.columnOffset = mirror.columnOffset(); 2643 content.lineCount = mirror.lineCount(); 2644 if (mirror.data()) { 2645 content.data = mirror.data(); 2646 } 2647 if (this.includeSource_()) { 2648 content.source = mirror.source(); 2649 } else { 2650 var sourceStart = mirror.source().substring(0, 80); 2651 content.sourceStart = sourceStart; 2652 } 2653 content.sourceLength = mirror.source().length; 2654 content.scriptType = mirror.scriptType(); 2655 content.compilationType = mirror.compilationType(); 2656 // For compilation type eval emit information on the script from which 2657 // eval was called if a script is present. 2658 if (mirror.compilationType() == 1 && 2659 mirror.evalFromScript()) { 2660 content.evalFromScript = 2661 this.serializeReference(mirror.evalFromScript()); 2662 var evalFromLocation = mirror.evalFromLocation(); 2663 if (evalFromLocation) { 2664 content.evalFromLocation = { line: evalFromLocation.line, 2665 column: evalFromLocation.column }; 2666 } 2667 if (mirror.evalFromFunctionName()) { 2668 content.evalFromFunctionName = mirror.evalFromFunctionName(); 2669 } 2670 } 2671 if (mirror.context()) { 2672 content.context = this.serializeReference(mirror.context()); 2673 } 2674 break; 2675 2676 case CONTEXT_TYPE: 2677 content.data = mirror.data(); 2678 break; 2679 } 2680 2681 // Always add the text representation. 2682 content.text = mirror.toText(); 2683 2684 // Create and return the JSON string. 2685 return content; 2686}; 2687 2688 2689/** 2690 * Serialize object information to the following JSON format. 2691 * 2692 * {"className":"<class name>", 2693 * "constructorFunction":{"ref":<number>}, 2694 * "protoObject":{"ref":<number>}, 2695 * "prototypeObject":{"ref":<number>}, 2696 * "namedInterceptor":<boolean>, 2697 * "indexedInterceptor":<boolean>, 2698 * "properties":[<properties>], 2699 * "internalProperties":[<internal properties>]} 2700 */ 2701JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content, 2702 details) { 2703 // Add general object properties. 2704 content.className = mirror.className(); 2705 content.constructorFunction = 2706 this.serializeReference(mirror.constructorFunction()); 2707 content.protoObject = this.serializeReference(mirror.protoObject()); 2708 content.prototypeObject = this.serializeReference(mirror.prototypeObject()); 2709 2710 // Add flags to indicate whether there are interceptors. 2711 if (mirror.hasNamedInterceptor()) { 2712 content.namedInterceptor = true; 2713 } 2714 if (mirror.hasIndexedInterceptor()) { 2715 content.indexedInterceptor = true; 2716 } 2717 2718 if (mirror.isFunction()) { 2719 // Add function specific properties. 2720 content.name = mirror.name(); 2721 if (!IS_UNDEFINED(mirror.inferredName())) { 2722 content.inferredName = mirror.inferredName(); 2723 } 2724 content.resolved = mirror.resolved(); 2725 if (mirror.resolved()) { 2726 content.source = mirror.source(); 2727 } 2728 if (mirror.script()) { 2729 content.script = this.serializeReference(mirror.script()); 2730 content.scriptId = mirror.script().id(); 2731 2732 serializeLocationFields(mirror.sourceLocation(), content); 2733 } 2734 2735 content.scopes = []; 2736 for (var i = 0; i < mirror.scopeCount(); i++) { 2737 var scope = mirror.scope(i); 2738 content.scopes.push({ 2739 type: scope.scopeType(), 2740 index: i 2741 }); 2742 } 2743 } 2744 2745 if (mirror.isGenerator()) { 2746 // Add generator specific properties. 2747 2748 // Either 'running', 'closed', or 'suspended'. 2749 content.status = mirror.status(); 2750 2751 content.func = this.serializeReference(mirror.func()) 2752 content.receiver = this.serializeReference(mirror.receiver()) 2753 2754 // If the generator is suspended, the content add line/column properties. 2755 serializeLocationFields(mirror.sourceLocation(), content); 2756 2757 // TODO(wingo): Also serialize a reference to the context (scope chain). 2758 } 2759 2760 if (mirror.isDate()) { 2761 // Add date specific properties. 2762 content.value = mirror.value(); 2763 } 2764 2765 if (mirror.isPromise()) { 2766 // Add promise specific properties. 2767 content.status = mirror.status(); 2768 content.promiseValue = this.serializeReference(mirror.promiseValue()); 2769 } 2770 2771 // Add actual properties - named properties followed by indexed properties. 2772 var propertyNames = mirror.propertyNames(PropertyKind.Named); 2773 var propertyIndexes = mirror.propertyNames(PropertyKind.Indexed); 2774 var p = new Array(propertyNames.length + propertyIndexes.length); 2775 for (var i = 0; i < propertyNames.length; i++) { 2776 var propertyMirror = mirror.property(propertyNames[i]); 2777 p[i] = this.serializeProperty_(propertyMirror); 2778 if (details) { 2779 this.add_(propertyMirror.value()); 2780 } 2781 } 2782 for (var i = 0; i < propertyIndexes.length; i++) { 2783 var propertyMirror = mirror.property(propertyIndexes[i]); 2784 p[propertyNames.length + i] = this.serializeProperty_(propertyMirror); 2785 if (details) { 2786 this.add_(propertyMirror.value()); 2787 } 2788 } 2789 content.properties = p; 2790 2791 var internalProperties = mirror.internalProperties(); 2792 if (internalProperties.length > 0) { 2793 var ip = []; 2794 for (var i = 0; i < internalProperties.length; i++) { 2795 ip.push(this.serializeInternalProperty_(internalProperties[i])); 2796 } 2797 content.internalProperties = ip; 2798 } 2799}; 2800 2801 2802/** 2803 * Serialize location information to the following JSON format: 2804 * 2805 * "position":"<position>", 2806 * "line":"<line>", 2807 * "column":"<column>", 2808 * 2809 * @param {SourceLocation} location The location to serialize, may be undefined. 2810 */ 2811function serializeLocationFields (location, content) { 2812 if (!location) { 2813 return; 2814 } 2815 content.position = location.position; 2816 var line = location.line; 2817 if (!IS_UNDEFINED(line)) { 2818 content.line = line; 2819 } 2820 var column = location.column; 2821 if (!IS_UNDEFINED(column)) { 2822 content.column = column; 2823 } 2824} 2825 2826 2827/** 2828 * Serialize property information to the following JSON format for building the 2829 * array of properties. 2830 * 2831 * {"name":"<property name>", 2832 * "attributes":<number>, 2833 * "propertyType":<number>, 2834 * "ref":<number>} 2835 * 2836 * If the attribute for the property is PropertyAttribute.None it is not added. 2837 * If the propertyType for the property is PropertyType.Normal it is not added. 2838 * Here are a couple of examples. 2839 * 2840 * {"name":"hello","ref":1} 2841 * {"name":"length","attributes":7,"propertyType":3,"ref":2} 2842 * 2843 * @param {PropertyMirror} propertyMirror The property to serialize. 2844 * @returns {Object} Protocol object representing the property. 2845 */ 2846JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) { 2847 var result = {}; 2848 2849 result.name = propertyMirror.name(); 2850 var propertyValue = propertyMirror.value(); 2851 if (this.inlineRefs_() && propertyValue.isValue()) { 2852 result.value = this.serializeReferenceWithDisplayData_(propertyValue); 2853 } else { 2854 if (propertyMirror.attributes() != PropertyAttribute.None) { 2855 result.attributes = propertyMirror.attributes(); 2856 } 2857 if (propertyMirror.propertyType() != PropertyType.Normal) { 2858 result.propertyType = propertyMirror.propertyType(); 2859 } 2860 result.ref = propertyValue.handle(); 2861 } 2862 return result; 2863}; 2864 2865 2866/** 2867 * Serialize internal property information to the following JSON format for 2868 * building the array of properties. 2869 * 2870 * {"name":"<property name>", 2871 * "ref":<number>} 2872 * 2873 * {"name":"[[BoundThis]]","ref":117} 2874 * 2875 * @param {InternalPropertyMirror} propertyMirror The property to serialize. 2876 * @returns {Object} Protocol object representing the property. 2877 */ 2878JSONProtocolSerializer.prototype.serializeInternalProperty_ = 2879 function(propertyMirror) { 2880 var result = {}; 2881 2882 result.name = propertyMirror.name(); 2883 var propertyValue = propertyMirror.value(); 2884 if (this.inlineRefs_() && propertyValue.isValue()) { 2885 result.value = this.serializeReferenceWithDisplayData_(propertyValue); 2886 } else { 2887 result.ref = propertyValue.handle(); 2888 } 2889 return result; 2890}; 2891 2892 2893JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) { 2894 content.index = mirror.index(); 2895 content.receiver = this.serializeReference(mirror.receiver()); 2896 var func = mirror.func(); 2897 content.func = this.serializeReference(func); 2898 var script = func.script(); 2899 if (script) { 2900 content.script = this.serializeReference(script); 2901 } 2902 content.constructCall = mirror.isConstructCall(); 2903 content.atReturn = mirror.isAtReturn(); 2904 if (mirror.isAtReturn()) { 2905 content.returnValue = this.serializeReference(mirror.returnValue()); 2906 } 2907 content.debuggerFrame = mirror.isDebuggerFrame(); 2908 var x = new Array(mirror.argumentCount()); 2909 for (var i = 0; i < mirror.argumentCount(); i++) { 2910 var arg = {}; 2911 var argument_name = mirror.argumentName(i); 2912 if (argument_name) { 2913 arg.name = argument_name; 2914 } 2915 arg.value = this.serializeReference(mirror.argumentValue(i)); 2916 x[i] = arg; 2917 } 2918 content.arguments = x; 2919 var x = new Array(mirror.localCount()); 2920 for (var i = 0; i < mirror.localCount(); i++) { 2921 var local = {}; 2922 local.name = mirror.localName(i); 2923 local.value = this.serializeReference(mirror.localValue(i)); 2924 x[i] = local; 2925 } 2926 content.locals = x; 2927 serializeLocationFields(mirror.sourceLocation(), content); 2928 var source_line_text = mirror.sourceLineText(); 2929 if (!IS_UNDEFINED(source_line_text)) { 2930 content.sourceLineText = source_line_text; 2931 } 2932 2933 content.scopes = []; 2934 for (var i = 0; i < mirror.scopeCount(); i++) { 2935 var scope = mirror.scope(i); 2936 content.scopes.push({ 2937 type: scope.scopeType(), 2938 index: i 2939 }); 2940 } 2941}; 2942 2943 2944JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) { 2945 content.index = mirror.scopeIndex(); 2946 content.frameIndex = mirror.frameIndex(); 2947 content.type = mirror.scopeType(); 2948 content.object = this.inlineRefs_() ? 2949 this.serializeValue(mirror.scopeObject()) : 2950 this.serializeReference(mirror.scopeObject()); 2951}; 2952 2953 2954/** 2955 * Convert a number to a protocol value. For all finite numbers the number 2956 * itself is returned. For non finite numbers NaN, Infinite and 2957 * -Infinite the string representation "NaN", "Infinite" or "-Infinite" 2958 * (not including the quotes) is returned. 2959 * 2960 * @param {number} value The number value to convert to a protocol value. 2961 * @returns {number|string} Protocol value. 2962 */ 2963function NumberToJSON_(value) { 2964 if (isNaN(value)) { 2965 return 'NaN'; 2966 } 2967 if (!NUMBER_IS_FINITE(value)) { 2968 if (value > 0) { 2969 return 'Infinity'; 2970 } else { 2971 return '-Infinity'; 2972 } 2973 } 2974 return value; 2975} 2976