// Copyright 2013 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "gin/object_template_builder.h" #include #include "gin/interceptor.h" #include "gin/per_isolate_data.h" #include "gin/public/wrapper_info.h" namespace gin { namespace { WrappableBase* WrappableFromV8(v8::Isolate* isolate, v8::Local val) { if (!val->IsObject()) return NULL; v8::Local obj = v8::Local::Cast(val); WrapperInfo* info = WrapperInfo::From(obj); // If this fails, the object is not managed by Gin. if (!info) return NULL; // We don't further validate the type of the object, but assume it's derived // from WrappableBase. We look up the pointer in a global registry, to make // sure it's actually pointed to a valid life object. return static_cast( obj->GetAlignedPointerFromInternalField(kEncodedValueIndex)); } NamedPropertyInterceptor* NamedInterceptorFromV8(v8::Isolate* isolate, v8::Local val) { WrappableBase* base = WrappableFromV8(isolate, val); if (!base) return NULL; return PerIsolateData::From(isolate)->GetNamedPropertyInterceptor(base); } IndexedPropertyInterceptor* IndexedInterceptorFromV8( v8::Isolate* isolate, v8::Local val) { WrappableBase* base = WrappableFromV8(isolate, val); if (!base) return NULL; return PerIsolateData::From(isolate)->GetIndexedPropertyInterceptor(base); } void NamedPropertyGetter(v8::Local property, const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = NamedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; std::string name; ConvertFromV8(isolate, property, &name); info.GetReturnValue().Set(interceptor->GetNamedProperty(isolate, name)); } void NamedPropertySetter(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = NamedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; std::string name; ConvertFromV8(isolate, property, &name); if (interceptor->SetNamedProperty(isolate, name, value)) info.GetReturnValue().Set(value); } void NamedPropertyQuery(v8::Local property, const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = NamedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; std::string name; ConvertFromV8(isolate, property, &name); if (interceptor->GetNamedProperty(isolate, name).IsEmpty()) return; info.GetReturnValue().Set(0); } void NamedPropertyEnumerator(const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = NamedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; v8::Local properties; if (!TryConvertToV8(isolate, interceptor->EnumerateNamedProperties(isolate), &properties)) return; info.GetReturnValue().Set(v8::Local::Cast(properties)); } void IndexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); IndexedPropertyInterceptor* interceptor = IndexedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; info.GetReturnValue().Set(interceptor->GetIndexedProperty(isolate, index)); } void IndexedPropertySetter(uint32_t index, v8::Local value, const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); IndexedPropertyInterceptor* interceptor = IndexedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; if (interceptor->SetIndexedProperty(isolate, index, value)) info.GetReturnValue().Set(value); } void IndexedPropertyEnumerator( const v8::PropertyCallbackInfo& info) { v8::Isolate* isolate = info.GetIsolate(); IndexedPropertyInterceptor* interceptor = IndexedInterceptorFromV8(isolate, info.Holder()); if (!interceptor) return; v8::Local properties; if (!TryConvertToV8(isolate, interceptor->EnumerateIndexedProperties(isolate), &properties)) return; info.GetReturnValue().Set(v8::Local::Cast(properties)); } } // namespace ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate) : ObjectTemplateBuilder(isolate, nullptr) {} ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate, const char* type_name) : ObjectTemplateBuilder(isolate, type_name, v8::ObjectTemplate::New(isolate)) {} ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate, const char* type_name, v8::Local tmpl) : isolate_(isolate), type_name_(type_name), template_(tmpl) { template_->SetInternalFieldCount(kNumberOfInternalFields); } ObjectTemplateBuilder::ObjectTemplateBuilder( const ObjectTemplateBuilder& other) = default; ObjectTemplateBuilder::~ObjectTemplateBuilder() = default; ObjectTemplateBuilder& ObjectTemplateBuilder::AddNamedPropertyInterceptor() { template_->SetHandler(v8::NamedPropertyHandlerConfiguration( &NamedPropertyGetter, &NamedPropertySetter, &NamedPropertyQuery, nullptr, &NamedPropertyEnumerator, v8::Local(), v8::PropertyHandlerFlags::kOnlyInterceptStrings)); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::AddIndexedPropertyInterceptor() { template_->SetIndexedPropertyHandler(&IndexedPropertyGetter, &IndexedPropertySetter, NULL, NULL, &IndexedPropertyEnumerator); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl( const base::StringPiece& name, v8::Local val) { template_->Set(StringToSymbol(isolate_, name), val); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(v8::Local name, v8::Local val) { template_->Set(name, val); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( const base::StringPiece& name, v8::Local getter, v8::Local setter) { template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter, setter); return *this; } ObjectTemplateBuilder& ObjectTemplateBuilder::SetLazyDataPropertyImpl( const base::StringPiece& name, v8::AccessorNameGetterCallback callback, v8::Local data) { template_->SetLazyDataProperty(StringToSymbol(isolate_, name), callback, data); return *this; } v8::Local ObjectTemplateBuilder::Build() { v8::Local result = template_; template_.Clear(); return result; } } // namespace gin