Skip to content

Commit

Permalink
gin: Add ability to install call-as-function handlers on gin::Wrappable
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jochen@chromium.org committed Mar 10, 2014
1 parent 05a526a commit 777183d
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
14 changes: 14 additions & 0 deletions gin/function_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_
14 changes: 14 additions & 0 deletions gin/function_template.h.pump
Original file line number Diff line number Diff line change
Expand Up @@ -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_
21 changes: 21 additions & 0 deletions gin/object_template_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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();

Expand Down
54 changes: 54 additions & 0 deletions gin/wrappable_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 };

Expand Down Expand Up @@ -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

0 comments on commit 777183d

Please sign in to comment.