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 |