Factored the generation of JSON serialization from beeing part of the mirror objects...
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 7 Jan 2009 09:27:30 +0000 (09:27 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 7 Jan 2009 09:27:30 +0000 (09:27 +0000)
Added a test case for the script mirror and modified a number of the other mirror tests.
Review URL: http://codereview.chromium.org/16539

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1035 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/mirror-delay.js
test/mjsunit/mirror-array.js
test/mjsunit/mirror-function.js
test/mjsunit/mirror-object.js
test/mjsunit/mirror-script.js [new file with mode: 0644]
test/mjsunit/mirror-string.js

index caf963e..e7ff910 100644 (file)
@@ -33,6 +33,12 @@ RegExp;
 Date;
 
 
+/**
+ * Returns the mirror for a specified value or object.
+ *
+ * @param {value or Object} value the value or object to retreive the mirror for
+ * @returns {Mirror} the mirror reflects the passed value or object
+ */
 function MakeMirror(value) {
   if (IS_UNDEFINED(value)) return new UndefinedMirror();
   if (IS_NULL(value)) return new NullMirror();
@@ -106,7 +112,6 @@ PropertyType.ConstantTransition = 6;
 PropertyType.NullDescriptor     = 7;
 
 
-
 // Different attributes for a property.
 PropertyAttribute = {};
 PropertyAttribute.None       = NONE;
@@ -123,12 +128,12 @@ PropertyAttribute.DontDelete = DONT_DELETE;
 //       - NumberMirror
 //       - StringMirror
 //       - ObjectMirror
-//       - FunctionMirror
-//         - UnresolvedFunctionMirror
-//       - ArrayMirror
-//       - DateMirror
-//       - RegExpMirror
-//       - ErrorMirror
+//         - FunctionMirror
+//           - UnresolvedFunctionMirror
+//         - ArrayMirror
+//         - DateMirror
+//         - RegExpMirror
+//         - ErrorMirror
 //     - PropertyMirror
 //       - InterceptorPropertyMirror
 //     - AccessorMirror
@@ -296,29 +301,24 @@ Mirror.prototype.isFrame = function() {
 }
 
 
-Mirror.prototype.fillJSONType_ = function(content) {
-  content.push(MakeJSONPair_('type', StringToJSON_(this.type())));
-};
-
-
-Mirror.prototype.fillJSON_ = function(content) {
-  this.fillJSONType_(content);
-};
+/**
+ * Check whether the mirror reflects a script.
+ * @returns {boolean} True if the mirror reflects a script
+ */
+Mirror.prototype.isScript = function() {
+  return this instanceof ScriptMirror;
+}
 
 
 /**
- * Serialize object in JSON format. For the basic mirrors this includes only
- * the type in the following format.
- *   {"type":"<type name>"}
- * For specialized mirrors inheriting from the base Mirror
+ * Serialize object in JSON format. The actual serialization is handled by the
+ * JSONProtocolSerializer.
  * @param {boolean} details Indicate level of details to include
  * @return {string} JSON serialization
  */
-Mirror.prototype.toJSONProtocol = function(details, propertiesKind, interceptorPropertiesKind) {
-  var content = new Array();
-  this.fillJSON_(content, details, propertiesKind, interceptorPropertiesKind);
-  content.push(MakeJSONPair_('text', StringToJSON_(this.toText())));
-  return ArrayToJSONObject_(content);
+Mirror.prototype.toJSONProtocol = function(details) {
+  var serializer = new JSONProtocolSerializer(details)
+  return serializer.serialize(this)
 }
 
 
@@ -409,12 +409,6 @@ function BooleanMirror(value) {
 inherits(BooleanMirror, ValueMirror);
 
 
-BooleanMirror.prototype.fillJSON_ = function(content, details) {
-  BooleanMirror.super_.fillJSONType_.call(this, content);
-  content.push(MakeJSONPair_('value', BooleanToJSON_(this.value_)));
-}
-
-
 BooleanMirror.prototype.toText = function() {
   return this.value_ ? 'true' : 'false';
 }
@@ -432,12 +426,6 @@ function NumberMirror(value) {
 inherits(NumberMirror, ValueMirror);
 
 
-NumberMirror.prototype.fillJSON_ = function(content, details) {
-  NumberMirror.super_.fillJSONType_.call(this, content);
-  content.push(MakeJSONPair_('value', NumberToJSON_(this.value_)));
-}
-
-
 NumberMirror.prototype.toText = function() {
   return %NumberToString(this.value_);
 }
@@ -460,21 +448,6 @@ StringMirror.prototype.length = function() {
 };
 
 
-StringMirror.prototype.fillJSON_ = function(content, details) {
-  StringMirror.super_.fillJSONType_.call(this, content);
-  content.push(MakeJSONPair_('length', NumberToJSON_(this.length())));
-  if (this.length() > kMaxProtocolStringLength) {
-    content.push(MakeJSONPair_('fromIndex', NumberToJSON_(0)));
-    content.push(MakeJSONPair_('toIndex',
-                               NumberToJSON_(kMaxProtocolStringLength)));
-    var str = this.value_.substring(0, kMaxProtocolStringLength);
-    content.push(MakeJSONPair_('value', StringToJSON_(str)));
-  } else {
-    content.push(MakeJSONPair_('value', StringToJSON_(this.value_)));
-  }
-}
-
-
 StringMirror.prototype.toText = function() {
   if (this.length() > kMaxProtocolStringLength) {
     return this.value_.substring(0, kMaxProtocolStringLength) +
@@ -738,49 +711,6 @@ ObjectMirror.prototype.referencedBy = function(opt_max_instances) {
 };
 
 
-ObjectMirror.prototype.fillJSONProperties_ = function(content, kind, name, details) {
-  var propertyNames = this.propertyNames(kind);
-  var x = new Array(propertyNames.length);
-  for (var i = 0; i < propertyNames.length; i++) {
-    x[i] = this.property(propertyNames[i]).toJSONProtocol(details);
-  }
-  content.push(MakeJSONPair_(name || 'properties', ArrayToJSONArray_(x)));
-};
-
-
-ObjectMirror.prototype.fillJSONInterceptorProperties_ = function(content, kind, name, details) {
-  var propertyNames = this.interceptorPropertyNames(kind);
-  var x = new Array(propertyNames.length);
-  for (var i = 0; i < propertyNames.length; i++) {
-    x[i] = properties[i].toJSONProtocol(details);
-  }
-  content.push(MakeJSONPair_(name || 'interceptorProperties', ArrayToJSONArray_(x)));
-};
-
-
-ObjectMirror.prototype.fillJSON_ = function(content, details, propertiesKind, interceptorPropertiesKind) {
-  ObjectMirror.super_.fillJSONType_.call(this, content);
-  content.push(MakeJSONPair_('className', StringToJSON_(this.className())));
-  if (details) {
-    content.push(MakeJSONPair_('constructorFunction', this.constructorFunction().toJSONProtocol(false)));
-    content.push(MakeJSONPair_('protoObject', this.protoObject().toJSONProtocol(false)));
-    content.push(MakeJSONPair_('prototypeObject', this.prototypeObject().toJSONProtocol(false)));
-  }
-  if (details) {
-    this.fillJSONProperties_(content, propertiesKind)
-    if (interceptorPropertiesKind) {
-      this.fillJSONInterceptorProperties_(content, interceptorPropertiesKind)
-    }
-  }
-  if (this.hasNamedInterceptor()) {
-    content.push(MakeJSONPair_('namedInterceptor', BooleanToJSON_(true)));
-  }
-  if (this.hasIndexedInterceptor()) {
-    content.push(MakeJSONPair_('indexedInterceptor', BooleanToJSON_(true)));
-  }
-};
-
-
 ObjectMirror.prototype.toText = function() {
   var name;
   var ctor = this.constructorFunction();
@@ -884,21 +814,6 @@ FunctionMirror.prototype.constructedBy = function(opt_max_instances) {
 };
 
 
-FunctionMirror.prototype.fillJSON_ = function(content, details) {
-  // Fill JSON properties from parent (ObjectMirror).
-  FunctionMirror.super_.fillJSON_.call(this, content, details);
-  // Add function specific properties.
-  content.push(MakeJSONPair_('name', StringToJSON_(this.name())));
-  content.push(MakeJSONPair_('resolved', BooleanToJSON_(this.resolved())));
-  if (details && this.resolved()) {
-    content.push(MakeJSONPair_('source', StringToJSON_(this.source())));
-  }
-  if (this.script()) {
-    content.push(MakeJSONPair_('script', this.script().toJSONProtocol()));
-  }
-}
-
-
 FunctionMirror.prototype.toText = function() {
   return this.source();
 }
@@ -988,18 +903,6 @@ ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_
 }
 
 
-ArrayMirror.prototype.fillJSON_ = function(content, details) {
-  // Fill JSON as for parent (ObjectMirror) but just with named properties.
-  ArrayMirror.super_.fillJSON_.call(this, content, details, PropertyKind.Named);
-  // Fill indexed properties seperately.
-  if (details) {
-    this.fillJSONProperties_(content, PropertyKind.Indexed, 'indexedProperties')
-  }
-  // Add the array length.
-  content.push(MakeJSONPair_('length', NumberToJSON_(this.length())));
-}
-
-
 /**
  * Mirror object for dates.
  * @param {Date} value The Date object reflected by this mirror
@@ -1012,14 +915,6 @@ function DateMirror(value) {
 inherits(DateMirror, ObjectMirror);
 
 
-DateMirror.prototype.fillJSON_ = function(content, details) {
-  // Fill JSON properties from parent (ObjectMirror).
-  DateMirror.super_.fillJSON_.call(this, content, details);
-  // Add date specific properties.
-  content.push(MakeJSONPair_('value', DateToJSON_(this.value_)));
-}
-
-
 DateMirror.prototype.toText = function() {
   return DateToISO8601_(this.value_);
 }
@@ -1073,17 +968,6 @@ RegExpMirror.prototype.multiline = function() {
 };
 
 
-RegExpMirror.prototype.fillJSON_ = function(content, details) {
-  // Fill JSON properties from parent (ObjectMirror).
-  RegExpMirror.super_.fillJSON_.call(this, content, details);
-  // Add regexp specific properties.
-  content.push(MakeJSONPair_('source', StringToJSON_(this.source())));
-  content.push(MakeJSONPair_('global', BooleanToJSON_(this.global())));
-  content.push(MakeJSONPair_('ignoreCase', BooleanToJSON_(this.ignoreCase())));
-  content.push(MakeJSONPair_('multiline', BooleanToJSON_(this.multiline())));
-}
-
-
 RegExpMirror.prototype.toText = function() {
   // Simpel to text which is used when on specialization in subclass.
   return "/" + this.source() + "/";
@@ -1111,14 +995,6 @@ ErrorMirror.prototype.message = function() {
 };
 
 
-ErrorMirror.prototype.fillJSON_ = function(content, details) {
-  // Fill JSON properties from parent (ObjectMirror).
-  ErrorMirror.super_.fillJSON_.call(this, content, details);
-  // Add error specific properties.
-  content.push(MakeJSONPair_('message', StringToJSON_(this.message())));
-}
-
-
 ErrorMirror.prototype.toText = function() {
   // Use the same text representation as in messages.js.
   var text;
@@ -1206,18 +1082,6 @@ PropertyMirror.prototype.insertionIndex = function() {
 }
 
 
-PropertyMirror.prototype.fillJSON_ = function(content, details) {
-  content.push(MakeJSONPair_('name', StringToJSON_(this.name())));
-  content.push(MakeJSONPair_('value', this.value().toJSONProtocol(details)));
-  if (this.attributes() != PropertyAttribute.None) {
-    content.push(MakeJSONPair_('attributes', NumberToJSON_(this.attributes())));
-  }
-  if (this.propertyType() != PropertyType.Normal) {
-    content.push(MakeJSONPair_('propertyType', NumberToJSON_(this.propertyType())));
-  }
-}
-
-
 /**
  * Mirror object for interceptor named properties.
  * @param {ObjectMirror} mirror The mirror object having this property
@@ -1278,28 +1142,6 @@ AccessorMirror.prototype.setter = function(details) {
 }
 
 
-/**
- * Serialize the accessor mirror into JSON format. For accessor it has the
- * following format.
- *   {"type":"accessor",
-      "native:"<boolean>,
-      "getter":<function mirror JSON serialization>,
-      "setter":<function mirror JSON serialization>}
- * For specialized mirrors inheriting from the base Mirror
- * @param {boolean} details Indicate level of details to include
- * @return {string} JSON serialization
- */
-AccessorMirror.prototype.fillJSON_ = function(content, details) {
-  AccessorMirror.super_.fillJSONType_.call(this, content);
-  if (this.isNative()) {
-    content.push(MakeJSONPair_('native', BooleanToJSON_(true)));
-  } else {
-    content.push(MakeJSONPair_('getter', this.getter().toJSONProtocol(false)));
-    content.push(MakeJSONPair_('setter', this.setter().toJSONProtocol(false)));
-  }
-}
-
-
 const kFrameDetailsFrameIdIndex = 0;
 const kFrameDetailsReceiverIndex = 1;
 const kFrameDetailsFunctionIndex = 2;
@@ -1558,47 +1400,6 @@ FrameMirror.prototype.evaluate = function(source, disable_break) {
 };
 
 
-FrameMirror.prototype.fillJSON_ = function(content, details) {
-  FrameMirror.super_.fillJSONType_.call(this, content);
-  content.push(MakeJSONPair_('index', NumberToJSON_(this.index())));
-  content.push(MakeJSONPair_('receiver', this.receiver().toJSONProtocol(false)));
-  content.push(MakeJSONPair_('func', this.func().toJSONProtocol(false)));
-  content.push(MakeJSONPair_('constructCall', BooleanToJSON_(this.isConstructCall())));
-  content.push(MakeJSONPair_('debuggerFrame', BooleanToJSON_(this.isDebuggerFrame())));
-  var x = new Array(this.argumentCount());
-  for (var i = 0; i < this.argumentCount(); i++) {
-    arg = new Array();
-    var argument_name = this.argumentName(i)
-    if (argument_name) {
-      arg.push(MakeJSONPair_('name', StringToJSON_(argument_name)));
-    }
-    arg.push(MakeJSONPair_('value', this.argumentValue(i).toJSONProtocol(false)));
-    x[i] = ArrayToJSONObject_(arg);
-  }
-  content.push(MakeJSONPair_('arguments', ArrayToJSONArray_(x)));
-  var x = new Array(this.localCount());
-  for (var i = 0; i < this.localCount(); i++) {
-    var name = MakeJSONPair_('name', StringToJSON_(this.localName(i)));
-    var value = MakeJSONPair_('value', this.localValue(i).toJSONProtocol(false));
-    x[i] = '{' + name + ',' + value + '}';
-  }
-  content.push(MakeJSONPair_('locals', ArrayToJSONArray_(x)));
-  content.push(MakeJSONPair_('position', NumberToJSON_(this.sourcePosition())));
-  var line = this.sourceLine();
-  if (!IS_UNDEFINED(line)) {
-    content.push(MakeJSONPair_('line', NumberToJSON_(line)));
-  }
-  var column = this.sourceColumn();
-  if (!IS_UNDEFINED(column)) {
-    content.push(MakeJSONPair_('column', NumberToJSON_(column)));
-  }
-  var source_line_text = this.sourceLineText();
-  if (!IS_UNDEFINED(source_line_text)) {
-    content.push(MakeJSONPair_('sourceLineText', StringToJSON_(source_line_text)));
-  }
-}
-
-
 FrameMirror.prototype.invocationText = function() {
   // Format frame invoaction (receiver, function and arguments).
   var result = '';
@@ -1783,18 +1584,6 @@ ScriptMirror.prototype.sourceSlice = function (opt_from_line, opt_to_line) {
 }
 
 
-ScriptMirror.prototype.fillJSON_ = function(content, details) {
-  ScriptMirror.super_.fillJSONType_.call(this, content);
-  if (this.name()) {
-    content.push(MakeJSONPair_('name', StringToJSON_(this.name())));
-  }
-  content.push(MakeJSONPair_('lineOffset', NumberToJSON_(this.lineOffset())));
-  content.push(MakeJSONPair_('columnOffset', NumberToJSON_(this.columnOffset())));
-  content.push(MakeJSONPair_('lineCount', NumberToJSON_(this.lineCount())));
-  content.push(MakeJSONPair_('scriptType', NumberToJSON_(this.scriptType())));
-}
-
-
 ScriptMirror.prototype.toText = function() {
   var result = '';
   result += this.name();
@@ -1811,6 +1600,244 @@ ScriptMirror.prototype.toText = function() {
 }
 
 
+function JSONProtocolSerializer(details) {
+  this.details_ = details;
+}
+
+
+JSONProtocolSerializer.prototype.serialize = function(mirror) {
+  // Collect the JSON property/value pairs in a array.
+  var content = new Array();
+
+  // Always add the type  
+  content.push(MakeJSONPair_('type', StringToJSON_(mirror.type())));
+
+  switch (mirror.type()) {
+    case UNDEFINED_TYPE:
+    case NULL_TYPE:
+      // Undefined and null are represented just by their type.
+      break;
+
+    case BOOLEAN_TYPE:
+      // Boolean values are simply represented by their value.
+      content.push(MakeJSONPair_('value', BooleanToJSON_(mirror.value())));
+      break;
+
+    case NUMBER_TYPE:
+      // Number values are simply represented by their value.
+      content.push(MakeJSONPair_('value', NumberToJSON_(mirror.value())));
+      break;
+
+    case STRING_TYPE:
+      // String values might have their value cropped to keep down size.
+      if (mirror.length() > kMaxProtocolStringLength) {
+        var str = mirror.value().substring(0, kMaxProtocolStringLength);
+        content.push(MakeJSONPair_('value', StringToJSON_(str)));
+        content.push(MakeJSONPair_('fromIndex', NumberToJSON_(0)));
+        content.push(MakeJSONPair_('toIndex',
+                                   NumberToJSON_(kMaxProtocolStringLength)));
+      } else {
+        content.push(MakeJSONPair_('value', StringToJSON_(mirror.value())));
+      }
+      content.push(MakeJSONPair_('length', NumberToJSON_(mirror.length())));
+      break;
+
+    case OBJECT_TYPE:
+    case FUNCTION_TYPE:
+    case ERROR_TYPE:
+    case REGEXP_TYPE:
+      // Add object representation.
+      this.serializeObject_(mirror, content);
+      break;
+
+    case PROPERTY_TYPE:
+      // Properties are represented by name, value, attributes and type.
+      content.push(MakeJSONPair_('name',
+                                 StringToJSON_(mirror.name())));
+      content.push(MakeJSONPair_('value',
+                                 mirror.value().toJSONProtocol(this.details_)));
+      if (mirror.attributes() != PropertyAttribute.None) {
+        content.push(MakeJSONPair_('attributes',
+                                   NumberToJSON_(mirror.attributes())));
+      }
+      if (mirror.propertyType() != PropertyType.Normal) {
+        content.push(MakeJSONPair_('propertyType',
+                                   NumberToJSON_(mirror.propertyType())));
+      }
+      break;
+
+    case ACCESSOR_TYPE:
+      // An accessor can either be native or defined through JavaScript.
+      if (mirror.isNative()) {
+        content.push(MakeJSONPair_('native', BooleanToJSON_(true)));
+      } else {
+        content.push(MakeJSONPair_('getter',
+                                   mirror.getter().toJSONProtocol(false)));
+        content.push(MakeJSONPair_('setter',
+                                   mirror.setter().toJSONProtocol(false)));
+      }
+      break;
+
+    case FRAME_TYPE:
+      // Add object representation.
+      this.serializeFrame_(mirror, content);
+      break;
+
+    case SCRIPT_TYPE:
+      // Script is represented by name and source attributes.
+      if (mirror.name()) {
+        content.push(MakeJSONPair_('name', StringToJSON_(mirror.name())));
+      }
+      content.push(MakeJSONPair_('lineOffset',
+                                 NumberToJSON_(mirror.lineOffset())));
+      content.push(MakeJSONPair_('columnOffset',
+                                 NumberToJSON_(mirror.columnOffset())));
+      content.push(MakeJSONPair_('lineCount',
+                                 NumberToJSON_(mirror.lineCount())));
+      content.push(MakeJSONPair_('scriptType',
+                                 NumberToJSON_(mirror.scriptType())));
+      break;
+
+  }
+
+  // Always add the text representation.
+  content.push(MakeJSONPair_('text', StringToJSON_(mirror.toText())));
+  
+  // Create and return the JSON string.
+  return ArrayToJSONObject_(content);
+}
+
+
+JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content) {
+  content.push(MakeJSONPair_('className',
+                             StringToJSON_(mirror.className())));
+
+  if (this.details_) {
+    content.push(MakeJSONPair_('constructorFunction',
+        mirror.constructorFunction().toJSONProtocol(false)));
+    content.push(MakeJSONPair_('protoObject',
+                               mirror.protoObject().toJSONProtocol(false)));
+    content.push(MakeJSONPair_('prototypeObject',
+                               mirror.prototypeObject().toJSONProtocol(false)));
+
+    // Add properties. For arrays don't include indexed proeprties.
+    var kind = PropertyKind.Named;
+    if (!mirror.isArray()) {
+      kind |= PropertyKind.Indexed
+    }
+    var propertyNames = mirror.propertyNames(kind);
+    var x = new Array(propertyNames.length);
+    for (var i = 0; i < propertyNames.length; i++) {
+      x[i] = mirror.property(propertyNames[i]).toJSONProtocol(false);
+    }
+    content.push(MakeJSONPair_('properties', ArrayToJSONArray_(x)));
+
+    // Add interceptor properties.
+    propertyNames = mirror.interceptorPropertyNames();
+    var x = new Array(propertyNames.length);
+    for (var i = 0; i < propertyNames.length; i++) {
+      x[i] = properties[i].toJSONProtocol(details);
+    }
+    content.push(MakeJSONPair_('interceptorProperties', ArrayToJSONArray_(x)));
+
+    // For arrays the indexed properties are added separately and the length is
+    // added as well.
+    if (mirror.isArray()) {
+      var propertyNames = mirror.propertyNames(PropertyKind.Indexed);
+      var x = new Array(propertyNames.length);
+      for (var i = 0; i < propertyNames.length; i++) {
+        x[i] = mirror.property(propertyNames[i]).toJSONProtocol(false);
+      }
+      content.push(MakeJSONPair_('indexedProperties', ArrayToJSONArray_(x)));
+
+      // Add the array length.
+      content.push(MakeJSONPair_('length', NumberToJSON_(mirror.length())));
+    }
+  }
+
+  if (mirror.hasNamedInterceptor()) {
+    content.push(MakeJSONPair_('namedInterceptor', BooleanToJSON_(true)));
+  }
+
+  if (mirror.hasIndexedInterceptor()) {
+    content.push(MakeJSONPair_('indexedInterceptor', BooleanToJSON_(true)));
+  }
+  
+  if (mirror.isFunction()) {
+    // Add function specific properties.
+    content.push(MakeJSONPair_('name', StringToJSON_(mirror.name())));
+    content.push(MakeJSONPair_('resolved', BooleanToJSON_(mirror.resolved())));
+    if (this.details_ && mirror.resolved()) {
+      content.push(MakeJSONPair_('source', StringToJSON_(mirror.source())));
+    }
+    if (mirror.script()) {
+      content.push(MakeJSONPair_('script', mirror.script().toJSONProtocol()));
+    }
+  } else if (mirror.isDate()) {
+    // Add date specific properties.
+    content.push(MakeJSONPair_('value', DateToJSON_(mirror.value())));
+  } else if (mirror.isRegExp()) {
+    // Add regexp specific properties.
+    content.push(MakeJSONPair_('source', StringToJSON_(mirror.source())));
+    content.push(MakeJSONPair_('global', BooleanToJSON_(mirror.global())));
+    content.push(MakeJSONPair_('ignoreCase',
+                               BooleanToJSON_(mirror.ignoreCase())));
+    content.push(MakeJSONPair_('multiline',
+                               BooleanToJSON_(mirror.multiline())));
+  } else if (mirror.isError()) {
+    // Add error specific properties.
+    content.push(MakeJSONPair_('message', StringToJSON_(mirror.message())));
+  }
+}
+
+
+JSONProtocolSerializer.prototype.serializeFrame_ = function(mirror, content) {
+  content.push(MakeJSONPair_('index', NumberToJSON_(mirror.index())));
+  content.push(MakeJSONPair_('receiver',
+                             mirror.receiver().toJSONProtocol(false)));
+  content.push(MakeJSONPair_('func', mirror.func().toJSONProtocol(false)));
+  content.push(MakeJSONPair_('constructCall',
+                             BooleanToJSON_(mirror.isConstructCall())));
+  content.push(MakeJSONPair_('debuggerFrame',
+                             BooleanToJSON_(mirror.isDebuggerFrame())));
+  var x = new Array(mirror.argumentCount());
+  for (var i = 0; i < mirror.argumentCount(); i++) {
+    arg = new Array();
+    var argument_name = mirror.argumentName(i)
+    if (argument_name) {
+      arg.push(MakeJSONPair_('name', StringToJSON_(argument_name)));
+    }
+    arg.push(MakeJSONPair_('value',
+                           mirror.argumentValue(i).toJSONProtocol(false)));
+    x[i] = ArrayToJSONObject_(arg);
+  }
+  content.push(MakeJSONPair_('arguments', ArrayToJSONArray_(x)));
+  var x = new Array(mirror.localCount());
+  for (var i = 0; i < mirror.localCount(); i++) {
+    var name = MakeJSONPair_('name', StringToJSON_(mirror.localName(i)));
+    var value = MakeJSONPair_('value',
+                              mirror.localValue(i).toJSONProtocol(false));
+    x[i] = '{' + name + ',' + value + '}';
+  }
+  content.push(MakeJSONPair_('locals', ArrayToJSONArray_(x)));
+  content.push(MakeJSONPair_('position',
+                             NumberToJSON_(mirror.sourcePosition())));
+  var line = mirror.sourceLine();
+  if (!IS_UNDEFINED(line)) {
+    content.push(MakeJSONPair_('line', NumberToJSON_(line)));
+  }
+  var column = mirror.sourceColumn();
+  if (!IS_UNDEFINED(column)) {
+    content.push(MakeJSONPair_('column', NumberToJSON_(column)));
+  }
+  var source_line_text = mirror.sourceLineText();
+  if (!IS_UNDEFINED(source_line_text)) {
+    content.push(MakeJSONPair_('sourceLineText',
+                               StringToJSON_(source_line_text)));
+  }
+}
+
+
 function MakeJSONPair_(name, value) {
   return '"' + name + '":' + value;
 }
index 25e64a6..93c87bd 100644 (file)
@@ -47,7 +47,7 @@ function testArrayMirror(a, names) {
   assertTrue(mirror.constructorFunction() instanceof debug.ObjectMirror);
   assertTrue(mirror.protoObject() instanceof debug.Mirror);
   assertTrue(mirror.prototypeObject() instanceof debug.Mirror);
-  assertEquals(mirror.length(), a.length);
+  assertEquals(mirror.length(), a.length, "Length mismatch");
   
   var indexedValueMirrors = mirror.indexedPropertiesFromRange();
   assertEquals(indexedValueMirrors.length, a.length);
@@ -64,7 +64,7 @@ function testArrayMirror(a, names) {
   assertEquals('Array', fromJSON.className);
   assertEquals('function', fromJSON.constructorFunction.type);
   assertEquals('Array', fromJSON.constructorFunction.name);
-  assertEquals(a.length, fromJSON.length);
+  assertEquals(a.length, fromJSON.length, "Length mismatch in parsed JSON");
 
   // Check that the serialization contains all indexed properties.
   for (var i = 0; i < fromJSON.indexedProperties.length; i++) {
index c6e7a4e..43ff50f 100644 (file)
@@ -31,7 +31,6 @@
 function testFunctionMirror(f) {
   // Create mirror and JSON representation.
   var mirror = debug.MakeMirror(f);
-  print(mirror.toJSONProtocol(true));
   var json = mirror.toJSONProtocol(true);
 
   // Check the mirror hierachy.
index bbaf044..ff896fc 100644 (file)
@@ -119,7 +119,7 @@ function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) {
         found = true;
       }
     }
-    assertTrue(found, '"' + name + '" not found');
+    assertTrue(found, '"' + name + '" not found (' + json + ')');
   }
 }
 
@@ -139,6 +139,11 @@ testObjectMirror(this, 'global', undefined, true);  // Global object has special
 testObjectMirror([], 'Array', 'Array');
 testObjectMirror([1,2], 'Array', 'Array');
 
+// Test circular references.
+o = {};
+o.o = o;
+testObjectMirror(o, 'Object', 'Object');
+
 // Test that non enumerable properties are part of the mirror
 global_mirror = debug.MakeMirror(this);
 assertEquals('property', global_mirror.property("Math").type());
diff --git a/test/mjsunit/mirror-script.js b/test/mjsunit/mirror-script.js
new file mode 100644 (file)
index 0000000..0034829
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-debug-as debug
+// Test the mirror object for scripts.
+
+function testScriptMirror(f, file_name, file_lines, script_type) {
+  // Create mirror and JSON representation.
+  var mirror = debug.MakeMirror(f).script();
+  var json = mirror.toJSONProtocol(true);
+  print(json);
+
+  // Check the mirror hierachy.
+  assertTrue(mirror instanceof debug.Mirror);
+  assertFalse(mirror instanceof debug.ValueMirror);
+  assertTrue(mirror instanceof debug.ScriptMirror);
+
+  // Check the mirror properties.
+  assertTrue(mirror.isScript());
+  assertEquals('script', mirror.type());
+  var name = mirror.name();
+  assertEquals(file_name, name.substring(name.length - file_name.length));
+  assertEquals(0, mirror.lineOffset());
+  assertEquals(0, mirror.columnOffset());
+  if (file_lines > 0) {
+    assertEquals(file_lines, mirror.lineCount());
+  }
+  assertEquals(script_type, mirror.scriptType());
+  
+  // Parse JSON representation and check.
+  var fromJSON = eval('(' + json + ')');
+  assertEquals('script', fromJSON.type);
+  name = fromJSON.name;
+  assertEquals(file_name, name.substring(name.length - file_name.length));
+  assertEquals(0, fromJSON.lineOffset);
+  assertEquals(0, fromJSON.columnOffset);
+  if (file_lines > 0) {
+    assertEquals(file_lines, fromJSON.lineCount);
+  }
+  assertEquals(script_type, fromJSON.scriptType);  
+}
+
+
+// Test the script mirror for different functions.
+testScriptMirror(function(){}, 'mirror-script.js', 70, 2);
+testScriptMirror(Math.sin, 'native math.js', -1, 0);
index 451f8f1..0a382d3 100644 (file)
@@ -28,6 +28,8 @@
 // Flags: --expose-debug-as debug
 // Test the mirror object for string values
 
+const kMaxProtocolStringLength = 80; // Constant from mirror-delay.js
+
 function testStringMirror(s) {
   // Create mirror and JSON representation.
   var mirror = debug.MakeMirror(s);
@@ -44,16 +46,26 @@ function testStringMirror(s) {
   assertTrue(mirror.isPrimitive());
 
   // Test text representation
-  assertEquals(s, mirror.toText());
+  if (s.length <= kMaxProtocolStringLength) {
+    assertEquals(s, mirror.toText());
+  } else {
+    assertEquals(s.substring(0, kMaxProtocolStringLength),
+                 mirror.toText().substring(0, kMaxProtocolStringLength));
+  }
 
   // Parse JSON representation and check.
   var fromJSON = eval('(' + json + ')');
   assertEquals('string', fromJSON.type);
-  assertEquals(s, fromJSON.value);
+  if (s.length <= kMaxProtocolStringLength) {
+    assertEquals(s, fromJSON.value);
+  } else {
+    assertEquals(s.substring(0, kMaxProtocolStringLength),
+                 fromJSON.value.substring(0, kMaxProtocolStringLength));
+    assertEquals(fromJSON.fromIndex, 0);
+    assertEquals(fromJSON.toIndex, kMaxProtocolStringLength);
+  }
 }
 
-Number =2;
-
 // Test a number of different strings.
 testStringMirror('');
 testStringMirror('abcdABCD');
@@ -67,3 +79,10 @@ testStringMirror('\\');
 testStringMirror('\b\t\n\f\r');
 testStringMirror('\u0001\u0002\u001E\u001F');
 testStringMirror('"a":1,"b":2');
+
+var s = "1234567890"
+s = s + s + s + s + s + s + s + s;
+assertEquals(kMaxProtocolStringLength, s.length);
+testStringMirror(s);
+s = s + 'X';
+testStringMirror(s);