Chromium Code Reviews| 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_; |