• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
CreateTemplateCallbackTraits26   static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
27                                                          T callback) {
28     return CreateFunctionTemplate(isolate, base::Bind(callback));
29   }
SetAsFunctionHandlerCallbackTraits30   static void SetAsFunctionHandler(v8::Isolate* isolate,
31                                    v8::Local<v8::ObjectTemplate> tmpl,
32                                    T callback) {
33     CreateFunctionHandler(isolate, tmpl, base::Bind(callback));
34   }
35 };
36 
37 // Specialization for base::Callback.
38 template<typename T>
39 struct CallbackTraits<base::Callback<T> > {
40   static v8::Handle<v8::FunctionTemplate> CreateTemplate(
41       v8::Isolate* isolate, const base::Callback<T>& callback) {
42     return CreateFunctionTemplate(isolate, callback);
43   }
44   static void SetAsFunctionHandler(v8::Isolate* isolate,
45                                    v8::Local<v8::ObjectTemplate> tmpl,
46                                    const base::Callback<T>& callback) {
47     CreateFunctionHandler(isolate, tmpl, callback);
48   }
49 };
50 
51 // Specialization for member function pointers. We need to handle this case
52 // specially because the first parameter for callbacks to MFP should typically
53 // come from the the JavaScript "this" object the function was called on, not
54 // from the first normal parameter.
55 template<typename T>
56 struct CallbackTraits<T, typename base::enable_if<
57                            base::is_member_function_pointer<T>::value>::type> {
58   static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
59                                                          T callback) {
60     return CreateFunctionTemplate(isolate, base::Bind(callback),
61                                   HolderIsFirstArgument);
62   }
63   static void SetAsFunctionHandler(v8::Isolate* isolate,
64                                    v8::Local<v8::ObjectTemplate> tmpl,
65                                    T callback) {
66     CreateFunctionHandler(
67         isolate, tmpl, base::Bind(callback), HolderIsFirstArgument);
68   }
69 };
70 
71 // This specialization allows people to construct function templates directly if
72 // they need to do fancier stuff.
73 template<>
74 struct GIN_EXPORT CallbackTraits<v8::Handle<v8::FunctionTemplate> > {
75   static v8::Handle<v8::FunctionTemplate> CreateTemplate(
76       v8::Handle<v8::FunctionTemplate> templ) {
77     return templ;
78   }
79 };
80 
81 }  // namespace
82 
83 
84 // ObjectTemplateBuilder provides a handy interface to creating
85 // v8::ObjectTemplate instances with various sorts of properties.
86 class GIN_EXPORT ObjectTemplateBuilder {
87  public:
88   explicit ObjectTemplateBuilder(v8::Isolate* isolate);
89   ~ObjectTemplateBuilder();
90 
91   // It's against Google C++ style to return a non-const ref, but we take some
92   // poetic license here in order that all calls to Set() can be via the '.'
93   // operator and line up nicely.
94   template<typename T>
95   ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) {
96     return SetImpl(name, ConvertToV8(isolate_, val));
97   }
98 
99   // In the following methods, T and U can be function pointer, member function
100   // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to
101   // use one of the first two options. Also see gin::CreateFunctionTemplate()
102   // for creating raw function templates.
103   template<typename T>
104   ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
105                                    const T& callback) {
106     return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback));
107   }
108   template<typename T>
109   ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
110                                      const T& getter) {
111     return SetPropertyImpl(name,
112                            CallbackTraits<T>::CreateTemplate(isolate_, getter),
113                            v8::Local<v8::FunctionTemplate>());
114   }
115   template<typename T, typename U>
116   ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
117                                      const T& getter, const U& setter) {
118     return SetPropertyImpl(name,
119                            CallbackTraits<T>::CreateTemplate(isolate_, getter),
120                            CallbackTraits<U>::CreateTemplate(isolate_, setter));
121   }
122   template<typename T>
123   ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) {
124     CallbackTraits<T>::SetAsFunctionHandler(isolate_, template_, callback);
125     return *this;
126   }
127   ObjectTemplateBuilder& AddNamedPropertyInterceptor();
128   ObjectTemplateBuilder& AddIndexedPropertyInterceptor();
129 
130   v8::Local<v8::ObjectTemplate> Build();
131 
132  private:
133   ObjectTemplateBuilder& SetImpl(const base::StringPiece& name,
134                                  v8::Handle<v8::Data> val);
135   ObjectTemplateBuilder& SetPropertyImpl(
136       const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter,
137       v8::Handle<v8::FunctionTemplate> setter);
138 
139   v8::Isolate* isolate_;
140 
141   // ObjectTemplateBuilder should only be used on the stack.
142   v8::Local<v8::ObjectTemplate> template_;
143 };
144 
145 }  // namespace gin
146 
147 #endif  // GIN_OBJECT_TEMPLATE_BUILDER_H_
148