| Index: src/runtime.cc | 
| =================================================================== | 
| --- src/runtime.cc	(revision 3785) | 
| +++ src/runtime.cc	(working copy) | 
| @@ -596,8 +596,9 @@ | 
|  | 
| if (result.type() == CALLBACKS) { | 
| Object* structure = result.GetCallbackObject(); | 
| -    if (structure->IsProxy()) { | 
| -      // Property that is internally implemented as a callback. | 
| +    if (structure->IsProxy() || structure->IsAccessorInfo()) { | 
| +      // Property that is internally implemented as a callback or | 
| +      // an API defined callback. | 
| Object* value = obj->GetPropertyWithCallback( | 
| obj, structure, name, result.holder()); | 
| elms->set(0, Heap::false_value()); | 
| @@ -609,7 +610,6 @@ | 
| elms->set(1, FixedArray::cast(structure)->get(0)); | 
| elms->set(2, FixedArray::cast(structure)->get(1)); | 
| } else { | 
| -      // TODO(ricow): Handle API callbacks. | 
| return Heap::undefined_value(); | 
| } | 
| } else { | 
| @@ -619,7 +619,7 @@ | 
| } | 
|  | 
| elms->set(3, Heap::ToBoolean(!result.IsDontEnum())); | 
| -  elms->set(4, Heap::ToBoolean(!result.IsReadOnly())); | 
| +  elms->set(4, Heap::ToBoolean(!result.IsDontDelete())); | 
| return *desc; | 
| } | 
|  | 
| @@ -2888,6 +2888,66 @@ | 
| } | 
|  | 
|  | 
| +static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { | 
| +  ASSERT(args.length() == 5); | 
| +  HandleScope scope; | 
| +  Handle<JSObject> obj = args.at<JSObject>(0); | 
| +  CONVERT_CHECKED(String, name, args[1]); | 
| +  CONVERT_CHECKED(Smi, flag_setter, args[2]); | 
| +  CONVERT_CHECKED(JSFunction, fun, args[3]); | 
| +  CONVERT_CHECKED(Smi, flag_attr, args[4]); | 
| +  int unchecked = flag_attr->value(); | 
| +  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 
| + | 
| +  LookupResult result; | 
| +  obj->LocalLookupRealNamedProperty(name, &result); | 
| + | 
| +  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 
| +  // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION | 
| +  // delete it to avoid running into trouble in DefineAccessor, which | 
| +  // handles this incorrectly if the property is readonly (does nothing) | 
| +  if (result.type() == FIELD || result.type() == NORMAL | 
| +      || result.type() == CONSTANT_FUNCTION) | 
| +    obj->DeleteProperty(name, JSObject::NORMAL_DELETION); | 
| + | 
| +  return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); | 
| +} | 
| + | 
| +static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { | 
| +  ASSERT(args.length() == 4); | 
| +  HandleScope scope; | 
| +  Handle<Object> obj = args.at<Object>(0); | 
| +  Handle<Object> name = args.at<Object>(1); | 
| +  Handle<Object> obj_value = args.at<Object>(2); | 
| +  Handle<JSObject> js_object = Handle<JSObject>::cast(obj); | 
| +  Handle<String> key_string = Handle<String>::cast(name); | 
| + | 
| +  CONVERT_CHECKED(Smi, flag, args[3]); | 
| +  int unchecked = flag->value(); | 
| +  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 
| + | 
| +  LookupResult result; | 
| +  js_object->LocalLookupRealNamedProperty(*key_string, &result); | 
| + | 
| +  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 
| + | 
| +  // Take special care when attributes are different and there is already | 
| +  // a property. For simplicity we normalize the property which enables us | 
| +  // to not worry about changing the instance_descriptor and creating a new | 
| +  // map. The current version of SetObjectProperty does not handle attributes | 
| +  // correctly in the case where a property is a field and is reset with | 
| +  // new attributes. | 
| +  if (result.IsProperty() && attr != result.GetAttributes()) { | 
| +    PropertyDetails details = PropertyDetails(attr, NORMAL); | 
| +    // New attributes - normalize to avoid writing to instance descriptor | 
| +    js_object->NormalizeProperties(KEEP_INOBJECT_PROPERTIES, 0); | 
| +    return js_object->SetNormalizedProperty(*key_string, *obj_value, details); | 
| +  } | 
| + | 
| +  return Runtime::SetObjectProperty(js_object, name, obj_value, attr); | 
| +} | 
| + | 
| + | 
| Object* Runtime::SetObjectProperty(Handle<Object> object, | 
| Handle<Object> key, | 
| Handle<Object> value, | 
|  |