Commit 777183d0 authored by jochen@chromium.org's avatar jochen@chromium.org

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
parent 05a526aa
...@@ -501,6 +501,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( ...@@ -501,6 +501,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
holder->GetHandle(isolate))); 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 } // namespace gin
#endif // GIN_FUNCTION_TEMPLATE_H_ #endif // GIN_FUNCTION_TEMPLATE_H_
...@@ -221,6 +221,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( ...@@ -221,6 +221,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
holder->GetHandle(isolate))); 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 } // namespace gin
#endif // GIN_FUNCTION_TEMPLATE_H_ #endif // GIN_FUNCTION_TEMPLATE_H_
...@@ -27,6 +27,11 @@ struct CallbackTraits { ...@@ -27,6 +27,11 @@ struct CallbackTraits {
T callback) { T callback) {
return CreateFunctionTemplate(isolate, base::Bind(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. // Specialization for base::Callback.
...@@ -36,6 +41,11 @@ struct CallbackTraits<base::Callback<T> > { ...@@ -36,6 +41,11 @@ struct CallbackTraits<base::Callback<T> > {
v8::Isolate* isolate, const base::Callback<T>& callback) { v8::Isolate* isolate, const base::Callback<T>& callback) {
return CreateFunctionTemplate(isolate, 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 // Specialization for member function pointers. We need to handle this case
...@@ -50,6 +60,12 @@ struct CallbackTraits<T, typename base::enable_if< ...@@ -50,6 +60,12 @@ struct CallbackTraits<T, typename base::enable_if<
return CreateFunctionTemplate(isolate, base::Bind(callback), return CreateFunctionTemplate(isolate, base::Bind(callback),
HolderIsFirstArgument); 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 // This specialization allows people to construct function templates directly if
...@@ -103,6 +119,11 @@ class GIN_EXPORT ObjectTemplateBuilder { ...@@ -103,6 +119,11 @@ class GIN_EXPORT ObjectTemplateBuilder {
CallbackTraits<T>::CreateTemplate(isolate_, getter), CallbackTraits<T>::CreateTemplate(isolate_, getter),
CallbackTraits<U>::CreateTemplate(isolate_, setter)); 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(); v8::Local<v8::ObjectTemplate> Build();
......
...@@ -74,6 +74,36 @@ class MyObjectSubclass : public MyObject { ...@@ -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> { class MyObject2 : public Wrappable<MyObject2> {
public: public:
static WrapperInfo kWrapperInfo; static WrapperInfo kWrapperInfo;
...@@ -90,6 +120,7 @@ ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) { ...@@ -90,6 +120,7 @@ ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) {
.SetProperty("value", &MyObject::value, &MyObject::set_value); .SetProperty("value", &MyObject::value, &MyObject::set_value);
} }
WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin }; WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin }; WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin };
...@@ -213,4 +244,27 @@ TEST_F(WrappableTest, ErrorInObjectConstructorProperty) { ...@@ -213,4 +244,27 @@ TEST_F(WrappableTest, ErrorInObjectConstructorProperty) {
EXPECT_TRUE(try_catch.HasCaught()); 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 } // namespace gin
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment