| 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.
|
| +// 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)) {
|
| + 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);
|
| }
|
| };
|
|
|
|
|