| Index: src/debug/mirrors.js
|
| diff --git a/src/debug/mirrors.js b/src/debug/mirrors.js
|
| index 8b050500ff0254419c6df1eca748375d5f039ad1..2713be36b76c9d06fc5fc7c049d5b662b7bff6e3 100644
|
| --- a/src/debug/mirrors.js
|
| +++ b/src/debug/mirrors.js
|
| @@ -2463,11 +2463,577 @@
|
| return this.data_;
|
| };
|
|
|
| +
|
| +/**
|
| + * Returns a mirror serializer
|
| + *
|
| + * @param {boolean} details Set to true to include details
|
| + * @param {Object} options Options comtrolling the serialization
|
| + * The following options can be set:
|
| + * includeSource: include ths full source of scripts
|
| + * @returns {MirrorSerializer} mirror serializer
|
| + */
|
| +function MakeMirrorSerializer(details, options) {
|
| + return new JSONProtocolSerializer(details, options);
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Object for serializing a mirror objects and its direct references.
|
| + * @param {boolean} details Indicates whether to include details for the mirror
|
| + * serialized
|
| + * @constructor
|
| + */
|
| +function JSONProtocolSerializer(details, options) {
|
| + this.details_ = details;
|
| + this.options_ = options;
|
| + this.mirrors_ = [ ];
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Returns a serialization of an object reference. The referenced object are
|
| + * added to the serialization state.
|
| + *
|
| + * @param {Mirror} mirror The mirror to serialize
|
| + * @returns {String} JSON serialization
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeReference = function(mirror) {
|
| + return this.serialize_(mirror, true, true);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Returns a serialization of an object value. The referenced objects are
|
| + * added to the serialization state.
|
| + *
|
| + * @param {Mirror} mirror The mirror to serialize
|
| + * @returns {String} JSON serialization
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeValue = function(mirror) {
|
| + var json = this.serialize_(mirror, false, true);
|
| + return json;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Returns a serialization of all the objects referenced.
|
| + *
|
| + * @param {Mirror} mirror The mirror to serialize.
|
| + * @returns {Array.<Object>} Array of the referenced objects converted to
|
| + * protcol objects.
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeReferencedObjects = function() {
|
| + // Collect the protocol representation of the referenced objects in an array.
|
| + var content = [];
|
| +
|
| + // Get the number of referenced objects.
|
| + var count = this.mirrors_.length;
|
| +
|
| + for (var i = 0; i < count; i++) {
|
| + content.push(this.serialize_(this.mirrors_[i], false, false));
|
| + }
|
| +
|
| + return content;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.includeSource_ = function() {
|
| + return this.options_ && this.options_.includeSource;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.inlineRefs_ = function() {
|
| + return this.options_ && this.options_.inlineRefs;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.maxStringLength_ = function() {
|
| + if (IS_UNDEFINED(this.options_) ||
|
| + IS_UNDEFINED(this.options_.maxStringLength)) {
|
| + return kMaxProtocolStringLength;
|
| + }
|
| + return this.options_.maxStringLength;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.add_ = function(mirror) {
|
| + // If this mirror is already in the list just return.
|
| + for (var i = 0; i < this.mirrors_.length; i++) {
|
| + if (this.mirrors_[i] === mirror) {
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Add the mirror to the list of mirrors to be serialized.
|
| + this.mirrors_.push(mirror);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Formats mirror object to protocol reference object with some data that can
|
| + * be used to display the value in debugger.
|
| + * @param {Mirror} mirror Mirror to serialize.
|
| + * @return {Object} Protocol reference object.
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
|
| + function(mirror) {
|
| + var o = {};
|
| + o.ref = mirror.handle();
|
| + o.type = mirror.type();
|
| + switch (mirror.type()) {
|
| + case MirrorType.UNDEFINED_TYPE:
|
| + case MirrorType.NULL_TYPE:
|
| + case MirrorType.BOOLEAN_TYPE:
|
| + case MirrorType.NUMBER_TYPE:
|
| + o.value = mirror.value();
|
| + break;
|
| + case MirrorType.STRING_TYPE:
|
| + o.value = mirror.getTruncatedValue(this.maxStringLength_());
|
| + break;
|
| + case MirrorType.SYMBOL_TYPE:
|
| + o.description = mirror.description();
|
| + break;
|
| + case MirrorType.FUNCTION_TYPE:
|
| + o.name = mirror.name();
|
| + o.inferredName = mirror.inferredName();
|
| + if (mirror.script()) {
|
| + o.scriptId = mirror.script().id();
|
| + }
|
| + break;
|
| + case MirrorType.ERROR_TYPE:
|
| + case MirrorType.REGEXP_TYPE:
|
| + o.value = mirror.toText();
|
| + break;
|
| + case MirrorType.OBJECT_TYPE:
|
| + o.className = mirror.className();
|
| + break;
|
| + }
|
| + return o;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
|
| + details) {
|
| + // If serializing a reference to a mirror just return the reference and add
|
| + // the mirror to the referenced mirrors.
|
| + if (reference &&
|
| + (mirror.isValue() || mirror.isScript() || mirror.isContext())) {
|
| + if (this.inlineRefs_() && mirror.isValue()) {
|
| + return this.serializeReferenceWithDisplayData_(mirror);
|
| + } else {
|
| + this.add_(mirror);
|
| + return {'ref' : mirror.handle()};
|
| + }
|
| + }
|
| +
|
| + // Collect the JSON property/value pairs.
|
| + var content = {};
|
| +
|
| + // Add the mirror handle.
|
| + if (mirror.isValue() || mirror.isScript() || mirror.isContext()) {
|
| + content.handle = mirror.handle();
|
| + }
|
| +
|
| + // Always add the type.
|
| + content.type = mirror.type();
|
| +
|
| + switch (mirror.type()) {
|
| + case MirrorType.UNDEFINED_TYPE:
|
| + case MirrorType.NULL_TYPE:
|
| + // Undefined and null are represented just by their type.
|
| + break;
|
| +
|
| + case MirrorType.BOOLEAN_TYPE:
|
| + // Boolean values are simply represented by their value.
|
| + content.value = mirror.value();
|
| + break;
|
| +
|
| + case MirrorType.NUMBER_TYPE:
|
| + // Number values are simply represented by their value.
|
| + content.value = NumberToJSON_(mirror.value());
|
| + break;
|
| +
|
| + case MirrorType.STRING_TYPE:
|
| + // String values might have their value cropped to keep down size.
|
| + if (this.maxStringLength_() != -1 &&
|
| + mirror.length() > this.maxStringLength_()) {
|
| + var str = mirror.getTruncatedValue(this.maxStringLength_());
|
| + content.value = str;
|
| + content.fromIndex = 0;
|
| + content.toIndex = this.maxStringLength_();
|
| + } else {
|
| + content.value = mirror.value();
|
| + }
|
| + content.length = mirror.length();
|
| + break;
|
| +
|
| + case MirrorType.SYMBOL_TYPE:
|
| + content.description = mirror.description();
|
| + break;
|
| +
|
| + case MirrorType.OBJECT_TYPE:
|
| + case MirrorType.FUNCTION_TYPE:
|
| + case MirrorType.ERROR_TYPE:
|
| + case MirrorType.REGEXP_TYPE:
|
| + case MirrorType.PROMISE_TYPE:
|
| + case MirrorType.GENERATOR_TYPE:
|
| + // Add object representation.
|
| + this.serializeObject_(mirror, content, details);
|
| + break;
|
| +
|
| + case MirrorType.PROPERTY_TYPE:
|
| + case MirrorType.INTERNAL_PROPERTY_TYPE:
|
| + throw %make_error(kDebugger,
|
| + 'PropertyMirror cannot be serialized independently');
|
| + break;
|
| +
|
| + case MirrorType.FRAME_TYPE:
|
| + // Add object representation.
|
| + this.serializeFrame_(mirror, content);
|
| + break;
|
| +
|
| + case MirrorType.SCOPE_TYPE:
|
| + // Add object representation.
|
| + this.serializeScope_(mirror, content);
|
| + break;
|
| +
|
| + case MirrorType.SCRIPT_TYPE:
|
| + // Script is represented by id, name and source attributes.
|
| + if (mirror.name()) {
|
| + content.name = mirror.name();
|
| + }
|
| + content.id = mirror.id();
|
| + content.lineOffset = mirror.lineOffset();
|
| + content.columnOffset = mirror.columnOffset();
|
| + content.lineCount = mirror.lineCount();
|
| + if (mirror.data()) {
|
| + content.data = mirror.data();
|
| + }
|
| + if (this.includeSource_()) {
|
| + content.source = mirror.source();
|
| + } else {
|
| + var sourceStart = mirror.source().substring(0, 80);
|
| + content.sourceStart = sourceStart;
|
| + }
|
| + content.sourceLength = mirror.source().length;
|
| + content.scriptType = mirror.scriptType();
|
| + content.compilationType = mirror.compilationType();
|
| + // For compilation type eval emit information on the script from which
|
| + // eval was called if a script is present.
|
| + if (mirror.compilationType() == 1 &&
|
| + mirror.evalFromScript()) {
|
| + content.evalFromScript =
|
| + this.serializeReference(mirror.evalFromScript());
|
| + var evalFromLocation = mirror.evalFromLocation();
|
| + if (evalFromLocation) {
|
| + content.evalFromLocation = { line: evalFromLocation.line,
|
| + column: evalFromLocation.column };
|
| + }
|
| + if (mirror.evalFromFunctionName()) {
|
| + content.evalFromFunctionName = mirror.evalFromFunctionName();
|
| + }
|
| + }
|
| + if (mirror.context()) {
|
| + content.context = this.serializeReference(mirror.context());
|
| + }
|
| + break;
|
| +
|
| + case MirrorType.CONTEXT_TYPE:
|
| + content.data = mirror.data();
|
| + break;
|
| + }
|
| +
|
| + // Always add the text representation.
|
| + content.text = mirror.toText();
|
| +
|
| + // Create and return the JSON string.
|
| + return content;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Serialize object information to the following JSON format.
|
| + *
|
| + * {"className":"<class name>",
|
| + * "constructorFunction":{"ref":<number>},
|
| + * "protoObject":{"ref":<number>},
|
| + * "prototypeObject":{"ref":<number>},
|
| + * "namedInterceptor":<boolean>,
|
| + * "indexedInterceptor":<boolean>,
|
| + * "properties":[<properties>],
|
| + * "internalProperties":[<internal properties>]}
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content,
|
| + details) {
|
| + // Add general object properties.
|
| + content.className = mirror.className();
|
| + content.constructorFunction =
|
| + this.serializeReference(mirror.constructorFunction());
|
| + content.protoObject = this.serializeReference(mirror.protoObject());
|
| + content.prototypeObject = this.serializeReference(mirror.prototypeObject());
|
| +
|
| + // Add flags to indicate whether there are interceptors.
|
| + if (mirror.hasNamedInterceptor()) {
|
| + content.namedInterceptor = true;
|
| + }
|
| + if (mirror.hasIndexedInterceptor()) {
|
| + content.indexedInterceptor = true;
|
| + }
|
| +
|
| + if (mirror.isFunction()) {
|
| + // Add function specific properties.
|
| + content.name = mirror.name();
|
| + if (!IS_UNDEFINED(mirror.inferredName())) {
|
| + content.inferredName = mirror.inferredName();
|
| + }
|
| + content.resolved = mirror.resolved();
|
| + if (mirror.resolved()) {
|
| + content.source = mirror.source();
|
| + }
|
| + if (mirror.script()) {
|
| + content.script = this.serializeReference(mirror.script());
|
| + content.scriptId = mirror.script().id();
|
| +
|
| + serializeLocationFields(mirror.sourceLocation(), content);
|
| + }
|
| +
|
| + content.scopes = [];
|
| + for (var i = 0; i < mirror.scopeCount(); i++) {
|
| + var scope = mirror.scope(i);
|
| + content.scopes.push({
|
| + type: scope.scopeType(),
|
| + index: i
|
| + });
|
| + }
|
| + }
|
| +
|
| + if (mirror.isGenerator()) {
|
| + // Add generator specific properties.
|
| +
|
| + // Either 'running', 'closed', or 'suspended'.
|
| + content.status = mirror.status();
|
| +
|
| + content.func = this.serializeReference(mirror.func())
|
| + content.receiver = this.serializeReference(mirror.receiver())
|
| +
|
| + // If the generator is suspended, the content add line/column properties.
|
| + serializeLocationFields(mirror.sourceLocation(), content);
|
| +
|
| + // TODO(wingo): Also serialize a reference to the context (scope chain).
|
| + }
|
| +
|
| + if (mirror.isDate()) {
|
| + // Add date specific properties.
|
| + content.value = mirror.value();
|
| + }
|
| +
|
| + if (mirror.isPromise()) {
|
| + // Add promise specific properties.
|
| + content.status = mirror.status();
|
| + content.promiseValue = this.serializeReference(mirror.promiseValue());
|
| + }
|
| +
|
| + // Add actual properties - named properties followed by indexed properties.
|
| + var properties = mirror.propertyNames();
|
| + for (var i = 0; i < properties.length; i++) {
|
| + var propertyMirror = mirror.property(properties[i]);
|
| + properties[i] = this.serializeProperty_(propertyMirror);
|
| + if (details) {
|
| + this.add_(propertyMirror.value());
|
| + }
|
| + }
|
| + content.properties = properties;
|
| +
|
| + var internalProperties = mirror.internalProperties();
|
| + if (internalProperties.length > 0) {
|
| + var ip = [];
|
| + for (var i = 0; i < internalProperties.length; i++) {
|
| + ip.push(this.serializeInternalProperty_(internalProperties[i]));
|
| + }
|
| + content.internalProperties = ip;
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Serialize location information to the following JSON format:
|
| + *
|
| + * "position":"<position>",
|
| + * "line":"<line>",
|
| + * "column":"<column>",
|
| + *
|
| + * @param {SourceLocation} location The location to serialize, may be undefined.
|
| + */
|
| +function serializeLocationFields (location, content) {
|
| + if (!location) {
|
| + return;
|
| + }
|
| + content.position = location.position;
|
| + var line = location.line;
|
| + if (!IS_UNDEFINED(line)) {
|
| + content.line = line;
|
| + }
|
| + var column = location.column;
|
| + if (!IS_UNDEFINED(column)) {
|
| + content.column = column;
|
| + }
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Serialize property information to the following JSON format for building the
|
| + * array of properties.
|
| + *
|
| + * {"name":"<property name>",
|
| + * "attributes":<number>,
|
| + * "propertyType":<number>,
|
| + * "ref":<number>}
|
| + *
|
| + * If the attribute for the property is PropertyAttribute.None it is not added.
|
| + * Here are a couple of examples.
|
| + *
|
| + * {"name":"hello","propertyType":0,"ref":1}
|
| + * {"name":"length","attributes":7,"propertyType":3,"ref":2}
|
| + *
|
| + * @param {PropertyMirror} propertyMirror The property to serialize.
|
| + * @returns {Object} Protocol object representing the property.
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeProperty_ = function(propertyMirror) {
|
| + var result = {};
|
| +
|
| + result.name = propertyMirror.name();
|
| + var propertyValue = propertyMirror.value();
|
| + if (this.inlineRefs_() && propertyValue.isValue()) {
|
| + result.value = this.serializeReferenceWithDisplayData_(propertyValue);
|
| + } else {
|
| + if (propertyMirror.attributes() != PropertyAttribute.None) {
|
| + result.attributes = propertyMirror.attributes();
|
| + }
|
| + result.propertyType = propertyMirror.propertyType();
|
| + result.ref = propertyValue.handle();
|
| + }
|
| + return result;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Serialize internal property information to the following JSON format for
|
| + * building the array of properties.
|
| + *
|
| + * {"name":"<property name>",
|
| + * "ref":<number>}
|
| + *
|
| + * {"name":"[[BoundThis]]","ref":117}
|
| + *
|
| + * @param {InternalPropertyMirror} propertyMirror The property to serialize.
|
| + * @returns {Object} Protocol object representing the property.
|
| + */
|
| +JSONProtocolSerializer.prototype.serializeInternalProperty_ =
|
| + function(propertyMirror) {
|
| + var result = {};
|
| +
|
| + result.name = propertyMirror.name();
|
| + var propertyValue = propertyMirror.value();
|
| + if (this.inlineRefs_() && propertyValue.isValue()) {
|
| + result.value = this.serializeReferenceWithDisplayData_(propertyValue);
|
| + } else {
|
| + result.ref = propertyValue.handle();
|
| + }
|
| + return result;
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
|
| + content.index = mirror.index();
|
| + content.receiver = this.serializeReference(mirror.receiver());
|
| + var func = mirror.func();
|
| + content.func = this.serializeReference(func);
|
| + var script = func.script();
|
| + if (script) {
|
| + content.script = this.serializeReference(script);
|
| + }
|
| + content.constructCall = mirror.isConstructCall();
|
| + content.atReturn = mirror.isAtReturn();
|
| + if (mirror.isAtReturn()) {
|
| + content.returnValue = this.serializeReference(mirror.returnValue());
|
| + }
|
| + content.debuggerFrame = mirror.isDebuggerFrame();
|
| + var x = new GlobalArray(mirror.argumentCount());
|
| + for (var i = 0; i < mirror.argumentCount(); i++) {
|
| + var arg = {};
|
| + var argument_name = mirror.argumentName(i);
|
| + if (argument_name) {
|
| + arg.name = argument_name;
|
| + }
|
| + arg.value = this.serializeReference(mirror.argumentValue(i));
|
| + x[i] = arg;
|
| + }
|
| + content.arguments = x;
|
| + var x = new GlobalArray(mirror.localCount());
|
| + for (var i = 0; i < mirror.localCount(); i++) {
|
| + var local = {};
|
| + local.name = mirror.localName(i);
|
| + local.value = this.serializeReference(mirror.localValue(i));
|
| + x[i] = local;
|
| + }
|
| + content.locals = x;
|
| + serializeLocationFields(mirror.sourceLocation(), content);
|
| + var source_line_text = mirror.sourceLineText();
|
| + if (!IS_UNDEFINED(source_line_text)) {
|
| + content.sourceLineText = source_line_text;
|
| + }
|
| +
|
| + content.scopes = [];
|
| + for (var i = 0; i < mirror.scopeCount(); i++) {
|
| + var scope = mirror.scope(i);
|
| + content.scopes.push({
|
| + type: scope.scopeType(),
|
| + index: i
|
| + });
|
| + }
|
| +};
|
| +
|
| +
|
| +JSONProtocolSerializer.prototype.serializeScope_ = function(mirror, content) {
|
| + content.index = mirror.scopeIndex();
|
| + content.frameIndex = mirror.frameIndex();
|
| + content.type = mirror.scopeType();
|
| + content.object = this.inlineRefs_() ?
|
| + this.serializeValue(mirror.scopeObject()) :
|
| + this.serializeReference(mirror.scopeObject());
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Convert a number to a protocol value. For all finite numbers the number
|
| + * itself is returned. For non finite numbers NaN, Infinite and
|
| + * -Infinite the string representation "NaN", "Infinite" or "-Infinite"
|
| + * (not including the quotes) is returned.
|
| + *
|
| + * @param {number} value The number value to convert to a protocol value.
|
| + * @returns {number|string} Protocol value.
|
| + */
|
| +function NumberToJSON_(value) {
|
| + if (IsNaN(value)) {
|
| + return 'NaN';
|
| + }
|
| + if (!NUMBER_IS_FINITE(value)) {
|
| + if (value > 0) {
|
| + return 'Infinity';
|
| + } else {
|
| + return '-Infinity';
|
| + }
|
| + }
|
| + return value;
|
| +}
|
| +
|
| // ----------------------------------------------------------------------------
|
| // Exports
|
|
|
| utils.InstallFunctions(global, DONT_ENUM, [
|
| "MakeMirror", MakeMirror,
|
| + "MakeMirrorSerializer", MakeMirrorSerializer,
|
| "LookupMirror", LookupMirror,
|
| "ToggleMirrorCache", ToggleMirrorCache,
|
| "MirrorCacheIsEmpty", MirrorCacheIsEmpty,
|
|
|