summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-10 12:55:19 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-10 12:55:19 +0000
commit777183d073f20b851391345e6a5d8ca9ad7a45ac (patch)
tree7f2d29aa6bf991f79da63139d399bb5bac2cc622
parent05a526aa340676d4df945b3c772cb17bc200dbe1 (diff)
downloadchromium_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
-rw-r--r--gin/function_template.h14
-rw-r--r--gin/function_template.h.pump14
-rw-r--r--gin/object_template_builder.h21
-rw-r--r--gin/wrappable_unittest.cc54
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