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

Unified Diff: src/objects.cc

Issue 2272383002: [api] Add interceptor for defineProperty(). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@DefineProperty
Patch Set: Query descriptor triggers on defineProperty(). Created 4 years, 3 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 fce862b2579627425f2f17c208520df8fc2f27b0..db4d9b5a0cb544bb43f51a088e57eb69eef520d7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1677,6 +1677,71 @@ 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,
+ Object::ConvertReceiver(isolate, receiver),
+ Nothing<bool>());
+ }
+ PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
+ *holder, should_throw);
+
+ std::unique_ptr<v8::PropertyDescriptor> descriptor(
+ new v8::PropertyDescriptor());
+ if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
+ descriptor.reset(new v8::PropertyDescriptor(
+ v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
+ } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
+ if (desc.has_writable()) {
+ descriptor.reset(new v8::PropertyDescriptor(
+ v8::Utils::ToLocal(desc.value()), desc.writable()));
+ } else {
+ descriptor.reset(
+ new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
+ }
+ }
+ if (desc.has_enumerable()) {
+ descriptor->set_enumerable(desc.enumerable());
+ }
+ if (desc.has_configurable()) {
+ descriptor->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, *descriptor).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, *descriptor).is_null();
+ }
+
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
+ return Just(result);
+}
+
} // namespace
MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
@@ -6535,6 +6600,34 @@ 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 = DefinePropertyWithInterceptorInternal(
+ &it, it.GetInterceptor(), 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.");
+ }
+ }
+
return OrdinaryDefineOwnProperty(&it, desc, should_throw);
}
« 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