Chromium Code Reviews| 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); |
| } |
| }; |