Refactored the mirror representation of properties. Removed the AssessorMirror and...
authorsgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Jan 2009 14:38:44 +0000 (14:38 +0000)
committersgjesse@chromium.org <sgjesse@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 13 Jan 2009 14:38:44 +0000 (14:38 +0000)
Properties from interceptors are also reflected through PropertyMirror as the distinction did not make sense seen from a JavaScript debugging perspective. The isNative function on a PropertyMirror can be used to check whether a property is defined natively by the host (or V8).

Simplified the local property lookup in the debug runtime call to just call GetProperty as the property is known to be a local property.
Review URL: http://codereview.chromium.org/17377

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

src/mirror-delay.js
src/runtime.cc
test/cctest/test-debug.cc
test/mjsunit/mirror-object.js

index e7ff9107115b7866e9c7001b5c48982a2d6d9e80..7e25501e0dcc5f4b915473ca2adc9b383ebb226b 100644 (file)
@@ -135,8 +135,6 @@ PropertyAttribute.DontDelete = DONT_DELETE;
 //         - RegExpMirror
 //         - ErrorMirror
 //     - PropertyMirror
-//       - InterceptorPropertyMirror
-//     - AccessorMirror
 //     - FrameMirror
 //     - ScriptMirror
 
@@ -273,25 +271,6 @@ Mirror.prototype.isProperty = function() {
 }
 
 
-/**
- * Check whether the mirror reflects a property from an interceptor.
- * @returns {boolean} True if the mirror reflects a property from an
- *     interceptor
- */
-Mirror.prototype.isInterceptorProperty = function() {
-  return this instanceof InterceptorPropertyMirror;
-}
-
-
-/**
- * Check whether the mirror reflects an accessor.
- * @returns {boolean} True if the mirror reflects an accessor
- */
-Mirror.prototype.isAccessor = function() {
-  return this instanceof AccessorMirror;
-}
-
-
 /**
  * Check whether the mirror reflects a stack frame.
  * @returns {boolean} True if the mirror reflects a stack frame
@@ -519,13 +498,39 @@ ObjectMirror.prototype.propertyNames = function(kind, limit) {
   var propertyNames;
   var elementNames;
   var total = 0;
+  
+  // Find all the named properties.
   if (kind & PropertyKind.Named) {
+    // Get the local property names.
     propertyNames = %DebugLocalPropertyNames(this.value_);
     total += propertyNames.length;
+
+    // Get names for named interceptor properties if any.
+    if (this.hasNamedInterceptor() && (kind & PropertyKind.Named)) {
+      var namedInterceptorNames =
+          %DebugNamedInterceptorPropertyNames(this.value_);
+      if (namedInterceptorNames) {
+        propertyNames = propertyNames.concat(namedInterceptorNames);
+        total += namedInterceptorNames.length;
+      }
+    }
   }
+
+  // Find all the indexed properties.
   if (kind & PropertyKind.Indexed) {
-    elementNames = %DebugLocalElementNames(this.value_)
+    // Get the local element names.
+    elementNames = %DebugLocalElementNames(this.value_);
     total += elementNames.length;
+
+    // Get names for indexed interceptor properties.
+    if (this.hasIndexedInterceptor() && (kind & PropertyKind.Indexed)) {
+      var indexedInterceptorNames =
+          %DebugIndexedInterceptorElementNames(this.value_);
+      if (indexedInterceptorNames) {
+        elementNames = elementNames.concat(indexedInterceptorNames);
+        total += indexedInterceptorNames.length;
+      }
+    }
   }
   limit = Math.min(limit || total, total);
 
@@ -569,95 +574,10 @@ ObjectMirror.prototype.properties = function(kind, limit) {
 };
 
 
-/**
- * Return the interceptor property names for this object.
- * @param {number} kind Indicate whether named, indexed or both kinds of
- *     interceptor properties are requested
- * @param {number} limit Limit the number of names returend to the specified
-       value
- * @return {Array} interceptor property names for this object
- */
-ObjectMirror.prototype.interceptorPropertyNames = function(kind, limit) {
-  // Find kind.
-  kind = kind || PropertyKind.Named | PropertyKind.Indexed;
-  var namedInterceptorNames;
-  var indexedInterceptorNames;
-
-  // Get names for named interceptor properties.
-  if (this.hasNamedInterceptor() && kind & PropertyKind.Named) {
-    namedInterceptorNames = %DebugNamedInterceptorPropertyNames(this.value_);
-  }
-
-  // Get names for indexed interceptor properties.
-  if (this.hasIndexedInterceptor() && kind & PropertyKind.Indexed) {
-    indexedInterceptorNames = %DebugIndexedInterceptorElementNames(this.value_);
-  }
-
-  // Return either retult or both concattenated.
-  if (namedInterceptorNames && indexedInterceptorNames) {
-    return namedInterceptorNames.concat(indexedInterceptorNames);
-  } else if (namedInterceptorNames) {
-    return namedInterceptorNames;
-  } else if (indexedInterceptorNames) {
-    return indexedInterceptorNames;
-  } else {
-    return new Array(0);
-  }
-};
-
-
-/**
- * Return interceptor properties this object.
- * @param {number} opt_kind Indicate whether named, indexed or both kinds of
- *     interceptor properties are requested
- * @param {Array} opt_names Limit the number of properties returned to the
-       specified value
- * @return {Array} properties this object as an array of PropertyMirror objects
- */
-ObjectMirror.prototype.interceptorProperties = function(opt_kind, opt_names) {
-  // Find kind.
-  var kind = opt_kind || PropertyKind.Named | PropertyKind.Indexed;
-  var namedInterceptorProperties;
-  var indexedInterceptorProperties;
-
-  // Get values for named interceptor properties.
-  if (kind & PropertyKind.Named) {
-    var names = opt_names || this.interceptorPropertyNames(PropertyKind.Named);
-    namedInterceptorProperties = new Array(names.length);
-    for (i = 0; i < names.length; i++) {
-      var value = %DebugNamedInterceptorPropertyValue(this.value_, names[i]);
-      namedInterceptorProperties[i] = new InterceptorPropertyMirror(this, names[i], value);
-    }
-  }
-
-  // Get values for indexed interceptor properties.
-  if (kind & PropertyKind.Indexed) {
-    var names = opt_names || this.interceptorPropertyNames(PropertyKind.Indexed);
-    indexedInterceptorProperties = new Array(names.length);
-    for (i = 0; i < names.length; i++) {
-      // Don't try to get the value if the name is not a number.
-      if (IS_NUMBER(names[i])) {
-        var value = %DebugIndexedInterceptorElementValue(this.value_, names[i]);
-        indexedInterceptorProperties[i] = new InterceptorPropertyMirror(this, names[i], value);
-      }
-    }
-  }
-
-  // Return either result or both concattenated.
-  if (namedInterceptorProperties && indexedInterceptorProperties) {
-    return namedInterceptorProperties.concat(indexedInterceptorProperties);
-  } else if (namedInterceptorProperties) {
-    return namedInterceptorProperties;
-  } else {
-    return indexedInterceptorProperties;
-  }
-};
-
-
 ObjectMirror.prototype.property = function(name) {
   var details = %DebugGetPropertyDetails(this.value_, %ToString(name));
   if (details) {
-    return new PropertyMirror(this, name, details[0], details[1]);
+    return new PropertyMirror(this, name, details);
   }
 
   // Nothing found.
@@ -893,7 +813,7 @@ ArrayMirror.prototype.indexedPropertiesFromRange = function(opt_from_index, opt_
     var details = %DebugGetPropertyDetails(this.value_, %ToString(i));
     var value;
     if (details) {
-      value = new PropertyMirror(this, i, details[0], details[1]);
+      value = new PropertyMirror(this, i, details);
     } else {
       value = new UndefinedMirror();
     }
@@ -1011,16 +931,21 @@ ErrorMirror.prototype.toText = function() {
  * Base mirror object for properties.
  * @param {ObjectMirror} mirror The mirror object having this property
  * @param {string} name The name of the property
- * @param {Object} value The value of the property
+ * @param {Array} details Details about the property
  * @constructor
  * @extends Mirror
  */
-function PropertyMirror(mirror, name, value, details) {
+function PropertyMirror(mirror, name, details) {
   Mirror.call(this, PROPERTY_TYPE);
   this.mirror_ = mirror;
   this.name_ = name;
-  this.value_ = value;
-  this.details_ = details;
+  this.value_ = details[0];
+  this.details_ = details[1];
+  if (details.length > 2) {
+    this.exception_ = details[2]
+    this.getter_ = details[3];
+    this.setter_ = details[4];
+  }
 }
 inherits(PropertyMirror, Mirror);
 
@@ -1056,14 +981,16 @@ PropertyMirror.prototype.isIndexed = function() {
 
 
 PropertyMirror.prototype.value = function() {
-  if (this.propertyType() == PropertyType.Callbacks) {
-    // TODO(1242933): AccessorMirror should have getter/setter values.
-    return new AccessorMirror();
-  } else if (this.type() == PropertyType.Interceptor) {
-    return new UndefinedMirror();
-  } else {
-    return MakeMirror(this.value_);
-  }
+  return MakeMirror(this.value_);
+}
+
+
+/**
+ * Returns whether this property value is an exception.
+ * @return {booolean} True if this property value is an exception
+ */
+PropertyMirror.prototype.isException = function() {
+  return this.exception_ ? true : false;
 }
 
 
@@ -1083,62 +1010,61 @@ PropertyMirror.prototype.insertionIndex = function() {
 
 
 /**
- * Mirror object for interceptor named properties.
- * @param {ObjectMirror} mirror The mirror object having this property
- * @param {String} name The name of the property
- * @param {value} value The value of the property
- * @constructor
- * @extends PropertyMirror
+ * Returns whether this property has a getter defined through __defineGetter__.
+ * @return {booolean} True if this property has a getter
  */
-function InterceptorPropertyMirror(mirror, name, value) {
-  PropertyMirror.call(this, mirror, name, value, PropertyType.Interceptor);
+PropertyMirror.prototype.hasGetter = function() {
+  return this.getter_ ? true : false;
 }
-inherits(InterceptorPropertyMirror, PropertyMirror);
 
 
 /**
- * Mirror object for property accessors.
- * @param {Function} getter The getter function for this accessor
- * @param {Function} setter The setter function for this accessor
- * @constructor
- * @extends Mirror
+ * Returns whether this property has a setter defined through __defineSetter__.
+ * @return {booolean} True if this property has a setter
  */
-function AccessorMirror(getter, setter) {
-  Mirror.call(this, ACCESSOR_TYPE);
-  this.getter_ = getter;
-  this.setter_ = setter;
+PropertyMirror.prototype.hasSetter = function() {
+  return this.setter_ ? true : false;
 }
-inherits(AccessorMirror, Mirror);
 
 
 /**
- * Returns whether this accessor is native or not. A native accessor is either
- * a VM buildin or provided through the API. A non native accessor is defined
- * in JavaScript using the __defineGetter__ and/or __defineGetter__ functions.
- * @return {boolean} True is the accessor is native
+ * Returns the getter for this property defined through __defineGetter__.
+ * @return {Mirror} FunctionMirror reflecting the getter function or
+ *     UndefinedMirror if there is no getter for this property
  */
-AccessorMirror.prototype.isNative = function() {
-  return IS_UNDEFINED(this.getter_) && IS_UNDEFINED(this.setter_);
+PropertyMirror.prototype.getter = function() {
+  if (this.hasGetter()) {
+    return MakeMirror(this.getter_);
+  } else {
+    return new UndefinedMirror();
+  }
 }
 
 
 /**
- * Returns a mirror for the function of a non native getter.
- * @return {FunctionMirror} Function mirror for the getter set using
- *     __defineGetter__.
+ * Returns the setter for this property defined through __defineSetter__.
+ * @return {Mirror} FunctionMirror reflecting the setter function or
+ *     UndefinedMirror if there is no setter for this property
  */
-AccessorMirror.prototype.getter = function(details) {
-  return MakeMirror(this.getter_);
+PropertyMirror.prototype.setter = function() {
+  if (this.hasSetter()) {
+    return MakeMirror(this.setter_);
+  } else {
+    return new UndefinedMirror();
+  }
 }
 
 
 /**
- * Returns a mirror for the function of a non native setter.
- * @return {FunctionMirror} Function mirror for the getter set using
- *     __defineSetter__.
+ * Returns whether this property is natively implemented by the host or a set
+ * through JavaScript code.
+ * @return {boolean} True if the property is 
+ *     UndefinedMirror if there is no setter for this property
  */
-AccessorMirror.prototype.setter = function(details) {
-  return MakeMirror(this.setter_);
+PropertyMirror.prototype.isNative = function() {
+  return (this.propertyType() == PropertyType.Interceptor) ||
+         ((this.propertyType() == PropertyType.Callbacks) &&
+          !this.hasGetter() && !this.hasSetter());
 }
 
 
@@ -1732,14 +1658,6 @@ JSONProtocolSerializer.prototype.serializeObject_ = function(mirror, content) {
     }
     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()) {
index d2b62a4226809c60fe1b93a0574ee13532e47865..326921770e932714f4b973db6615bfb0c16ae47a 100644 (file)
@@ -4503,30 +4503,32 @@ static Object* Runtime_Break(Arguments args) {
 }
 
 
-static Object* DebugLookupResultValue(LookupResult* result) {
-  Object* value;
+static Object* DebugLookupResultValue(Object* obj, String* name,
+                                      LookupResult* result,
+                                      bool* caught_exception) {
   switch (result->type()) {
-    case NORMAL: {
-      Dictionary* dict =
-          JSObject::cast(result->holder())->property_dictionary();
-      value = dict->ValueAt(result->GetDictionaryEntry());
-      if (value->IsTheHole()) {
-        return Heap::undefined_value();
-      }
-      return value;
-    }
+    case NORMAL:
     case FIELD:
-      value =
-          JSObject::cast(
-              result->holder())->FastPropertyAt(result->GetFieldIndex());
-      if (value->IsTheHole()) {
-        return Heap::undefined_value();
+    case CONSTANT_FUNCTION:
+      return obj->GetProperty(name);
+    case CALLBACKS: {
+      // Get the property value. If there is an exception it must be thown from
+      // a JavaScript getter.
+      Object* value;
+      value = obj->GetProperty(name);
+      if (value->IsException()) {
+        if (caught_exception != NULL) {
+          *caught_exception = true;
+        }
+        value = Top::pending_exception();
+        Top::optional_reschedule_exception(true);
       }
+      ASSERT(!Top::has_pending_exception());
+      ASSERT(!Top::external_caught_exception());
       return value;
-    case CONSTANT_FUNCTION:
-      return result->GetConstantFunction();
-    case CALLBACKS:
+    }
     case INTERCEPTOR:
+      return obj->GetProperty(name);
     case MAP_TRANSITION:
     case CONSTANT_TRANSITION:
     case NULL_DESCRIPTOR:
@@ -4539,6 +4541,18 @@ static Object* DebugLookupResultValue(LookupResult* result) {
 }
 
 
+// Get debugger related details for an object property.
+// args[0]: object holding property
+// args[1]: name of the property
+//
+// The array returned contains the following information:
+// 0: Property value
+// 1: Property details
+// 2: Property value is exception
+// 3: Getter function if defined
+// 4: Setter function if defined
+// Items 2-4 are only filled if the property has either a getter or a setter
+// defined through __defineGetter__ and/or __defineSetter__.
 static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
   HandleScope scope;
 
@@ -4559,12 +4573,26 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
 
   // Perform standard local lookup on the object.
   LookupResult result;
-  obj->Lookup(*name, &result);
+  obj->LocalLookup(*name, &result);
   if (result.IsProperty()) {
-    Handle<Object> value(DebugLookupResultValue(&result));
-    Handle<FixedArray> details = Factory::NewFixedArray(2);
+    bool caught_exception = false;
+    Handle<Object> value(DebugLookupResultValue(*obj, *name, &result,
+                                                &caught_exception));
+    // If the callback object is a fixed array then it contains JavaScript
+    // getter and/or setter.
+    bool hasJavaScriptAccessors = result.type() == CALLBACKS &&
+                                  result.GetCallbackObject()->IsFixedArray();
+    Handle<FixedArray> details =
+        Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
     details->set(0, *value);
     details->set(1, result.GetPropertyDetails().AsSmi());
+    if (hasJavaScriptAccessors) {
+      details->set(2,
+                   caught_exception ? Heap::true_value() : Heap::false_value());
+      details->set(3, FixedArray::cast(result.GetCallbackObject())->get(0));
+      details->set(4, FixedArray::cast(result.GetCallbackObject())->get(1));
+    }
+
     return *Factory::NewJSArrayWithElements(details);
   }
   return Heap::undefined_value();
@@ -4582,7 +4610,7 @@ static Object* Runtime_DebugGetProperty(Arguments args) {
   LookupResult result;
   obj->Lookup(*name, &result);
   if (result.IsProperty()) {
-    return DebugLookupResultValue(&result);
+    return DebugLookupResultValue(*obj, *name, &result, NULL);
   }
   return Heap::undefined_value();
 }
@@ -4676,10 +4704,11 @@ static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
-  RUNTIME_ASSERT(obj->HasNamedInterceptor());
 
-  v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
-  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  if (obj->HasNamedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
   return Heap::undefined_value();
 }
 
@@ -4690,10 +4719,11 @@ static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
   HandleScope scope;
   ASSERT(args.length() == 1);
   CONVERT_ARG_CHECKED(JSObject, obj, 0);
-  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
 
-  v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
-  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  if (obj->HasIndexedInterceptor()) {
+    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
+    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
+  }
   return Heap::undefined_value();
 }
 
index 924eeecda93168a320a36c5a46ecb243bf652ddc..6c8c28f386a025008dd4eae6d2f501b37ce19490 100644 (file)
@@ -2660,58 +2660,76 @@ TEST(InterceptorPropertyMirror) {
 
   // Get the property names from the interceptors
   CompileRun(
-      "named_names = named_mirror.interceptorPropertyNames();"
-      "indexed_names = indexed_mirror.interceptorPropertyNames();"
-      "both_names = both_mirror.interceptorPropertyNames()");
+      "named_names = named_mirror.propertyNames();"
+      "indexed_names = indexed_mirror.propertyNames();"
+      "both_names = both_mirror.propertyNames()");
   CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
   CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
   CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
 
   // Check the expected number of properties.
   const char* source;
-  source = "named_mirror.interceptorProperties().length";
+  source = "named_mirror.properties().length";
   CHECK_EQ(3, CompileRun(source)->Int32Value());
 
-  source = "indexed_mirror.interceptorProperties().length";
+  source = "indexed_mirror.properties().length";
   CHECK_EQ(2, CompileRun(source)->Int32Value());
 
-  source = "both_mirror.interceptorProperties().length";
+  source = "both_mirror.properties().length";
   CHECK_EQ(5, CompileRun(source)->Int32Value());
 
-  source = "both_mirror.interceptorProperties(1).length";
+  // 1 is PropertyKind.Named;
+  source = "both_mirror.properties(1).length";
   CHECK_EQ(3, CompileRun(source)->Int32Value());
 
-  source = "both_mirror.interceptorProperties(2).length";
+  // 2 is PropertyKind.Indexed;
+  source = "both_mirror.properties(2).length";
   CHECK_EQ(2, CompileRun(source)->Int32Value());
 
-  source = "both_mirror.interceptorProperties(3).length";
+  // 3 is PropertyKind.Named  | PropertyKind.Indexed;
+  source = "both_mirror.properties(3).length";
   CHECK_EQ(5, CompileRun(source)->Int32Value());
 
-  // Get the interceptor properties for the object with both types of
-  // interceptors.
-  CompileRun("both_values = both_mirror.interceptorProperties()");
+  // Get the interceptor properties for the object with only named interceptor.
+  CompileRun("named_values = named_mirror.properties()");
 
-  // Check the mirror hierachy
-  source = "both_values[0] instanceof debug.PropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 3; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer,
+                 "named_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
 
-  source = "both_values[0] instanceof debug.InterceptorPropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+    // 4 is PropertyType.Interceptor
+    OS::SNPrintF(buffer, "named_values[%d].propertyType()", i);
+    CHECK_EQ(4, CompileRun(buffer.start())->Int32Value());
 
-  source = "both_values[1] instanceof debug.InterceptorPropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+    OS::SNPrintF(buffer, "named_values[%d].isNative()", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
 
-  source = "both_values[2] instanceof debug.InterceptorPropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+  // Get the interceptor properties for the object with only indexed
+  // interceptor.
+  CompileRun("indexed_values = indexed_mirror.properties()");
 
-  source = "both_values[3] instanceof debug.PropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 2; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer,
+                 "indexed_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
 
-  source = "both_values[3] instanceof debug.InterceptorPropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+  // Get the interceptor properties for the object with both types of
+  // interceptors.
+  CompileRun("both_values = both_mirror.properties()");
 
-  source = "both_values[4] instanceof debug.InterceptorPropertyMirror";
-  CHECK(CompileRun(source)->BooleanValue());
+  // Check that the properties are interceptor properties.
+  for (int i = 0; i < 5; i++) {
+    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
+    OS::SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
+    CHECK(CompileRun(buffer.start())->BooleanValue());
+  }
 
   // Check the property names.
   source = "both_values[0].name() == 'a'";
index ff896fc23baa6047cb9eb5abbfde3605ad09ab1d..5f86acdfdefa501b28f17ccf9042425a421e9daa 100644 (file)
@@ -107,8 +107,7 @@ function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) {
         } else {
           assertTrue(typeof(fromJSON.properties[i].attributes) === 'undefined');
         }
-        if (!properties[i].value() instanceof debug.AccessorMirror &&
-            properties[i].value().isPrimitive()) {
+        if (!properties[i].value().isPrimitive()) {
           // NaN is not equal to NaN.
           if (isNaN(properties[i].value().value())) {
             assertTrue(isNaN(fromJSON.properties[i].value.value));
@@ -157,27 +156,46 @@ assertFalse(math_mirror.property("E").canDelete());
 
 // Test objects with JavaScript accessors.
 o = {}
-o.__defineGetter__('a', function(){throw 'a';})
-o.__defineSetter__('b', function(){throw 'b';})
-o.__defineGetter__('c', function(){throw 'c';})
-o.__defineSetter__('c', function(){throw 'c';})
+o.__defineGetter__('a', function(){return 'a';});
+o.__defineSetter__('b', function(){});
+o.__defineGetter__('c', function(){throw 'c';});
+o.__defineSetter__('c', function(){throw 'c';});
 testObjectMirror(o, 'Object', 'Object');
 mirror = debug.MakeMirror(o);
 // a has getter but no setter.
-assertTrue(mirror.property('a').value() instanceof debug.AccessorMirror);
+assertTrue(mirror.property('a').hasGetter());
+assertFalse(mirror.property('a').hasSetter());
 assertEquals(debug.PropertyType.Callbacks, mirror.property('a').propertyType());
+assertEquals('function', mirror.property('a').getter().type());
+assertEquals('undefined', mirror.property('a').setter().type());
+assertEquals('function (){return \'a\';}', mirror.property('a').getter().source());
+assertEquals('a', mirror.property('a').value().value());
+assertFalse(mirror.property('a').isException());
 // b has setter but no getter.
-assertTrue(mirror.property('b').value() instanceof debug.AccessorMirror);
+assertFalse(mirror.property('b').hasGetter());
+assertTrue(mirror.property('b').hasSetter());
 assertEquals(debug.PropertyType.Callbacks, mirror.property('b').propertyType());
-// c has both getter and setter.
-assertTrue(mirror.property('c').value() instanceof debug.AccessorMirror);
+assertEquals('undefined', mirror.property('b').getter().type());
+assertEquals('function', mirror.property('b').setter().type());
+assertEquals('function (){}', mirror.property('b').setter().source());
+assertFalse(mirror.property('b').isException());
+// c has both getter and setter. The getter throws an exception.
+assertTrue(mirror.property('c').hasGetter());
+assertTrue(mirror.property('c').hasSetter());
 assertEquals(debug.PropertyType.Callbacks, mirror.property('c').propertyType());
+assertEquals('function', mirror.property('c').getter().type());
+assertEquals('function', mirror.property('c').setter().type());
+assertEquals('function (){throw \'c\';}', mirror.property('c').getter().source());
+assertEquals('function (){throw \'c\';}', mirror.property('c').setter().source());
+assertEquals('c', mirror.property('c').value().value());
+assertTrue(mirror.property('c').isException());
 
 // Test objects with native accessors.
 mirror = debug.MakeMirror(new String('abc'));
 assertTrue(mirror instanceof debug.ObjectMirror);
-assertTrue(mirror.property('length').value() instanceof debug.AccessorMirror);
-assertTrue(mirror.property('length').value().isNative());
+assertFalse(mirror.property('length').hasGetter());
+assertFalse(mirror.property('length').hasSetter());
+assertTrue(mirror.property('length').isNative());
 assertEquals('a', mirror.property(0).value().value());
 assertEquals('b', mirror.property(1).value().value());
 assertEquals('c', mirror.property(2).value().value());