Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 4722) |
+++ src/runtime.cc (working copy) |
@@ -569,6 +569,18 @@ |
} |
+// Enumerator used as indices into the array returned from GetOwnProperty |
+enum PropertyDescriptorIndices { |
+ IS_ACCESSOR_INDEX, |
+ VALUE_INDEX, |
+ GETTER_INDEX, |
+ SETTER_INDEX, |
+ WRITABLE_INDEX, |
+ ENUMERABLE_INDEX, |
+ CONFIGURABLE_INDEX, |
+ DESCRIPTOR_SIZE |
+}; |
+ |
// Returns an array with the property description: |
// if args[1] is not a property on args[0] |
// returns undefined |
@@ -579,18 +591,63 @@ |
static Object* Runtime_GetOwnProperty(Arguments args) { |
ASSERT(args.length() == 2); |
HandleScope scope; |
- Handle<FixedArray> elms = Factory::NewFixedArray(5); |
+ Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE); |
Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms); |
LookupResult result; |
CONVERT_CHECKED(JSObject, obj, args[0]); |
CONVERT_CHECKED(String, name, args[1]); |
+ // This could be an element. |
+ uint32_t index; |
+ if (name->AsArrayIndex(&index)) { |
+ if (!obj->HasLocalElement(index)) { |
+ return Heap::undefined_value(); |
+ } |
+ |
+ // Special handling of string objects according to ECMAScript 5 15.5.5.2. |
+ // Note that this might be a string object with elements other than the |
+ // actual string value. This is covered by the subsequent cases. |
+ if (obj->IsStringObjectWithCharacterAt(index)) { |
+ JSValue* js_value = JSValue::cast(obj); |
+ String* str = String::cast(js_value->value()); |
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
+ elms->set(VALUE_INDEX, str->SubString(index, index+1)); |
+ elms->set(WRITABLE_INDEX, Heap::false_value()); |
+ elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
+ elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
+ return *desc; |
+ } |
+ |
+ // This can potentially be an element in the elements dictionary or |
+ // a fast element. |
+ if (obj->HasDictionaryElements()) { |
+ NumberDictionary* dictionary = obj->element_dictionary(); |
+ int entry = dictionary->FindEntry(index); |
+ PropertyDetails details = dictionary->DetailsAt(entry); |
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
+ elms->set(VALUE_INDEX, dictionary->ValueAt(entry)); |
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
+ elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
+ elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); |
+ return *desc; |
+ } else { |
+ // Elements that are stored as array elements always has: |
+ // writable: true, configurable: true, enumerable: true. |
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
+ elms->set(VALUE_INDEX, obj->GetElement(index)); |
+ elms->set(WRITABLE_INDEX, Heap::true_value()); |
+ elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
+ elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
+ return *desc; |
+ } |
+ } |
+ |
// Use recursive implementation to also traverse hidden prototypes |
GetOwnPropertyImplementation(obj, name, &result); |
- if (!result.IsProperty()) |
+ if (!result.IsProperty()) { |
return Heap::undefined_value(); |
- |
+ } |
if (result.type() == CALLBACKS) { |
Object* structure = result.GetCallbackObject(); |
if (structure->IsProxy() || structure->IsAccessorInfo()) { |
@@ -598,25 +655,25 @@ |
// an API defined callback. |
Object* value = obj->GetPropertyWithCallback( |
obj, structure, name, result.holder()); |
- elms->set(0, Heap::false_value()); |
- elms->set(1, value); |
- elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); |
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
+ elms->set(VALUE_INDEX, value); |
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
} else if (structure->IsFixedArray()) { |
// __defineGetter__/__defineSetter__ callback. |
- elms->set(0, Heap::true_value()); |
- elms->set(1, FixedArray::cast(structure)->get(0)); |
- elms->set(2, FixedArray::cast(structure)->get(1)); |
+ elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
+ elms->set(GETTER_INDEX, FixedArray::cast(structure)->get(0)); |
+ elms->set(SETTER_INDEX, FixedArray::cast(structure)->get(1)); |
} else { |
return Heap::undefined_value(); |
} |
} else { |
- elms->set(0, Heap::false_value()); |
- elms->set(1, result.GetLazyValue()); |
- elms->set(2, Heap::ToBoolean(!result.IsReadOnly())); |
+ elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
+ elms->set(VALUE_INDEX, result.GetLazyValue()); |
+ elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); |
} |
- elms->set(3, Heap::ToBoolean(!result.IsDontEnum())); |
- elms->set(4, Heap::ToBoolean(!result.IsDontDelete())); |
+ elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!result.IsDontEnum())); |
+ elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!result.IsDontDelete())); |
return *desc; |
} |