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

Unified Diff: src/objects.cc

Issue 2087823002: Optionally invoke an interceptor on failed access checks (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: updates Created 4 years, 6 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-debug.cc » ('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 a5da88a0b3b2e0b5e44b17e0918d17655ea38e09..f267b92dd8bddc12dd911d9c708837ffaeba8885 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1357,19 +1357,191 @@ bool JSObject::AllCanRead(LookupIterator* it) {
return false;
}
+namespace {
+
+MaybeHandle<Object> GetPropertyWithInterceptorInternal(
+ LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
+ *done = false;
+ Isolate* isolate = it->isolate();
+ // Make sure that the top context does not change when doing callbacks or
+ // interceptor calls.
+ AssertNoContextChange ncc(isolate);
+
+ if (interceptor->getter()->IsUndefined(isolate)) {
+ return isolate->factory()->undefined_value();
+ }
+
+ Handle<JSObject> holder = it->GetHolder<JSObject>();
+ Handle<Object> result;
+ Handle<Object> receiver = it->GetReceiver();
+ if (!receiver->IsJSReceiver()) {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
+ }
+ PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+ *holder, Object::DONT_THROW);
+
+ if (it->IsElement()) {
+ uint32_t index = it->index();
+ v8::IndexedPropertyGetterCallback getter =
+ v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
+ result = args.Call(getter, index);
+ } else {
+ Handle<Name> name = it->name();
+ DCHECK(!name->IsPrivate());
+
+ if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
+ return isolate->factory()->undefined_value();
+ }
+
+ v8::GenericNamedPropertyGetterCallback getter =
+ v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
+ interceptor->getter());
+ result = args.Call(getter, name);
+ }
+
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ if (result.is_null()) return isolate->factory()->undefined_value();
+ *done = true;
+ // Rebox handle before return
+ return handle(*result, isolate);
+}
+
+Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
+ LookupIterator* it, Handle<InterceptorInfo> interceptor) {
+ Isolate* isolate = it->isolate();
+ // Make sure that the top context does not change when doing
+ // callbacks or interceptor calls.
+ AssertNoContextChange ncc(isolate);
+ HandleScope scope(isolate);
+
+ Handle<JSObject> holder = it->GetHolder<JSObject>();
+ if (!it->IsElement() && it->name()->IsSymbol() &&
+ !interceptor->can_intercept_symbols()) {
+ return Just(ABSENT);
+ }
+ Handle<Object> receiver = it->GetReceiver();
+ if (!receiver->IsJSReceiver()) {
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
+ Object::ConvertReceiver(isolate, receiver),
+ Nothing<PropertyAttributes>());
+ }
+ PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+ *holder, Object::DONT_THROW);
+ if (!interceptor->query()->IsUndefined(isolate)) {
+ Handle<Object> result;
+ if (it->IsElement()) {
+ uint32_t index = it->index();
+ v8::IndexedPropertyQueryCallback query =
+ v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
+ result = args.Call(query, index);
+ } else {
+ Handle<Name> name = it->name();
+ DCHECK(!name->IsPrivate());
+ v8::GenericNamedPropertyQueryCallback query =
+ v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
+ interceptor->query());
+ result = args.Call(query, name);
+ }
+ if (!result.is_null()) {
+ int32_t value;
+ CHECK(result->ToInt32(&value));
+ return Just(static_cast<PropertyAttributes>(value));
+ }
+ } else if (!interceptor->getter()->IsUndefined(isolate)) {
+ // TODO(verwaest): Use GetPropertyWithInterceptor?
+ Handle<Object> result;
+ if (it->IsElement()) {
+ uint32_t index = it->index();
+ v8::IndexedPropertyGetterCallback getter =
+ v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
+ result = args.Call(getter, index);
+ } else {
+ Handle<Name> name = it->name();
+ DCHECK(!name->IsPrivate());
+ v8::GenericNamedPropertyGetterCallback getter =
+ v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
+ interceptor->getter());
+ result = args.Call(getter, name);
+ }
+ if (!result.is_null()) return Just(DONT_ENUM);
+ }
+
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
+ return Just(ABSENT);
+}
+
+Maybe<bool> SetPropertyWithInterceptorInternal(
+ LookupIterator* it, Handle<InterceptorInfo> interceptor,
+ Object::ShouldThrow should_throw, Handle<Object> value) {
+ Isolate* isolate = it->isolate();
+ // Make sure that the top context does not change when doing callbacks or
+ // interceptor calls.
+ AssertNoContextChange ncc(isolate);
+
+ if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
+
+ Handle<JSObject> holder = it->GetHolder<JSObject>();
+ bool result;
+ Handle<Object> receiver = it->GetReceiver();
+ if (!receiver->IsJSReceiver()) {
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
+ Object::ConvertReceiver(isolate, receiver),
+ Nothing<bool>());
+ }
+ PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+ *holder, should_throw);
+
+ if (it->IsElement()) {
+ uint32_t index = it->index();
+ v8::IndexedPropertySetterCallback setter =
+ v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
+ // TODO(neis): In the future, we may want to actually return the
+ // interceptor's result, which then should be a boolean.
+ result = !args.Call(setter, index, value).is_null();
+ } else {
+ Handle<Name> name = it->name();
+ DCHECK(!name->IsPrivate());
+
+ if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
+ return Just(false);
+ }
+
+ v8::GenericNamedPropertySetterCallback setter =
+ v8::ToCData<v8::GenericNamedPropertySetterCallback>(
+ interceptor->setter());
+ result = !args.Call(setter, name, value).is_null();
+ }
+
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
+ return Just(result);
+}
+
+} // namespace
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
LookupIterator* it) {
+ Isolate* isolate = it->isolate();
Handle<JSObject> checked = it->GetHolder<JSObject>();
- while (AllCanRead(it)) {
- if (it->state() == LookupIterator::ACCESSOR) {
- return GetPropertyWithAccessor(it);
+ Handle<InterceptorInfo> interceptor =
+ it->GetInterceptorForFailedAccessCheck();
+ if (interceptor.is_null()) {
+ while (AllCanRead(it)) {
+ if (it->state() == LookupIterator::ACCESSOR) {
+ return GetPropertyWithAccessor(it);
+ }
+ DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+ bool done;
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
+ GetPropertyWithInterceptor(it, &done), Object);
+ if (done) return result;
}
- DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+ } else {
+ MaybeHandle<Object> result;
bool done;
- Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result,
- GetPropertyWithInterceptor(it, &done), Object);
+ result = GetPropertyWithInterceptorInternal(it, interceptor, &done);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (done) return result;
}
@@ -1380,27 +1552,36 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
return it->factory()->undefined_value();
}
- it->isolate()->ReportFailedAccessCheck(checked);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object);
+ isolate->ReportFailedAccessCheck(checked);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return it->factory()->undefined_value();
}
Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
LookupIterator* it) {
+ Isolate* isolate = it->isolate();
Handle<JSObject> checked = it->GetHolder<JSObject>();
- while (AllCanRead(it)) {
- if (it->state() == LookupIterator::ACCESSOR) {
- return Just(it->property_attributes());
+ Handle<InterceptorInfo> interceptor =
+ it->GetInterceptorForFailedAccessCheck();
+ if (interceptor.is_null()) {
+ while (AllCanRead(it)) {
+ if (it->state() == LookupIterator::ACCESSOR) {
+ return Just(it->property_attributes());
+ }
+ DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
+ auto result = GetPropertyAttributesWithInterceptor(it);
+ if (isolate->has_scheduled_exception()) break;
+ if (result.IsJust() && result.FromJust() != ABSENT) return result;
}
- DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
- auto result = GetPropertyAttributesWithInterceptor(it);
- if (it->isolate()->has_scheduled_exception()) break;
- if (result.IsJust() && result.FromJust() != ABSENT) return result;
+ } else {
+ Maybe<PropertyAttributes> result =
+ GetPropertyAttributesWithInterceptorInternal(it, interceptor);
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
+ if (result.FromMaybe(ABSENT) != ABSENT) return result;
}
- it->isolate()->ReportFailedAccessCheck(checked);
- RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(),
- Nothing<PropertyAttributes>());
+ isolate->ReportFailedAccessCheck(checked);
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
return Just(ABSENT);
}
@@ -1421,13 +1602,23 @@ bool JSObject::AllCanWrite(LookupIterator* it) {
Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
+ Isolate* isolate = it->isolate();
Handle<JSObject> checked = it->GetHolder<JSObject>();
- if (AllCanWrite(it)) {
- return SetPropertyWithAccessor(it, value, should_throw);
+ Handle<InterceptorInfo> interceptor =
+ it->GetInterceptorForFailedAccessCheck();
+ if (interceptor.is_null()) {
+ if (AllCanWrite(it)) {
+ return SetPropertyWithAccessor(it, value, should_throw);
+ }
+ } else {
+ Maybe<bool> result = SetPropertyWithInterceptorInternal(
+ it, interceptor, should_throw, value);
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
+ if (result.IsJust()) return result;
}
- it->isolate()->ReportFailedAccessCheck(checked);
- RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
+ isolate->ReportFailedAccessCheck(checked);
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
return Just(true);
}
@@ -4217,56 +4408,14 @@ Handle<Map> Map::Update(Handle<Map> map) {
ALLOW_IN_DESCRIPTOR);
}
-
Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
ShouldThrow should_throw,
Handle<Object> value) {
- Isolate* isolate = it->isolate();
- // Make sure that the top context does not change when doing callbacks or
- // interceptor calls.
- AssertNoContextChange ncc(isolate);
-
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
- Handle<InterceptorInfo> interceptor(it->GetInterceptor());
- if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
-
- Handle<JSObject> holder = it->GetHolder<JSObject>();
- bool result;
- Handle<Object> receiver = it->GetReceiver();
- if (!receiver->IsJSReceiver()) {
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
- Object::ConvertReceiver(isolate, receiver),
- Nothing<bool>());
- }
- PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
- *holder, should_throw);
-
- if (it->IsElement()) {
- uint32_t index = it->index();
- v8::IndexedPropertySetterCallback setter =
- v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
- // TODO(neis): In the future, we may want to actually return the
- // interceptor's result, which then should be a boolean.
- result = !args.Call(setter, index, value).is_null();
- } else {
- Handle<Name> name = it->name();
- DCHECK(!name->IsPrivate());
-
- if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
- return Just(false);
- }
-
- v8::GenericNamedPropertySetterCallback setter =
- v8::ToCData<v8::GenericNamedPropertySetterCallback>(
- interceptor->setter());
- result = !args.Call(setter, name, value).is_null();
- }
-
- RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
- return Just(result);
+ return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
+ should_throw, value);
}
-
MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
Handle<Name> name, Handle<Object> value,
LanguageMode language_mode,
@@ -5525,73 +5674,11 @@ MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
}
-
Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
LookupIterator* it) {
- Isolate* isolate = it->isolate();
- // Make sure that the top context does not change when doing
- // callbacks or interceptor calls.
- AssertNoContextChange ncc(isolate);
- HandleScope scope(isolate);
-
- Handle<JSObject> holder = it->GetHolder<JSObject>();
- Handle<InterceptorInfo> interceptor(it->GetInterceptor());
- if (!it->IsElement() && it->name()->IsSymbol() &&
- !interceptor->can_intercept_symbols()) {
- return Just(ABSENT);
- }
- Handle<Object> receiver = it->GetReceiver();
- if (!receiver->IsJSReceiver()) {
- ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
- Object::ConvertReceiver(isolate, receiver),
- Nothing<PropertyAttributes>());
- }
- PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
- *holder, Object::DONT_THROW);
- if (!interceptor->query()->IsUndefined(isolate)) {
- Handle<Object> result;
- if (it->IsElement()) {
- uint32_t index = it->index();
- v8::IndexedPropertyQueryCallback query =
- v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
- result = args.Call(query, index);
- } else {
- Handle<Name> name = it->name();
- DCHECK(!name->IsPrivate());
- v8::GenericNamedPropertyQueryCallback query =
- v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
- interceptor->query());
- result = args.Call(query, name);
- }
- if (!result.is_null()) {
- int32_t value;
- CHECK(result->ToInt32(&value));
- return Just(static_cast<PropertyAttributes>(value));
- }
- } else if (!interceptor->getter()->IsUndefined(isolate)) {
- // TODO(verwaest): Use GetPropertyWithInterceptor?
- Handle<Object> result;
- if (it->IsElement()) {
- uint32_t index = it->index();
- v8::IndexedPropertyGetterCallback getter =
- v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
- result = args.Call(getter, index);
- } else {
- Handle<Name> name = it->name();
- DCHECK(!name->IsPrivate());
- v8::GenericNamedPropertyGetterCallback getter =
- v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
- interceptor->getter());
- result = args.Call(getter, name);
- }
- if (!result.is_null()) return Just(DONT_ENUM);
- }
-
- RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
- return Just(ABSENT);
+ return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
}
-
Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
LookupIterator* it) {
for (; it->IsFound(); it->Next()) {
@@ -15458,55 +15545,10 @@ void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
bool* done) {
- *done = false;
- Isolate* isolate = it->isolate();
- // Make sure that the top context does not change when doing callbacks or
- // interceptor calls.
- AssertNoContextChange ncc(isolate);
-
DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
- Handle<InterceptorInfo> interceptor = it->GetInterceptor();
- if (interceptor->getter()->IsUndefined(isolate)) {
- return isolate->factory()->undefined_value();
- }
-
- Handle<JSObject> holder = it->GetHolder<JSObject>();
- Handle<Object> result;
- Handle<Object> receiver = it->GetReceiver();
- if (!receiver->IsJSReceiver()) {
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
- }
- PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
- *holder, Object::DONT_THROW);
-
- if (it->IsElement()) {
- uint32_t index = it->index();
- v8::IndexedPropertyGetterCallback getter =
- v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
- result = args.Call(getter, index);
- } else {
- Handle<Name> name = it->name();
- DCHECK(!name->IsPrivate());
-
- if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
- return isolate->factory()->undefined_value();
- }
-
- v8::GenericNamedPropertyGetterCallback getter =
- v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
- interceptor->getter());
- result = args.Call(getter, name);
- }
-
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- if (result.is_null()) return isolate->factory()->undefined_value();
- *done = true;
- // Rebox handle before return
- return handle(*result, isolate);
+ return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
}
-
Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> name) {
LookupIterator it = LookupIterator::PropertyOrElement(
@@ -18863,5 +18905,24 @@ void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
}
}
+// static
+AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
+ Handle<JSObject> receiver) {
+ DisallowHeapAllocation no_gc;
+ DCHECK(receiver->map()->is_access_check_needed());
+ Object* maybe_constructor = receiver->map()->GetConstructor();
+ // Might happen for a detached context.
+ if (!maybe_constructor->IsJSFunction()) return nullptr;
+ JSFunction* constructor = JSFunction::cast(maybe_constructor);
+ // Might happen for the debug context.
+ if (!constructor->shared()->IsApiFunction()) return nullptr;
+
+ Object* data_obj =
+ constructor->shared()->get_api_func_data()->access_check_info();
+ if (data_obj->IsUndefined(isolate)) return nullptr;
+
+ return AccessCheckInfo::cast(data_obj);
+}
+
} // namespace internal
} // namespace v8
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698