diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-10 12:55:19 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-10 12:55:19 +0000 |
commit | 777183d073f20b851391345e6a5d8ca9ad7a45ac (patch) | |
tree | 7f2d29aa6bf991f79da63139d399bb5bac2cc622 /gin | |
parent | 05a526aa340676d4df945b3c772cb17bc200dbe1 (diff) | |
download | chromium_src-777183d073f20b851391345e6a5d8ca9ad7a45ac.zip chromium_src-777183d073f20b851391345e6a5d8ca9ad7a45ac.tar.gz chromium_src-777183d073f20b851391345e6a5d8ca9ad7a45ac.tar.bz2 |
gin: Add ability to install call-as-function handlers on gin::Wrappable
BUG=347565
R=dcarney@chromium.org
Review URL: https://codereview.chromium.org/192693002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@255927 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gin')
-rw-r--r-- | gin/function_template.h | 14 | ||||
-rw-r--r-- | gin/function_template.h.pump | 14 | ||||
-rw-r--r-- | gin/object_template_builder.h | 21 | ||||
-rw-r--r-- | gin/wrappable_unittest.cc | 54 |
4 files changed, 103 insertions, 0 deletions
diff --git a/gin/function_template.h b/gin/function_template.h index fe95f51..7ba54b5 100644 --- a/gin/function_template.h +++ b/gin/function_template.h @@ -501,6 +501,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( holder->GetHandle(isolate))); } +// CreateFunctionHandler installs a CallAsFunction handler on the given +// object template that forwards to a provided C++ function or base::Callback. +template<typename Sig> +void CreateFunctionHandler(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> tmpl, + const base::Callback<Sig> callback, + int callback_flags = 0) { + typedef internal::CallbackHolder<Sig> HolderT; + HolderT* holder = new HolderT(isolate, callback, callback_flags); + tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback, + ConvertToV8<v8::Handle<v8::External> >( + isolate, holder->GetHandle(isolate))); +} + } // namespace gin #endif // GIN_FUNCTION_TEMPLATE_H_ diff --git a/gin/function_template.h.pump b/gin/function_template.h.pump index 6f5bade..20b2821 100644 --- a/gin/function_template.h.pump +++ b/gin/function_template.h.pump @@ -221,6 +221,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( holder->GetHandle(isolate))); } +// CreateFunctionHandler installs a CallAsFunction handler on the given +// object template that forwards to a provided C++ function or base::Callback. +template<typename Sig> +void CreateFunctionHandler(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> tmpl, + const base::Callback<Sig> callback, + int callback_flags = 0) { + typedef internal::CallbackHolder<Sig> HolderT; + HolderT* holder = new HolderT(isolate, callback, callback_flags); + tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback, + ConvertToV8<v8::Handle<v8::External> >( + isolate, holder->GetHandle(isolate))); +} + } // namespace gin #endif // GIN_FUNCTION_TEMPLATE_H_ diff --git a/gin/object_template_builder.h b/gin/object_template_builder.h index 6367b71..768f4c8 100644 --- a/gin/object_template_builder.h +++ b/gin/object_template_builder.h @@ -27,6 +27,11 @@ struct CallbackTraits { T callback) { return CreateFunctionTemplate(isolate, base::Bind(callback)); } + static void SetAsFunctionHandler(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> tmpl, + T callback) { + CreateFunctionHandler(isolate, tmpl, base::Bind(callback)); + } }; // Specialization for base::Callback. @@ -36,6 +41,11 @@ struct CallbackTraits<base::Callback<T> > { v8::Isolate* isolate, const base::Callback<T>& callback) { return CreateFunctionTemplate(isolate, callback); } + static void SetAsFunctionHandler(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> tmpl, + const base::Callback<T>& callback) { + CreateFunctionHandler(isolate, tmpl, callback); + } }; // Specialization for member function pointers. We need to handle this case @@ -50,6 +60,12 @@ struct CallbackTraits<T, typename base::enable_if< return CreateFunctionTemplate(isolate, base::Bind(callback), HolderIsFirstArgument); } + static void SetAsFunctionHandler(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> tmpl, + T callback) { + CreateFunctionHandler( + isolate, tmpl, base::Bind(callback), HolderIsFirstArgument); + } }; // This specialization allows people to construct function templates directly if @@ -103,6 +119,11 @@ class GIN_EXPORT ObjectTemplateBuilder { CallbackTraits<T>::CreateTemplate(isolate_, getter), CallbackTraits<U>::CreateTemplate(isolate_, setter)); } + template<typename T> + ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) { + CallbackTraits<T>::SetAsFunctionHandler(isolate_, template_, callback); + return *this; + } v8::Local<v8::ObjectTemplate> Build(); diff --git a/gin/wrappable_unittest.cc b/gin/wrappable_unittest.cc index bf143ce..ec067d5 100644 --- a/gin/wrappable_unittest.cc +++ b/gin/wrappable_unittest.cc @@ -74,6 +74,36 @@ class MyObjectSubclass : public MyObject { } }; +class MyCallableObject : public Wrappable<MyCallableObject> { + public: + static WrapperInfo kWrapperInfo; + + static gin::Handle<MyCallableObject> Create(v8::Isolate* isolate) { + return CreateHandle(isolate, new MyCallableObject()); + } + + int result() { return result_; } + + private: + virtual ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) OVERRIDE { + return Wrappable<MyCallableObject>::GetObjectTemplateBuilder(isolate) + .SetCallAsFunctionHandler(&MyCallableObject::Call); + } + + MyCallableObject() : result_(0) { + } + + virtual ~MyCallableObject() { + } + + void Call(int val) { + result_ = val; + } + + int result_; +}; + class MyObject2 : public Wrappable<MyObject2> { public: static WrapperInfo kWrapperInfo; @@ -90,6 +120,7 @@ ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) { .SetProperty("value", &MyObject::value, &MyObject::set_value); } +WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin }; WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin }; WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin }; @@ -213,4 +244,27 @@ TEST_F(WrappableTest, ErrorInObjectConstructorProperty) { EXPECT_TRUE(try_catch.HasCaught()); } +TEST_F(WrappableTest, CallAsFunction) { + v8::Isolate* isolate = instance_->isolate(); + v8::HandleScope handle_scope(isolate); + + gin::Handle<MyCallableObject> object(MyCallableObject::Create(isolate)); + EXPECT_EQ(0, object->result()); + v8::Handle<v8::String> source = StringToV8(isolate, + "(function(obj) {" + "obj(42);" + "})"); + gin::TryCatch try_catch; + v8::Handle<v8::Script> script = v8::Script::Compile(source); + v8::Handle<v8::Value> val = script->Run(); + v8::Handle<v8::Function> func; + EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); + v8::Handle<v8::Value> argv[] = { + ConvertToV8(isolate, object.get()) + }; + func->Call(v8::Undefined(isolate), 1, argv); + EXPECT_FALSE(try_catch.HasCaught()); + EXPECT_EQ(42, object->result()); +} + } // namespace gin |