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