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

Unified Diff: src/objects.cc

Issue 906463002: add support for all can read interceptors (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months 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.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index cfd18780795be70e6aa75736cf43e16ba11eb6e5..20fd66b37eb90b1f1523627350edace29096bfa9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -433,12 +433,19 @@ MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
static bool FindAllCanReadHolder(LookupIterator* it) {
- for (; it->IsFound(); it->Next()) {
+ // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
+ // which have already been checked.
+ DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
+ it->state() == LookupIterator::INTERCEPTOR);
+ for (it->Next(); it->IsFound(); it->Next()) {
if (it->state() == LookupIterator::ACCESSOR) {
- Handle<Object> accessors = it->GetAccessors();
+ auto accessors = it->GetAccessors();
if (accessors->IsAccessorInfo()) {
if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
}
+ } else if (it->state() == LookupIterator::INTERCEPTOR) {
+ auto holder = it->GetHolder<JSObject>();
+ if (holder->GetNamedInterceptor()->all_can_read()) return true;
}
}
return false;
@@ -448,10 +455,18 @@ static bool FindAllCanReadHolder(LookupIterator* it) {
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
LookupIterator* it) {
Handle<JSObject> checked = it->GetHolder<JSObject>();
- if (FindAllCanReadHolder(it)) {
- return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
- it->GetHolder<JSObject>(),
- it->GetAccessors());
+ while (FindAllCanReadHolder(it)) {
+ if (it->state() == LookupIterator::ACCESSOR) {
+ return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
+ it->GetHolder<JSObject>(),
+ it->GetAccessors());
+ }
+ DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+ auto receiver = Handle<JSObject>::cast(it->GetReceiver());
+ auto result = GetPropertyWithInterceptor(it->GetHolder<JSObject>(),
+ receiver, it->name());
+ if (it->isolate()->has_scheduled_exception()) break;
+ if (!result.is_null()) return result;
}
it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
@@ -462,8 +477,16 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
LookupIterator* it) {
Handle<JSObject> checked = it->GetHolder<JSObject>();
- if (FindAllCanReadHolder(it))
- return maybe(it->property_details().attributes());
+ while (FindAllCanReadHolder(it)) {
+ if (it->state() == LookupIterator::ACCESSOR) {
+ return maybe(it->property_details().attributes());
+ }
+ DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+ auto result = GetPropertyAttributesWithInterceptor(
+ it->GetHolder<JSObject>(), it->GetReceiver(), it->name());
+ if (it->isolate()->has_scheduled_exception()) break;
+ if (result.has_value && result.value != ABSENT) return result;
+ }
it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS);
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
Maybe<PropertyAttributes>());
@@ -550,6 +573,65 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
}
+static MaybeHandle<JSObject> FindIndexedAllCanReadHolder(
+ Isolate* isolate, Handle<JSObject> js_object,
+ PrototypeIterator::WhereToStart where_to_start) {
+ for (PrototypeIterator iter(isolate, js_object, where_to_start);
+ !iter.IsAtEnd(); iter.Advance()) {
+ auto curr = PrototypeIterator::GetCurrent(iter);
+ if (!curr->IsJSObject()) break;
+ auto obj = Handle<JSObject>::cast(curr);
+ if (!obj->HasIndexedInterceptor()) continue;
+ if (obj->GetIndexedInterceptor()->all_can_read()) return obj;
+ }
+ return MaybeHandle<JSObject>();
+}
+
+
+MaybeHandle<Object> JSObject::GetElementWithFailedAccessCheck(
+ Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
+ uint32_t index) {
+ Handle<JSObject> holder = object;
+ PrototypeIterator::WhereToStart where_to_start =
+ PrototypeIterator::START_AT_RECEIVER;
+ while (true) {
+ auto all_can_read_holder =
+ FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
+ if (!all_can_read_holder.ToHandle(&holder)) break;
+ auto result =
+ JSObject::GetElementWithInterceptor(holder, receiver, index, false);
+ if (isolate->has_scheduled_exception()) break;
+ if (!result.is_null()) return result;
+ where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
+ }
+ isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ return isolate->factory()->undefined_value();
+}
+
+
+Maybe<PropertyAttributes> JSObject::GetElementAttributesWithFailedAccessCheck(
+ Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
+ uint32_t index) {
+ Handle<JSObject> holder = object;
+ PrototypeIterator::WhereToStart where_to_start =
+ PrototypeIterator::START_AT_RECEIVER;
+ while (true) {
+ auto all_can_read_holder =
+ FindIndexedAllCanReadHolder(isolate, holder, where_to_start);
+ if (!all_can_read_holder.ToHandle(&holder)) break;
+ auto result =
+ JSObject::GetElementAttributeFromInterceptor(object, receiver, index);
+ if (isolate->has_scheduled_exception()) break;
+ if (result.has_value && result.value != ABSENT) return result;
+ where_to_start = PrototypeIterator::START_AT_PROTOTYPE;
+ }
+ isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
+ return maybe(ABSENT);
+}
+
+
MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
Handle<Object> object,
Handle<Object> receiver,
@@ -582,14 +664,14 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
// Check access rights if needed.
if (js_object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
- isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- return isolate->factory()->undefined_value();
+ return JSObject::GetElementWithFailedAccessCheck(isolate, js_object,
+ receiver, index);
}
}
if (js_object->HasIndexedInterceptor()) {
- return JSObject::GetElementWithInterceptor(js_object, receiver, index);
+ return JSObject::GetElementWithInterceptor(js_object, receiver, index,
+ true);
}
if (js_object->elements() != isolate->heap()->empty_fixed_array()) {
@@ -4012,9 +4094,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithReceiver(
// Check access rights if needed.
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) {
- isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS);
- RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
- return maybe(ABSENT);
+ return GetElementAttributesWithFailedAccessCheck(isolate, object,
+ receiver, index);
}
}
@@ -13264,10 +13345,10 @@ MaybeHandle<Object> JSArray::ReadOnlyLengthError(Handle<JSArray> array) {
}
-MaybeHandle<Object> JSObject::GetElementWithInterceptor(
- Handle<JSObject> object,
- Handle<Object> receiver,
- uint32_t index) {
+MaybeHandle<Object> JSObject::GetElementWithInterceptor(Handle<JSObject> object,
+ Handle<Object> receiver,
+ uint32_t index,
+ bool check_prototype) {
Isolate* isolate = object->GetIsolate();
// Make sure that the top context does not change when doing
@@ -13292,6 +13373,8 @@ MaybeHandle<Object> JSObject::GetElementWithInterceptor(
}
}
+ if (!check_prototype) return MaybeHandle<Object>();
+
ElementsAccessor* handler = object->GetElementsAccessor();
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698