Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index f6ae8470da9043dbae68364537bba01a0fd7990f..a41cf79f44de885d41ef1ec310935922aab4b2b4 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -1677,6 +1677,76 @@ Maybe<bool> SetPropertyWithInterceptorInternal( |
| return Just(result); |
| } |
| +Maybe<bool> DefinePropertyWithInterceptorInternal( |
| + LookupIterator* it, Handle<InterceptorInfo> interceptor, |
| + Object::ShouldThrow should_throw, PropertyDescriptor& desc) { |
| + Isolate* isolate = it->isolate(); |
| + // Make sure that the top context does not change when doing callbacks or |
| + // interceptor calls. |
| + AssertNoContextChange ncc(isolate); |
| + |
| + if (interceptor->definer()->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, |
|
jochen (gone - plz use gerrit)
2016/08/26 18:18:46
btw, is it a problem for your usecase that our int
Franzi
2016/09/01 06:38:18
So far, nobody has complained about it :)
|
| + Object::ConvertReceiver(isolate, receiver), |
| + Nothing<bool>()); |
| + } |
| + PropertyCallbackArguments args(isolate, interceptor->data(), *receiver, |
| + *holder, should_throw); |
| + |
| + std::unique_ptr<v8::PropertyDescriptor> propDescriptor( |
|
jochen (gone - plz use gerrit)
2016/08/26 18:18:46
nit. property_descriptor
Franzi
2016/09/01 06:38:18
Done.
|
| + new v8::PropertyDescriptor()); |
| + if (PropertyDescriptor::IsAccessorDescriptor(&desc)) { |
| + Handle<JSReceiver> getter = Handle<JSReceiver>(); |
| + if (desc.has_get() && desc.get()->IsCallable()) { |
| + getter = Handle<JSReceiver>::cast(desc.get()); |
| + } |
| + Handle<JSReceiver> setter = Handle<JSReceiver>(); |
| + if (desc.has_set() && desc.set()->IsCallable()) { |
| + setter = Handle<JSReceiver>::cast(desc.set()); |
| + } |
| + propDescriptor.reset(new v8::PropertyDescriptor( |
| + v8::Utils::CallableToLocal(getter), desc.has_get(), |
| + v8::Utils::CallableToLocal(setter), desc.has_set())); |
| + } else if (PropertyDescriptor::IsDataDescriptor(&desc)) { |
| + propDescriptor.reset(new v8::PropertyDescriptor( |
| + v8::Utils::ToLocal(desc.value()), desc.has_value(), desc.writable(), |
| + desc.has_writable())); |
| + } |
| + if (desc.has_enumerable()) { |
| + propDescriptor->set_enumerable(desc.enumerable()); |
| + } |
| + if (desc.has_configurable()) { |
| + propDescriptor->set_configurable(desc.configurable()); |
| + } |
| + |
| + if (it->IsElement()) { |
| + uint32_t index = it->index(); |
| + v8::IndexedPropertyDefinerCallback definer = |
| + v8::ToCData<v8::IndexedPropertyDefinerCallback>(interceptor->definer()); |
| + result = !args.Call(definer, index, *propDescriptor).is_null(); |
| + } else { |
| + Handle<Name> name = it->name(); |
| + DCHECK(!name->IsPrivate()); |
| + |
| + if (name->IsSymbol() && !interceptor->can_intercept_symbols()) { |
| + return Just(false); |
| + } |
| + |
| + v8::GenericNamedPropertyDefinerCallback definer = |
| + v8::ToCData<v8::GenericNamedPropertyDefinerCallback>( |
| + interceptor->definer()); |
| + result = !args.Call(definer, name, *propDescriptor).is_null(); |
| + } |
| + |
| + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>()); |
| + return Just(result); |
| +} |
| + |
| } // namespace |
| MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
| @@ -4525,6 +4595,14 @@ Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it, |
| should_throw, value); |
| } |
| +Maybe<bool> JSObject::DefinePropertyWithInterceptor(LookupIterator* it, |
| + ShouldThrow should_throw, |
| + PropertyDescriptor& desc) { |
| + DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
| + return DefinePropertyWithInterceptorInternal(it, it->GetInterceptor(), |
|
jochen (gone - plz use gerrit)
2016/08/26 18:18:46
just inline this method, as it's not used from any
Franzi
2016/09/01 06:38:18
Done.
|
| + should_throw, desc); |
| +} |
| + |
| MaybeHandle<Object> Object::SetProperty(Handle<Object> object, |
| Handle<Name> name, Handle<Object> value, |
| LanguageMode language_mode, |
| @@ -6542,6 +6620,35 @@ Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate, |
| it.Next(); |
| } |
| + // Handle interceptor |
| + if (it.state() == LookupIterator::INTERCEPTOR) { |
| + Handle<Map> store_target_map; |
| + if (it.GetReceiver()->IsJSObject()) { |
| + store_target_map = handle(it.GetStoreTarget()->map(), it.isolate()); |
| + } |
| + if (it.HolderIsReceiverOrHiddenPrototype()) { |
| + Maybe<bool> result = |
| + JSObject::DefinePropertyWithInterceptor(&it, should_throw, *desc); |
| + if (result.IsNothing() || result.FromJust()) { |
| + return result; |
| + } |
| + // Interceptor modified the store target but failed to set the |
| + // property. |
| + if (!store_target_map.is_null() && |
| + *store_target_map != it.GetStoreTarget()->map()) { |
| + it.isolate()->PushStackTraceAndDie( |
| + 0xabababaa, v8::ToCData<void*>(it.GetInterceptor()->setter()), |
| + nullptr, 0xabababab); |
| + } |
| + Utils::ApiCheck(store_target_map.is_null() || |
| + *store_target_map == it.GetStoreTarget()->map(), |
| + it.IsElement() ? "v8::IndexedPropertySetterCallback" |
| + : "v8::NamedPropertySetterCallback", |
| + "Interceptor silently changed store target."); |
| + } |
| + it.Next(); |
| + } |
| + |
| return OrdinaryDefineOwnProperty(&it, desc, should_throw); |
| } |