Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(917)

Unified Diff: src/runtime.cc

Issue 11415051: Revert r12990 and r12991 from trunk. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects-inl.h ('k') | src/version.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index b16c6855974a59660f07d854677a0fc7a7485beb..567a90ba7689d6543f06e6aa566c7f32dfe552bc 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -977,109 +977,97 @@ static void GetOwnPropertyImplementation(JSObject* obj,
Object* proto = obj->GetPrototype();
if (proto->IsJSObject() &&
- JSObject::cast(proto)->map()->is_hidden_prototype()) {
+ JSObject::cast(proto)->map()->is_hidden_prototype())
GetOwnPropertyImplementation(JSObject::cast(proto),
name, result);
- }
}
-static bool CheckAccessException(Object* callback,
+static bool CheckAccessException(LookupResult* result,
v8::AccessType access_type) {
- if (callback->IsAccessorInfo()) {
- AccessorInfo* info = AccessorInfo::cast(callback);
- return
- (access_type == v8::ACCESS_HAS &&
- (info->all_can_read() || info->all_can_write())) ||
- (access_type == v8::ACCESS_GET && info->all_can_read()) ||
- (access_type == v8::ACCESS_SET && info->all_can_write());
- }
- return false;
-}
-
-
-template<class Key>
-static bool CheckGenericAccess(
- JSObject* receiver,
- JSObject* holder,
- Key key,
- v8::AccessType access_type,
- bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) {
- Isolate* isolate = receiver->GetIsolate();
- for (JSObject* current = receiver;
- true;
- current = JSObject::cast(current->GetPrototype())) {
- if (current->IsAccessCheckNeeded() &&
- !(isolate->*mayAccess)(current, key, access_type)) {
- return false;
+ if (result->type() == CALLBACKS) {
+ Object* callback = result->GetCallbackObject();
+ if (callback->IsAccessorInfo()) {
+ AccessorInfo* info = AccessorInfo::cast(callback);
+ bool can_access =
+ (access_type == v8::ACCESS_HAS &&
+ (info->all_can_read() || info->all_can_write())) ||
+ (access_type == v8::ACCESS_GET && info->all_can_read()) ||
+ (access_type == v8::ACCESS_SET && info->all_can_write());
+ return can_access;
}
- if (current == holder) break;
- }
- return true;
-}
-
-
-static bool CheckElementAccess(
- JSObject* obj,
- uint32_t index,
- v8::AccessType access_type) {
- // TODO(1095): we should traverse hidden prototype hierachy as well.
- if (CheckGenericAccess(
- obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
- return true;
}
- obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
return false;
}
-static bool CheckPropertyAccess(
- JSObject* obj,
- String* name,
- v8::AccessType access_type) {
- uint32_t index;
- if (name->AsArrayIndex(&index)) {
- return CheckElementAccess(obj, index, access_type);
- }
+static bool CheckAccess(JSObject* obj,
+ String* name,
+ LookupResult* result,
+ v8::AccessType access_type) {
+ ASSERT(result->IsProperty());
- LookupResult lookup(obj->GetIsolate());
- obj->LocalLookup(name, &lookup);
+ JSObject* holder = result->holder();
+ JSObject* current = obj;
+ Isolate* isolate = obj->GetIsolate();
+ while (true) {
+ if (current->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(current, name, access_type)) {
+ // Access check callback denied the access, but some properties
+ // can have a special permissions which override callbacks descision
+ // (currently see v8::AccessControl).
+ break;
+ }
+
+ if (current == holder) {
+ return true;
+ }
- if (CheckGenericAccess<Object*>(
- obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) {
- return true;
+ current = JSObject::cast(current->GetPrototype());
}
- // Access check callback denied the access, but some properties
- // can have a special permissions which override callbacks descision
- // (currently see v8::AccessControl).
// API callbacks can have per callback access exceptions.
- switch (lookup.type()) {
- case CALLBACKS:
- if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
+ switch (result->type()) {
+ case CALLBACKS: {
+ if (CheckAccessException(result, access_type)) {
return true;
}
break;
- case INTERCEPTOR:
+ }
+ case INTERCEPTOR: {
// If the object has an interceptor, try real named properties.
// Overwrite the result to fetch the correct property later.
- lookup.holder()->LookupRealNamedProperty(name, &lookup);
- if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
- if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
+ holder->LookupRealNamedProperty(name, result);
+ if (result->IsProperty()) {
+ if (CheckAccessException(result, access_type)) {
return true;
}
}
break;
+ }
default:
break;
}
- obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
+ isolate->ReportFailedAccessCheck(current, access_type);
return false;
}
+// TODO(1095): we should traverse hidden prototype hierachy as well.
+static bool CheckElementAccess(JSObject* obj,
+ uint32_t index,
+ v8::AccessType access_type) {
+ if (obj->IsAccessCheckNeeded() &&
+ !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
+ return false;
+ }
+
+ return true;
+}
+
+
// Enumerator used as indices into the array returned from GetOwnProperty
enum PropertyDescriptorIndices {
IS_ACCESSOR_INDEX,
@@ -1097,33 +1085,141 @@ static MaybeObject* GetOwnProperty(Isolate* isolate,
Handle<JSObject> obj,
Handle<String> name) {
Heap* heap = isolate->heap();
- PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
- if (attrs == ABSENT) return heap->undefined_value();
- AccessorPair* accessors = obj->GetLocalPropertyAccessorPair(*name);
-
Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
- elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
- elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
- elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(accessors != NULL));
-
- if (accessors == NULL) {
- elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
- // GetProperty does access check.
- elms->set(VALUE_INDEX, *GetProperty(obj, name));
- } else {
- // Access checks are performed for both accessors separately.
- // When they fail, the respective field is not set in the descriptor.
+ Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
+ LookupResult result(isolate);
+ // This could be an element.
+ uint32_t index;
+ if (name->AsArrayIndex(&index)) {
+ switch (obj->GetLocalElementKind(index)) {
+ case JSObject::UNDEFINED_ELEMENT:
+ return heap->undefined_value();
+
+ case JSObject::STRING_CHARACTER_ELEMENT: {
+ // 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.
+ Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
+ Handle<String> str(String::cast(js_value->value()));
+ Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
+
+ elms->set(IS_ACCESSOR_INDEX, heap->false_value());
+ elms->set(VALUE_INDEX, *substr);
+ elms->set(WRITABLE_INDEX, heap->false_value());
+ elms->set(ENUMERABLE_INDEX, heap->true_value());
+ elms->set(CONFIGURABLE_INDEX, heap->false_value());
+ return *desc;
+ }
+
+ case JSObject::INTERCEPTED_ELEMENT:
+ case JSObject::FAST_ELEMENT: {
+ elms->set(IS_ACCESSOR_INDEX, heap->false_value());
+ Handle<Object> value = Object::GetElement(obj, index);
+ RETURN_IF_EMPTY_HANDLE(isolate, value);
+ elms->set(VALUE_INDEX, *value);
+ elms->set(WRITABLE_INDEX, heap->true_value());
+ elms->set(ENUMERABLE_INDEX, heap->true_value());
+ elms->set(CONFIGURABLE_INDEX, heap->true_value());
+ return *desc;
+ }
+
+ case JSObject::DICTIONARY_ELEMENT: {
+ Handle<JSObject> holder = obj;
+ if (obj->IsJSGlobalProxy()) {
+ Object* proto = obj->GetPrototype();
+ if (proto->IsNull()) return heap->undefined_value();
+ ASSERT(proto->IsJSGlobalObject());
+ holder = Handle<JSObject>(JSObject::cast(proto));
+ }
+ FixedArray* elements = FixedArray::cast(holder->elements());
+ SeededNumberDictionary* dictionary = NULL;
+ if (elements->map() == heap->non_strict_arguments_elements_map()) {
+ dictionary = SeededNumberDictionary::cast(elements->get(1));
+ } else {
+ dictionary = SeededNumberDictionary::cast(elements);
+ }
+ int entry = dictionary->FindEntry(index);
+ ASSERT(entry != SeededNumberDictionary::kNotFound);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ switch (details.type()) {
+ case CALLBACKS: {
+ // This is an accessor property with getter and/or setter.
+ AccessorPair* accessors =
+ AccessorPair::cast(dictionary->ValueAt(entry));
+ elms->set(IS_ACCESSOR_INDEX, heap->true_value());
+ if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
+ elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
+ }
+ if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
+ elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
+ }
+ break;
+ }
+ case NORMAL: {
+ // This is a data property.
+ elms->set(IS_ACCESSOR_INDEX, heap->false_value());
+ Handle<Object> value = Object::GetElement(obj, index);
+ ASSERT(!value.is_null());
+ elms->set(VALUE_INDEX, *value);
+ elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
+ elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
+ return *desc;
+ }
+ }
+ }
+
+ // Use recursive implementation to also traverse hidden prototypes
+ GetOwnPropertyImplementation(*obj, *name, &result);
+
+ if (!result.IsProperty()) {
+ return heap->undefined_value();
+ }
+
+ if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
+ return heap->false_value();
+ }
+
+ elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
+ elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
+
+ bool is_js_accessor = result.IsPropertyCallbacks() &&
+ (result.GetCallbackObject()->IsAccessorPair());
+
+ if (is_js_accessor) {
+ // __defineGetter__/__defineSetter__ callback.
+ elms->set(IS_ACCESSOR_INDEX, heap->true_value());
+
+ AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
- Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
- if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) {
+ if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
elms->set(GETTER_INDEX, getter);
}
- if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) {
+ Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
+ if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
elms->set(SETTER_INDEX, setter);
}
+ } else {
+ elms->set(IS_ACCESSOR_INDEX, heap->false_value());
+ elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
+
+ PropertyAttributes attrs;
+ Object* value;
+ // GetProperty will check access and report any violations.
+ { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ }
+ elms->set(VALUE_INDEX, value);
}
- return *isolate->factory()->NewJSArrayWithElements(elms);
+ return *desc;
}
@@ -4631,6 +4727,41 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
CONVERT_ARG_CHECKED(JSObject, object, 0);
CONVERT_ARG_CHECKED(String, key, 1);
+ uint32_t index;
+ if (key->AsArrayIndex(&index)) {
+ JSObject::LocalElementKind type = object->GetLocalElementKind(index);
+ switch (type) {
+ case JSObject::UNDEFINED_ELEMENT:
+ case JSObject::STRING_CHARACTER_ELEMENT:
+ return isolate->heap()->false_value();
+ case JSObject::INTERCEPTED_ELEMENT:
+ case JSObject::FAST_ELEMENT:
+ return isolate->heap()->true_value();
+ case JSObject::DICTIONARY_ELEMENT: {
+ if (object->IsJSGlobalProxy()) {
+ Object* proto = object->GetPrototype();
+ if (proto->IsNull()) {
+ return isolate->heap()->false_value();
+ }
+ ASSERT(proto->IsJSGlobalObject());
+ object = JSObject::cast(proto);
+ }
+ FixedArray* elements = FixedArray::cast(object->elements());
+ SeededNumberDictionary* dictionary = NULL;
+ if (elements->map() ==
+ isolate->heap()->non_strict_arguments_elements_map()) {
+ dictionary = SeededNumberDictionary::cast(elements->get(1));
+ } else {
+ dictionary = SeededNumberDictionary::cast(elements);
+ }
+ int entry = dictionary->FindEntry(index);
+ ASSERT(entry != SeededNumberDictionary::kNotFound);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ return isolate->heap()->ToBoolean(!details.IsDontEnum());
+ }
+ }
+ }
+
PropertyAttributes att = object->GetLocalPropertyAttribute(key);
return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
}
« no previous file with comments | « src/objects-inl.h ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698