| Index: gin/function_template.h
|
| diff --git a/gin/function_template.h b/gin/function_template.h
|
| index 643131776b8fac78617d2d1d3d39281c9696a282..b2badfa7dfb48d58f6ab9822aacb97bfbb01488e 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()));
|
| }
|
|
|
|
|