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