diff options
Diffstat (limited to 'gin/function_template.h.pump')
-rw-r--r-- | gin/function_template.h.pump | 87 |
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())); } ]] |