summaryrefslogtreecommitdiffstats
path: root/gin/function_template.h.pump
diff options
context:
space:
mode:
Diffstat (limited to 'gin/function_template.h.pump')
-rw-r--r--gin/function_template.h.pump87
1 files changed, 73 insertions, 14 deletions
diff --git a/gin/function_template.h.pump b/gin/function_template.h.pump
index 802e048b..7e90324 100644
--- a/gin/function_template.h.pump
+++ b/gin/function_template.h.pump
@@ -36,12 +36,10 @@ struct RemoveConstRef<const T&> {
typedef T Type;
};
-} // namespace internal
-
// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from
// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to
-// DispatchCallback, where it is invoked.
+// DispatchToCallback, where it is invoked.
//
// v8::FunctionTemplate only supports passing void* as data so how do we know
// when to delete the base::Callback? That's where CallbackHolderBase comes in.
@@ -57,10 +55,6 @@ class CallbackHolderBase : public Wrappable {
virtual ~CallbackHolderBase() {}
};
-template<>
-struct Converter<CallbackHolderBase*>
- : public WrappableConverter<CallbackHolderBase> {};
-
template<typename Sig>
class CallbackHolder : public CallbackHolderBase {
public:
@@ -71,6 +65,51 @@ class CallbackHolder : public CallbackHolderBase {
virtual ~CallbackHolder() {}
};
+
+// This set of templates invokes a base::Callback, converts the return type to a
+// JavaScript value, and returns that value to script via the provided
+// gin::Arguments object.
+//
+// In C++, you can declare the function foo(void), but you can't pass a void
+// expression to foo. As a result, we must specialize the case of Callbacks that
+// have the void return type.
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$var INV_ARITY = MAX_ARITY - ARITY
+$range ARG 1..INV_ARITY
+$range VOID INV_ARITY+1..MAX_ARITY
+
+$if ARITY == 0 [[
+template<typename R$for ARG [[, typename P$(ARG) = void]]>
+struct Invoker {
+]] $else [[
+template<typename R$for ARG [[, typename P$(ARG)]]>
+struct Invoker<R$for ARG [[, P$(ARG)]]$for VOID [[, void]]> {
+]]
+
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R($for ARG , [[P$(ARG)]])>& callback$for ARG [[,
+ const P$(ARG)& a$(ARG)]]) {
+ args->Return(callback.Run($for ARG, [[a$(ARG)]]));
+ }
+};
+template<$for ARG , [[typename P$(ARG)]]>
+struct Invoker<void$for ARG [[, P$(ARG)]]$for VOID [[, void]]> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void($for ARG , [[P$(ARG)]])>& callback$for ARG [[,
+ const P$(ARG)& a$(ARG)]]) {
+ callback.Run($for ARG, [[a$(ARG)]]);
+ }
+};
+
+
+]]
+
+// DispatchToCallback converts all the JavaScript arguments to C++ types and
+// invokes the base::Callback.
$range ARITY 0..MAX_ARITY
$for ARITY [[
$range ARG 1..ARITY
@@ -82,13 +121,13 @@ static void DispatchToCallback(
CallbackHolderBase* holder_base = NULL;
CHECK(args.GetData(&holder_base));
- typedef CallbackHolder<void($for ARG , [[P$(ARG)]])> HolderT;
+ typedef CallbackHolder<R($for ARG , [[P$(ARG)]])> HolderT;
HolderT* holder = static_cast<HolderT*>(holder_base);
$if ARITY != 0 [[
-$for ARG [[ typename internal::RemoveConstRef<P$(ARG)>::Type a$(ARG);
+$for ARG [[ typename RemoveConstRef<P$(ARG)>::Type a$(ARG);
]]
if (
@@ -100,18 +139,38 @@ $for ARG ||
]]
- holder->callback.Run($for ARG , [[a$(ARG)]]);
+ Invoker<R$for ARG [[, P$(ARG)]]>::Go(&args, holder->callback$for ARG [[, a$(ARG)]]);
}
+]]
+
+} // namespace internal
+
+
+// This has to be outside the internal namespace because template
+// specializations must be declared in the same namespace as the original
+// template.
+template<>
+struct Converter<internal::CallbackHolderBase*>
+ : public WrappableConverter<internal::CallbackHolderBase> {};
+
+
+// Creates a v8::FunctionTemplate that will run the provided base::Callback each
+// time it is called. JavaScript arguments and return values are converted via
+// gin::Converter.
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
template<typename R$for ARG [[, typename P$(ARG)]]>
-v8::Local<v8::FunctionTemplate> CreateFunctionTempate(
+v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
v8::Isolate* isolate,
const base::Callback<R($for ARG , [[P$(ARG)]])> callback) {
- typedef CallbackHolder<void($for ARG , [[P$(ARG)]])> HolderT;
+ typedef internal::CallbackHolder<R($for ARG , [[P$(ARG)]])> HolderT;
scoped_refptr<HolderT> holder(new HolderT(callback));
return v8::FunctionTemplate::New(
- &DispatchToCallback<R$for ARG [[, P$(ARG)]]>,
- ConvertToV8<CallbackHolderBase*>(isolate, holder.get()));
+ &internal::DispatchToCallback<R$for ARG [[, P$(ARG)]]>,
+ ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get()));
}
]]