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