diff options
Diffstat (limited to 'gin/function_template.h')
-rw-r--r-- | gin/function_template.h | 293 |
1 files changed, 144 insertions, 149 deletions
diff --git a/gin/function_template.h b/gin/function_template.h index 6431317..b2badfa 100644 --- a/gin/function_template.h +++ b/gin/function_template.h @@ -26,15 +26,23 @@ namespace gin { class PerIsolateData; +enum CreateFunctionTemplateFlags { + HolderIsFirstArgument = 1 << 0, +}; + namespace internal { template<typename T> -struct RemoveConstRef { - typedef T Type; +struct CallbackParamTraits { + typedef T LocalType; +}; +template<typename T> +struct CallbackParamTraits<const T&> { + typedef T LocalType; }; template<typename T> -struct RemoveConstRef<const T&> { - typedef T Type; +struct CallbackParamTraits<const T*> { + typedef T* LocalType; }; @@ -58,9 +66,10 @@ class CallbackHolderBase : public Wrappable { template<typename Sig> class CallbackHolder : public CallbackHolderBase { public: - CallbackHolder(const base::Callback<Sig>& callback) - : callback(callback) {} + CallbackHolder(const base::Callback<Sig>& callback, int flags) + : callback(callback), flags(flags) {} base::Callback<Sig> callback; + int flags; private: virtual ~CallbackHolder() {} }; @@ -180,108 +189,141 @@ struct Invoker<void, void, void, void, void> { }; +template<typename T> +bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + T* result) { + if (is_first && (create_flags & HolderIsFirstArgument) != 0) { + return args->GetHolder(result); + } else { + return args->GetNext(result); + } +} + +// For advanced use cases, we allow callers to request the unparsed Arguments +// object and poke around in it directly. +inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first, + Arguments* result) { + *result = *args; + return true; +} + + // DispatchToCallback converts all the JavaScript arguments to C++ types and // invokes the base::Callback. +template<typename Sig> +struct Dispatcher { +}; + template<typename R> -static void DispatchToCallback( - const v8::FunctionCallbackInfo<v8::Value>& info) { - Arguments args(info); - CallbackHolderBase* holder_base = NULL; - CHECK(args.GetData(&holder_base)); +struct Dispatcher<R()> { + static void DispatchToCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); + CallbackHolderBase* holder_base = NULL; + CHECK(args.GetData(&holder_base)); - typedef CallbackHolder<R()> HolderT; - HolderT* holder = static_cast<HolderT*>(holder_base); + typedef CallbackHolder<R()> HolderT; + HolderT* holder = static_cast<HolderT*>(holder_base); - Invoker<R>::Go(&args, holder->callback); -} + Invoker<R>::Go(&args, holder->callback); + } +}; template<typename R, typename P1> -static void DispatchToCallback( - const v8::FunctionCallbackInfo<v8::Value>& info) { - Arguments args(info); - CallbackHolderBase* holder_base = NULL; - CHECK(args.GetData(&holder_base)); - - typedef CallbackHolder<R(P1)> HolderT; - HolderT* holder = static_cast<HolderT*>(holder_base); - - typename RemoveConstRef<P1>::Type a1; - if (!args.GetNext(&a1)) { - args.ThrowError(); - return; +struct Dispatcher<R(P1)> { + static void DispatchToCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); + CallbackHolderBase* holder_base = NULL; + CHECK(args.GetData(&holder_base)); + + typedef CallbackHolder<R(P1)> HolderT; + HolderT* holder = static_cast<HolderT*>(holder_base); + + typename CallbackParamTraits<P1>::LocalType a1; + if (!GetNextArgument(&args, holder->flags, true, &a1)) { + args.ThrowError(); + return; + } + + Invoker<R, P1>::Go(&args, holder->callback, a1); } - - Invoker<R, P1>::Go(&args, holder->callback, a1); -} +}; template<typename R, typename P1, typename P2> -static void DispatchToCallback( - const v8::FunctionCallbackInfo<v8::Value>& info) { - Arguments args(info); - CallbackHolderBase* holder_base = NULL; - CHECK(args.GetData(&holder_base)); - - typedef CallbackHolder<R(P1, P2)> HolderT; - HolderT* holder = static_cast<HolderT*>(holder_base); - - typename RemoveConstRef<P1>::Type a1; - typename RemoveConstRef<P2>::Type a2; - if (!args.GetNext(&a1) || - !args.GetNext(&a2)) { - args.ThrowError(); - return; +struct Dispatcher<R(P1, P2)> { + static void DispatchToCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); + CallbackHolderBase* holder_base = NULL; + CHECK(args.GetData(&holder_base)); + + typedef CallbackHolder<R(P1, P2)> HolderT; + HolderT* holder = static_cast<HolderT*>(holder_base); + + typename CallbackParamTraits<P1>::LocalType a1; + typename CallbackParamTraits<P2>::LocalType a2; + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2)) { + args.ThrowError(); + return; + } + + Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2); } - - Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2); -} +}; template<typename R, typename P1, typename P2, typename P3> -static void DispatchToCallback( - const v8::FunctionCallbackInfo<v8::Value>& info) { - Arguments args(info); - CallbackHolderBase* holder_base = NULL; - CHECK(args.GetData(&holder_base)); - - typedef CallbackHolder<R(P1, P2, P3)> HolderT; - HolderT* holder = static_cast<HolderT*>(holder_base); - - typename RemoveConstRef<P1>::Type a1; - typename RemoveConstRef<P2>::Type a2; - typename RemoveConstRef<P3>::Type a3; - if (!args.GetNext(&a1) || - !args.GetNext(&a2) || - !args.GetNext(&a3)) { - args.ThrowError(); - return; +struct Dispatcher<R(P1, P2, P3)> { + static void DispatchToCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); + CallbackHolderBase* holder_base = NULL; + CHECK(args.GetData(&holder_base)); + + typedef CallbackHolder<R(P1, P2, P3)> HolderT; + HolderT* holder = static_cast<HolderT*>(holder_base); + + typename CallbackParamTraits<P1>::LocalType a1; + typename CallbackParamTraits<P2>::LocalType a2; + typename CallbackParamTraits<P3>::LocalType a3; + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3)) { + args.ThrowError(); + return; + } + + Invoker<R, P1, P2, P3>::Go(&args, holder->callback, a1, a2, a3); } - - Invoker<R, P1, P2, P3>::Go(&args, holder->callback, a1, a2, a3); -} +}; template<typename R, typename P1, typename P2, typename P3, typename P4> -static void DispatchToCallback( - const v8::FunctionCallbackInfo<v8::Value>& info) { - Arguments args(info); - CallbackHolderBase* holder_base = NULL; - CHECK(args.GetData(&holder_base)); - - typedef CallbackHolder<R(P1, P2, P3, P4)> HolderT; - HolderT* holder = static_cast<HolderT*>(holder_base); - - typename RemoveConstRef<P1>::Type a1; - typename RemoveConstRef<P2>::Type a2; - typename RemoveConstRef<P3>::Type a3; - typename RemoveConstRef<P4>::Type a4; - if (!args.GetNext(&a1) || - !args.GetNext(&a2) || - !args.GetNext(&a3) || - !args.GetNext(&a4)) { - args.ThrowError(); - return; +struct Dispatcher<R(P1, P2, P3, P4)> { + static void DispatchToCallback( + const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); + CallbackHolderBase* holder_base = NULL; + CHECK(args.GetData(&holder_base)); + + typedef CallbackHolder<R(P1, P2, P3, P4)> HolderT; + HolderT* holder = static_cast<HolderT*>(holder_base); + + typename CallbackParamTraits<P1>::LocalType a1; + typename CallbackParamTraits<P2>::LocalType a2; + typename CallbackParamTraits<P3>::LocalType a3; + typename CallbackParamTraits<P4>::LocalType a4; + if (!GetNextArgument(&args, holder->flags, true, &a1) || + !GetNextArgument(&args, holder->flags, false, &a2) || + !GetNextArgument(&args, holder->flags, false, &a3) || + !GetNextArgument(&args, holder->flags, false, &a4)) { + args.ThrowError(); + return; + } + + Invoker<R, P1, P2, P3, P4>::Go(&args, holder->callback, a1, a2, a3, a4); } - - Invoker<R, P1, P2, P3, P4>::Go(&args, holder->callback, a1, a2, a3, a4); -} +}; } // namespace internal @@ -299,66 +341,19 @@ 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. -template<typename R> -v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( - v8::Isolate* isolate, - const base::Callback<R()> callback) { - typedef internal::CallbackHolder<R()> HolderT; - gin::Handle<HolderT> holder = CreateHandle(isolate, new HolderT(callback)); - return v8::FunctionTemplate::New( - isolate, - &internal::DispatchToCallback<R>, - ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); -} - -template<typename R, typename P1> -v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( - v8::Isolate* isolate, - const base::Callback<R(P1)> callback) { - typedef internal::CallbackHolder<R(P1)> HolderT; - gin::Handle<HolderT> holder = CreateHandle(isolate, new HolderT(callback)); - return v8::FunctionTemplate::New( - isolate, - &internal::DispatchToCallback<R, P1>, - ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); -} - -template<typename R, typename P1, typename P2> -v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( - v8::Isolate* isolate, - const base::Callback<R(P1, P2)> callback) { - typedef internal::CallbackHolder<R(P1, P2)> HolderT; - gin::Handle<HolderT> holder = CreateHandle(isolate, new HolderT(callback)); - return v8::FunctionTemplate::New( - isolate, - &internal::DispatchToCallback<R, P1, P2>, - ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); -} - -template<typename R, typename P1, typename P2, typename P3> -v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( - v8::Isolate* isolate, - const base::Callback<R(P1, P2, P3)> callback) { - typedef internal::CallbackHolder<R(P1, P2, P3)> HolderT; - gin::Handle<HolderT> holder = CreateHandle(isolate, new HolderT(callback)); - return v8::FunctionTemplate::New( - isolate, - &internal::DispatchToCallback<R, P1, P2, P3>, - ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); -} - -template<typename R, typename P1, typename P2, typename P3, typename P4> +// CreateFunctionTemplate creates a v8::FunctionTemplate that will create +// JavaScript functions that execute a provided C++ function or base::Callback. +// JavaScript arguments are automatically converted via gin::Converter, as is +// the return value of the C++ function, if any. +template<typename Sig> v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( - v8::Isolate* isolate, - const base::Callback<R(P1, P2, P3, P4)> callback) { - typedef internal::CallbackHolder<R(P1, P2, P3, P4)> HolderT; - gin::Handle<HolderT> holder = CreateHandle(isolate, new HolderT(callback)); + v8::Isolate* isolate, const base::Callback<Sig> callback, + int callback_flags = 0) { + typedef internal::CallbackHolder<Sig> HolderT; + gin::Handle<HolderT> holder = CreateHandle( + isolate, new HolderT(callback, callback_flags)); return v8::FunctionTemplate::New( - isolate, - &internal::DispatchToCallback<R, P1, P2, P3, P4>, + &internal::Dispatcher<Sig>::DispatchToCallback, ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); } |