Index: gin/function_template.h |
diff --git a/gin/function_template.h b/gin/function_template.h |
index 7ba54b5910ef4ffcb032deba86a8490a0fba72ef..955ff53c284d416b8ffa33e2011635a342476c2c 100644 |
--- a/gin/function_template.h |
+++ b/gin/function_template.h |
@@ -1,16 +1,10 @@ |
-// This file was GENERATED by command: |
-// pump.py function_template.h.pump |
-// DO NOT EDIT BY HAND!!! |
- |
- |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
Aaron Boodman
2014/10/31 22:26:40
I thought we weren't supposed to change the year.
|
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
#ifndef GIN_FUNCTION_TEMPLATE_H_ |
#define GIN_FUNCTION_TEMPLATE_H_ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
#include "base/callback.h" |
#include "base/logging.h" |
#include "gin/arguments.h" |
@@ -80,180 +74,6 @@ class CallbackHolder : public CallbackHolderBase { |
DISALLOW_COPY_AND_ASSIGN(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, typename P4 = void, typename P5 = void, |
- typename P6 = void> |
-struct Invoker { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<R(P1, P2, P3, P4, P5, P6)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4, |
- const P5& a5, |
- const P6& a6) { |
- args->Return(callback.Run(a1, a2, a3, a4, a5, a6)); |
- } |
-}; |
-template<typename P1, typename P2, typename P3, typename P4, typename P5, |
- typename P6> |
-struct Invoker<void, P1, P2, P3, P4, P5, P6> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<void(P1, P2, P3, P4, P5, P6)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4, |
- const P5& a5, |
- const P6& a6) { |
- callback.Run(a1, a2, a3, a4, a5, a6); |
- } |
-}; |
- |
-template<typename R, typename P1, typename P2, typename P3, typename P4, |
- typename P5> |
-struct Invoker<R, P1, P2, P3, P4, P5, void> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<R(P1, P2, P3, P4, P5)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4, |
- const P5& a5) { |
- args->Return(callback.Run(a1, a2, a3, a4, a5)); |
- } |
-}; |
-template<typename P1, typename P2, typename P3, typename P4, typename P5> |
-struct Invoker<void, P1, P2, P3, P4, P5, void> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<void(P1, P2, P3, P4, P5)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4, |
- const P5& a5) { |
- callback.Run(a1, a2, a3, a4, a5); |
- } |
-}; |
- |
-template<typename R, typename P1, typename P2, typename P3, typename P4> |
-struct Invoker<R, P1, P2, P3, P4, void, void> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<R(P1, P2, P3, P4)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4) { |
- args->Return(callback.Run(a1, a2, a3, a4)); |
- } |
-}; |
-template<typename P1, typename P2, typename P3, typename P4> |
-struct Invoker<void, P1, P2, P3, P4, void, void> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<void(P1, P2, P3, P4)>& callback, |
- const P1& a1, |
- const P2& a2, |
- const P3& a3, |
- const P4& a4) { |
- callback.Run(a1, a2, a3, a4); |
- } |
-}; |
- |
-template<typename R, typename P1, typename P2, typename P3> |
-struct Invoker<R, P1, P2, P3, void, void, void> { |
- 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, void, void, void> { |
- 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, void, void, 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, void, void, 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, void, 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, void, 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, 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, void, void, void> { |
- inline static void Go( |
- Arguments* args, |
- const base::Callback<void()>& callback) { |
- callback.Run(); |
- } |
-}; |
- |
- |
template<typename T> |
bool GetNextArgument(Arguments* args, int create_flags, bool is_first, |
T* result) { |
@@ -284,170 +104,88 @@ inline bool GetNextArgument(Arguments* args, int create_flags, |
return true; |
} |
+// Classes for generating and storing an argument pack of integer indices |
+// (based on well-known "indices trick", see: http://goo.gl/bKKojn): |
+template <size_t... indices> |
+struct IndicesHolder {}; |
-// DispatchToCallback converts all the JavaScript arguments to C++ types and |
-// invokes the base::Callback. |
-template<typename Sig> |
-struct Dispatcher { |
+template <size_t requested_index, size_t... indices> |
+struct IndicesGenerator { |
+ using type = typename IndicesGenerator<requested_index - 1, |
+ requested_index - 1, |
+ indices...>::type; |
}; |
- |
-template<typename R> |
-struct Dispatcher<R()> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
- |
- typedef CallbackHolder<R()> HolderT; |
- HolderT* holder = static_cast<HolderT*>(holder_base); |
- |
- Invoker<R>::Go(&args, holder->callback); |
- } |
+template <size_t... indices> |
+struct IndicesGenerator<0, indices...> { |
+ using type = IndicesHolder<indices...>; |
}; |
-template<typename R, typename P1> |
-struct Dispatcher<R(P1)> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
+// Class template for extracting and storing single argument for callback |
+// at position |index|. |
+template <size_t index, typename ArgType> |
+struct ArgumentHolder { |
+ using ArgLocalType = typename CallbackParamTraits<ArgType>::LocalType; |
- 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; |
- } |
+ ArgLocalType value; |
+ bool ok; |
- Invoker<R, P1>::Go(&args, holder->callback, a1); |
+ ArgumentHolder(Arguments* args, int create_flags) |
+ : ok(GetNextArgument(args, create_flags, index == 0, &value)) { |
Aaron Boodman
2014/10/31 22:26:40
Out of curiosity, since you have |index| already,
Krzysztof Olczyk
2014/11/05 07:50:40
Yes, we could have probably used the index directl
|
+ if (!ok) |
+ args->ThrowError(); |
} |
}; |
-template<typename R, typename P1, typename P2> |
-struct Dispatcher<R(P1, P2)> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
- |
- typedef CallbackHolder<R(P1, P2)> HolderT; |
- HolderT* holder = static_cast<HolderT*>(holder_base); |
+// Class template for converting arguments from JavaScript to C++ and running |
+// the callback with them. |
+template <typename IndicesType, typename... ArgTypes> |
+class Invoker {}; |
- 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; |
- } |
+template <size_t... indices, typename... ArgTypes> |
+class Invoker<IndicesHolder<indices...>, ArgTypes...> |
+ : public ArgumentHolder<indices, ArgTypes>... { |
+ public: |
+ // Invoker<> inherits from ArgumentHolder<> for each argument. |
+ // C++ has always been strict about the class initialization order, |
+ // so it is guaranteed ArgumentHolders will be initialized (and thus, will |
+ // extract arguments from Arguments) in the right order. |
+ Invoker(Arguments* args, int create_flags) |
+ : ArgumentHolder<indices, ArgTypes>(args, create_flags)..., |
+ args_(args) {} |
- Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2); |
+ bool IsOK() { |
+ return And(ArgumentHolder<indices, ArgTypes>::ok...); |
} |
-}; |
- |
-template<typename R, typename P1, typename P2, typename P3> |
-struct Dispatcher<R(P1, P2, P3)> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
- 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); |
+ template <typename ReturnType> |
+ void DispatchToCallback(base::Callback<ReturnType(ArgTypes...)> callback) { |
+ args_->Return(callback.Run(ArgumentHolder<indices, ArgTypes>::value...)); |
} |
-}; |
-template<typename R, typename P1, typename P2, typename P3, typename P4> |
-struct Dispatcher<R(P1, P2, P3, P4)> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
- |
- 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); |
+ // 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. |
+ void DispatchToCallback(base::Callback<void(ArgTypes...)> callback) { |
+ callback.Run(ArgumentHolder<indices, ArgTypes>::value...); |
} |
-}; |
-template<typename R, typename P1, typename P2, typename P3, typename P4, |
- typename P5> |
-struct Dispatcher<R(P1, P2, P3, P4, P5)> { |
- static void DispatchToCallback( |
- const v8::FunctionCallbackInfo<v8::Value>& info) { |
- Arguments args(info); |
- v8::Handle<v8::External> v8_holder; |
- CHECK(args.GetData(&v8_holder)); |
- CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
- v8_holder->Value()); |
- |
- typedef CallbackHolder<R(P1, P2, P3, P4, P5)> 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; |
- typename CallbackParamTraits<P5>::LocalType a5; |
- 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) || |
- !GetNextArgument(&args, holder->flags, false, &a5)) { |
- args.ThrowError(); |
- return; |
- } |
- |
- Invoker<R, P1, P2, P3, P4, P5>::Go(&args, holder->callback, a1, a2, a3, a4, |
- a5); |
+ private: |
+ static bool And() { return true; } |
+ template <typename... T> |
+ static bool And(bool arg1, T... args) { |
+ return arg1 && And(args...); |
} |
+ |
+ Arguments* args_; |
}; |
-template<typename R, typename P1, typename P2, typename P3, typename P4, |
- typename P5, typename P6> |
-struct Dispatcher<R(P1, P2, P3, P4, P5, P6)> { |
+// DispatchToCallback converts all the JavaScript arguments to C++ types and |
+// invokes the base::Callback. |
+template <typename Sig> |
+struct Dispatcher {}; |
+ |
+template <typename ReturnType, typename... ArgTypes> |
+struct Dispatcher<ReturnType(ArgTypes...)> { |
static void DispatchToCallback( |
const v8::FunctionCallbackInfo<v8::Value>& info) { |
Arguments args(info); |
@@ -456,27 +194,13 @@ struct Dispatcher<R(P1, P2, P3, P4, P5, P6)> { |
CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( |
v8_holder->Value()); |
- typedef CallbackHolder<R(P1, P2, P3, P4, P5, P6)> HolderT; |
+ typedef CallbackHolder<ReturnType(ArgTypes...)> 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; |
- typename CallbackParamTraits<P5>::LocalType a5; |
- typename CallbackParamTraits<P6>::LocalType a6; |
- 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) || |
- !GetNextArgument(&args, holder->flags, false, &a5) || |
- !GetNextArgument(&args, holder->flags, false, &a6)) { |
- args.ThrowError(); |
- return; |
- } |
- |
- Invoker<R, P1, P2, P3, P4, P5, P6>::Go(&args, holder->callback, a1, a2, a3, |
- a4, a5, a6); |
+ using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type; |
+ Invoker<Indices, ArgTypes...> invoker(&args, holder->flags); |
+ if (invoker.IsOK()) |
+ invoker.DispatchToCallback(holder->callback); |
} |
}; |