diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-26 21:02:51 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-26 21:02:51 +0000 |
commit | 81f8b91b2f2213ad40d5bd4ecbe096550a2eedd6 (patch) | |
tree | 8527f82a4bb22c71187c73e4bca60c8c414957e3 /gin/function_template.h | |
parent | 615bca519a93ba2d550455189802584cae4fafb5 (diff) | |
download | chromium_src-81f8b91b2f2213ad40d5bd4ecbe096550a2eedd6.zip chromium_src-81f8b91b2f2213ad40d5bd4ecbe096550a2eedd6.tar.gz chromium_src-81f8b91b2f2213ad40d5bd4ecbe096550a2eedd6.tar.bz2 |
Implement support in function_template.h for return types.
Review URL: https://codereview.chromium.org/86783002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@237408 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gin/function_template.h')
-rw-r--r-- | gin/function_template.h | 220 |
1 files changed, 161 insertions, 59 deletions
diff --git a/gin/function_template.h b/gin/function_template.h index 7cf84f8..0685c1b 100644 --- a/gin/function_template.h +++ b/gin/function_template.h @@ -33,12 +33,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. @@ -47,17 +45,12 @@ struct RemoveConstRef<const T&> { // JavaScript references in V8. class CallbackHolderBase : public Wrappable { public: - static void EnsureRegistered(PerIsolateData* isolate_data); virtual WrapperInfo* GetWrapperInfo() OVERRIDE; static WrapperInfo kWrapperInfo; protected: virtual ~CallbackHolderBase() {} }; -template<> -struct Converter<CallbackHolderBase*> - : public WrappableConverter<CallbackHolderBase> {}; - template<typename Sig> class CallbackHolder : public CallbackHolderBase { public: @@ -68,6 +61,97 @@ 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. +template<typename R, typename P1 = void, typename P2 = void, typename P3 = void> +struct Invoker { + inline static void Go( + Arguments* args, + const base::Callback<R(P1, P2, P3)>& callback, + const P1& a1, + const P2& a2, + const P3& a3) { + args->Return(callback.Run(a1, a2, a3)); + } +}; +template<typename P1, typename P2, typename P3> +struct Invoker<void, P1, P2, P3> { + inline static void Go( + Arguments* args, + const base::Callback<void(P1, P2, P3)>& callback, + const P1& a1, + const P2& a2, + const P3& a3) { + callback.Run(a1, a2, a3); + } +}; + +template<typename R, typename P1, typename P2> +struct Invoker<R, P1, P2, void> { + inline static void Go( + Arguments* args, + const base::Callback<R(P1, P2)>& callback, + const P1& a1, + const P2& a2) { + args->Return(callback.Run(a1, a2)); + } +}; +template<typename P1, typename P2> +struct Invoker<void, P1, P2, void> { + inline static void Go( + Arguments* args, + const base::Callback<void(P1, P2)>& callback, + const P1& a1, + const P2& a2) { + callback.Run(a1, a2); + } +}; + +template<typename R, typename P1> +struct Invoker<R, P1, void, void> { + inline static void Go( + Arguments* args, + const base::Callback<R(P1)>& callback, + const P1& a1) { + args->Return(callback.Run(a1)); + } +}; +template<typename P1> +struct Invoker<void, P1, void, void> { + inline static void Go( + Arguments* args, + const base::Callback<void(P1)>& callback, + const P1& a1) { + callback.Run(a1); + } +}; + +template<typename R> +struct Invoker<R, void, void, void> { + inline static void Go( + Arguments* args, + const base::Callback<R()>& callback) { + args->Return(callback.Run()); + } +}; +template<> +struct Invoker<void, void, void, void> { + inline static void Go( + Arguments* args, + const base::Callback<void()>& callback) { + callback.Run(); + } +}; + + +// DispatchToCallback converts all the JavaScript arguments to C++ types and +// invokes the base::Callback. template<typename R> static void DispatchToCallback( const v8::FunctionCallbackInfo<v8::Value>& info) { @@ -75,21 +159,10 @@ static void DispatchToCallback( CallbackHolderBase* holder_base = NULL; CHECK(args.GetData(&holder_base)); - typedef CallbackHolder<void()> HolderT; + typedef CallbackHolder<R()> HolderT; HolderT* holder = static_cast<HolderT*>(holder_base); - holder->callback.Run(); -} - -template<typename R> -v8::Local<v8::FunctionTemplate> CreateFunctionTempate( - v8::Isolate* isolate, - const base::Callback<R()> callback) { - typedef CallbackHolder<void()> HolderT; - scoped_refptr<HolderT> holder(new HolderT(callback)); - return v8::FunctionTemplate::New( - &DispatchToCallback<R>, - ConvertToV8<CallbackHolderBase*>(isolate, holder.get())); + Invoker<R>::Go(&args, holder->callback); } template<typename R, typename P1> @@ -99,27 +172,16 @@ static void DispatchToCallback( CallbackHolderBase* holder_base = NULL; CHECK(args.GetData(&holder_base)); - typedef CallbackHolder<void(P1)> HolderT; + typedef CallbackHolder<R(P1)> HolderT; HolderT* holder = static_cast<HolderT*>(holder_base); - typename internal::RemoveConstRef<P1>::Type a1; + typename RemoveConstRef<P1>::Type a1; if (!args.GetNext(&a1)) { args.ThrowError(); return; } - holder->callback.Run(a1); -} - -template<typename R, typename P1> -v8::Local<v8::FunctionTemplate> CreateFunctionTempate( - v8::Isolate* isolate, - const base::Callback<R(P1)> callback) { - typedef CallbackHolder<void(P1)> HolderT; - scoped_refptr<HolderT> holder(new HolderT(callback)); - return v8::FunctionTemplate::New( - &DispatchToCallback<R, P1>, - ConvertToV8<CallbackHolderBase*>(isolate, holder.get())); + Invoker<R, P1>::Go(&args, holder->callback, a1); } template<typename R, typename P1, typename P2> @@ -129,29 +191,18 @@ static void DispatchToCallback( CallbackHolderBase* holder_base = NULL; CHECK(args.GetData(&holder_base)); - typedef CallbackHolder<void(P1, P2)> HolderT; + typedef CallbackHolder<R(P1, P2)> HolderT; HolderT* holder = static_cast<HolderT*>(holder_base); - typename internal::RemoveConstRef<P1>::Type a1; - typename internal::RemoveConstRef<P2>::Type a2; + typename RemoveConstRef<P1>::Type a1; + typename RemoveConstRef<P2>::Type a2; if (!args.GetNext(&a1) || !args.GetNext(&a2)) { args.ThrowError(); return; } - holder->callback.Run(a1, a2); -} - -template<typename R, typename P1, typename P2> -v8::Local<v8::FunctionTemplate> CreateFunctionTempate( - v8::Isolate* isolate, - const base::Callback<R(P1, P2)> callback) { - typedef CallbackHolder<void(P1, P2)> HolderT; - scoped_refptr<HolderT> holder(new HolderT(callback)); - return v8::FunctionTemplate::New( - &DispatchToCallback<R, P1, P2>, - ConvertToV8<CallbackHolderBase*>(isolate, holder.get())); + Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2); } template<typename R, typename P1, typename P2, typename P3> @@ -161,12 +212,12 @@ static void DispatchToCallback( CallbackHolderBase* holder_base = NULL; CHECK(args.GetData(&holder_base)); - typedef CallbackHolder<void(P1, P2, P3)> HolderT; + typedef CallbackHolder<R(P1, P2, P3)> HolderT; HolderT* holder = static_cast<HolderT*>(holder_base); - typename internal::RemoveConstRef<P1>::Type a1; - typename internal::RemoveConstRef<P2>::Type a2; - typename internal::RemoveConstRef<P3>::Type a3; + 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)) { @@ -174,18 +225,69 @@ static void DispatchToCallback( return; } - holder->callback.Run(a1, a2, a3); + Invoker<R, P1, P2, P3>::Go(&args, holder->callback, a1, a2, a3); +} + +} // namespace internal + + +// This should be called once per-isolate to initialize the function template +// system. +void InitFunctionTemplates(PerIsolateData* isolate_data); + +// 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. +template<typename R> +v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( + v8::Isolate* isolate, + const base::Callback<R()> callback) { + typedef internal::CallbackHolder<R()> HolderT; + scoped_refptr<HolderT> holder(new HolderT(callback)); + return v8::FunctionTemplate::New( + &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; + scoped_refptr<HolderT> holder(new HolderT(callback)); + return v8::FunctionTemplate::New( + &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; + scoped_refptr<HolderT> holder(new HolderT(callback)); + return v8::FunctionTemplate::New( + &internal::DispatchToCallback<R, P1, P2>, + ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); } template<typename R, typename P1, typename P2, typename P3> -v8::Local<v8::FunctionTemplate> CreateFunctionTempate( +v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( v8::Isolate* isolate, const base::Callback<R(P1, P2, P3)> callback) { - typedef CallbackHolder<void(P1, P2, P3)> HolderT; + typedef internal::CallbackHolder<R(P1, P2, P3)> HolderT; scoped_refptr<HolderT> holder(new HolderT(callback)); return v8::FunctionTemplate::New( - &DispatchToCallback<R, P1, P2, P3>, - ConvertToV8<CallbackHolderBase*>(isolate, holder.get())); + &internal::DispatchToCallback<R, P1, P2, P3>, + ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get())); } } // namespace gin |