Index: gin/object_template_builder.h |
diff --git a/gin/object_template_builder.h b/gin/object_template_builder.h |
index 87e2633862c0f175e06594a376536a03b9427480..9af5e4f396811192273b6b8bf4548c762deef042 100644 |
--- a/gin/object_template_builder.h |
+++ b/gin/object_template_builder.h |
@@ -6,13 +6,64 @@ |
#define GIN_OBJECT_TEMPLATE_BUILDER_H_ |
#include "base/bind.h" |
+#include "base/callback.h" |
#include "base/strings/string_piece.h" |
+#include "base/template_util.h" |
#include "gin/converter.h" |
#include "gin/function_template.h" |
#include "v8/include/v8.h" |
namespace gin { |
+namespace { |
awong
2013/12/10 02:37:24
erp...I'm concerned about putting an anonymous nam
Jeffrey Yasskin
2013/12/10 02:42:45
Very good catch. It actually causes undefined beha
|
+ |
+// 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<typename T, typename Enable = void> |
+struct CallbackTraits { |
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, |
+ T callback) { |
+ return CreateFunctionTemplate(isolate, base::Bind(callback)); |
+ } |
+}; |
+ |
+// Specialization for base::Callback. |
+template<typename T> |
+struct CallbackTraits<base::Callback<T> > { |
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate( |
+ v8::Isolate* isolate, const base::Callback<T>& callback) { |
+ return CreateFunctionTemplate(isolate, 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<typename T> |
+struct CallbackTraits<T, typename base::enable_if< |
+ base::is_member_function_pointer<T>::value >::type> { |
awong
2013/12/10 02:37:24
Why do we need this enable_if?
Also, can this be
Jeffrey Yasskin
2013/12/10 02:42:45
Probably not, because he's using the specializatio
|
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate, |
+ T callback) { |
+ return CreateFunctionTemplate(isolate, base::Bind(callback), |
+ HolderIsFirstArgument); |
+ } |
+}; |
+ |
+// This specialization allows people to construct function templates directly if |
+// they need to do fancier stuff. |
+template<> |
+struct CallbackTraits<v8::Handle<v8::FunctionTemplate> > { |
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate( |
+ v8::Handle<v8::FunctionTemplate> templ) { |
+ return templ; |
+ } |
+}; |
+ |
+} // namespace |
+ |
+ |
// ObjectTemplateBuilder provides a handy interface to creating |
// v8::ObjectTemplate instances with various sorts of properties. |
class ObjectTemplateBuilder { |
@@ -28,15 +79,28 @@ class ObjectTemplateBuilder { |
return SetImpl(name, ConvertToV8(isolate_, val)); |
} |
+ // In the following methods, T and U can be function pointer, member function |
awong
2013/12/10 02:37:24
nit: can be -> can be a
|
+ // 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<typename T> |
- ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, T val) { |
- return SetMethod(name, base::Bind(val)); |
+ ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, |
+ const T& callback) { |
+ return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback)); |
} |
- |
template<typename T> |
- ObjectTemplateBuilder& SetMethod(const base::StringPiece& name, |
- const base::Callback<T>& callback) { |
- return SetImpl(name, CreateFunctionTemplate(isolate_, callback)); |
+ ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, |
+ const T& getter) { |
+ return SetPropertyImpl(name, |
+ CallbackTraits<T>::CreateTemplate(isolate_, getter), |
+ v8::Local<v8::FunctionTemplate>()); |
+ } |
+ template<typename T, typename U> |
+ ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, |
+ const T& getter, const U& setter) { |
+ return SetPropertyImpl(name, |
+ CallbackTraits<T>::CreateTemplate(isolate_, getter), |
+ CallbackTraits<U>::CreateTemplate(isolate_, setter)); |
} |
v8::Local<v8::ObjectTemplate> Build(); |
@@ -44,6 +108,9 @@ class ObjectTemplateBuilder { |
private: |
ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, |
v8::Handle<v8::Data> val); |
+ ObjectTemplateBuilder& SetPropertyImpl( |
+ const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter, |
+ v8::Handle<v8::FunctionTemplate> setter); |
v8::Isolate* isolate_; |