1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef GIN_OBJECT_TEMPLATE_BUILDER_H_ 6 #define GIN_OBJECT_TEMPLATE_BUILDER_H_ 7 8 #include "base/bind.h" 9 #include "base/callback.h" 10 #include "base/strings/string_piece.h" 11 #include "base/template_util.h" 12 #include "gin/converter.h" 13 #include "gin/function_template.h" 14 #include "gin/gin_export.h" 15 #include "v8/include/v8.h" 16 17 namespace gin { 18 19 namespace { 20 21 // Base template - used only for non-member function pointers. Other types 22 // either go to one of the below specializations, or go here and fail to compile 23 // because of base::Bind(). 24 template<typename T, typename Enable = void> 25 struct CallbackTraits { 26 static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, 27 T callback) { 28 return CreateFunctionTemplate(isolate, base::Bind(callback)); 29 } 30 }; 31 32 // Specialization for base::Callback. 33 template<typename T> 34 struct CallbackTraits<base::Callback<T> > { 35 static v8::Handle<v8::FunctionTemplate> CreateTemplate( 36 v8::Isolate* isolate, const base::Callback<T>& callback) { 37 return CreateFunctionTemplate(isolate, callback); 38 } 39 }; 40 41 // Specialization for member function pointers. We need to handle this case 42 // specially because the first parameter for callbacks to MFP should typically 43 // come from the the JavaScript "this" object the function was called on, not 44 // from the first normal parameter. 45 template<typename T> 46 struct CallbackTraits<T, typename base::enable_if< 47 base::is_member_function_pointer<T>::value>::type> { 48 static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, 49 T callback) { 50 return CreateFunctionTemplate(isolate, base::Bind(callback), 51 HolderIsFirstArgument); 52 } 53 }; 54 55 // This specialization allows people to construct function templates directly if 56 // they need to do fancier stuff. 57 template<> 58 struct GIN_EXPORT CallbackTraits<v8::Handle<v8::FunctionTemplate> > { 59 static v8::Handle<v8::FunctionTemplate> CreateTemplate( 60 v8::Handle<v8::FunctionTemplate> templ) { 61 return templ; 62 } 63 }; 64 65 } // namespace 66 67 68 // ObjectTemplateBuilder provides a handy interface to creating 69 // v8::ObjectTemplate instances with various sorts of properties. 70 class GIN_EXPORT ObjectTemplateBuilder { 71 public: 72 explicit ObjectTemplateBuilder(v8::Isolate* isolate); 73 ~ObjectTemplateBuilder(); 74 75 // It's against Google C++ style to return a non-const ref, but we take some 76 // poetic license here in order that all calls to Set() can be via the '.' 77 // operator and line up nicely. 78 template<typename T> 79 ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) { 80 return SetImpl(name, ConvertToV8(isolate_, val)); 81 } 82 83 // In the following methods, T and U can be function pointer, member function 84 // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to 85 // use one of the first two options. Also see gin::CreateFunctionTemplate() 86 // for creating raw function templates. 87 template<typename T> 88 ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, 89 const T& callback) { 90 return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback)); 91 } 92 template<typename T> 93 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, 94 const T& getter) { 95 return SetPropertyImpl(name, 96 CallbackTraits<T>::CreateTemplate(isolate_, getter), 97 v8::Local<v8::FunctionTemplate>()); 98 } 99 template<typename T, typename U> 100 ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, 101 const T& getter, const U& setter) { 102 return SetPropertyImpl(name, 103 CallbackTraits<T>::CreateTemplate(isolate_, getter), 104 CallbackTraits<U>::CreateTemplate(isolate_, setter)); 105 } 106 107 v8::Local<v8::ObjectTemplate> Build(); 108 109 private: 110 ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, 111 v8::Handle<v8::Data> val); 112 ObjectTemplateBuilder& SetPropertyImpl( 113 const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter, 114 v8::Handle<v8::FunctionTemplate> setter); 115 116 v8::Isolate* isolate_; 117 118 // ObjectTemplateBuilder should only be used on the stack. 119 v8::Local<v8::ObjectTemplate> template_; 120 }; 121 122 } // namespace gin 123 124 #endif // GIN_OBJECT_TEMPLATE_BUILDER_H_ 125