// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GIN_OBJECT_TEMPLATE_BUILDER_H_ #define GIN_OBJECT_TEMPLATE_BUILDER_H_ #include #include "base/bind.h" #include "base/callback.h" #include "base/strings/string_piece.h" #include "gin/converter.h" #include "gin/function_template.h" #include "gin/gin_export.h" #include "v8/include/v8.h" namespace gin { namespace { // Base template - used only for non-member function pointers. Other types // either go to one of the below specializations, or go here and fail to compile // because of base::Bind(). template struct CallbackTraits { static v8::Local CreateTemplate(v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } static void SetAsFunctionHandler(v8::Isolate* isolate, v8::Local tmpl, T callback) { CreateFunctionHandler(isolate, tmpl, base::Bind(callback)); } }; // Specialization for base::Callback. template struct CallbackTraits > { static v8::Local CreateTemplate( v8::Isolate* isolate, const base::Callback& callback) { return CreateFunctionTemplate(isolate, callback); } static void SetAsFunctionHandler(v8::Isolate* isolate, v8::Local tmpl, const base::Callback& callback) { CreateFunctionHandler(isolate, tmpl, callback); } }; // Specialization for member function pointers. We need to handle this case // specially because the first parameter for callbacks to MFP should typically // come from the the JavaScript "this" object the function was called on, not // from the first normal parameter. template struct CallbackTraits< T, typename std::enable_if::value>::type> { static v8::Local CreateTemplate(v8::Isolate* isolate, T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback), HolderIsFirstArgument); } static void SetAsFunctionHandler(v8::Isolate* isolate, v8::Local tmpl, T callback) { CreateFunctionHandler( isolate, tmpl, base::Bind(callback), HolderIsFirstArgument); } }; // This specialization allows people to construct function templates directly if // they need to do fancier stuff. template<> struct CallbackTraits > { static v8::Local CreateTemplate( v8::Local templ) { return templ; } }; } // namespace // ObjectTemplateBuilder provides a handy interface to creating // v8::ObjectTemplate instances with various sorts of properties. class GIN_EXPORT ObjectTemplateBuilder { public: explicit ObjectTemplateBuilder(v8::Isolate* isolate); ObjectTemplateBuilder(const ObjectTemplateBuilder& other); ~ObjectTemplateBuilder(); // It's against Google C++ style to return a non-const ref, but we take some // poetic license here in order that all calls to Set() can be via the '.' // operator and line up nicely. template ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) { return SetImpl(name, ConvertToV8(isolate_, val)); } // In the following methods, T and U can be function pointer, member function // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to // use one of the first two options. Also see gin::CreateFunctionTemplate() // for creating raw function templates. template ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, const T& callback) { return SetImpl(name, CallbackTraits::CreateTemplate(isolate_, callback)); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, const T& getter) { return SetPropertyImpl(name, CallbackTraits::CreateTemplate(isolate_, getter), v8::Local()); } template ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, const T& getter, const U& setter) { return SetPropertyImpl(name, CallbackTraits::CreateTemplate(isolate_, getter), CallbackTraits::CreateTemplate(isolate_, setter)); } template ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) { CallbackTraits::SetAsFunctionHandler(isolate_, template_, callback); return *this; } ObjectTemplateBuilder& AddNamedPropertyInterceptor(); ObjectTemplateBuilder& AddIndexedPropertyInterceptor(); v8::Local Build(); private: ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, v8::Local val); ObjectTemplateBuilder& SetPropertyImpl( const base::StringPiece& name, v8::Local getter, v8::Local setter); v8::Isolate* isolate_; // ObjectTemplateBuilder should only be used on the stack. v8::Local template_; }; } // namespace gin #endif // GIN_OBJECT_TEMPLATE_BUILDER_H_