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