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