Home | History | Annotate | Download | only in gin
      1 // This file was GENERATED by command:
      2 //     pump.py function_template.h.pump
      3 // DO NOT EDIT BY HAND!!!
      4 
      5 
      6 
      7 #ifndef GIN_FUNCTION_TEMPLATE_H_
      8 #define GIN_FUNCTION_TEMPLATE_H_
      9 
     10 // Copyright 2013 The Chromium Authors. All rights reserved.
     11 // Use of this source code is governed by a BSD-style license that can be
     12 // found in the LICENSE file.
     13 
     14 #include "base/callback.h"
     15 #include "base/logging.h"
     16 #include "gin/arguments.h"
     17 #include "gin/converter.h"
     18 #include "gin/gin_export.h"
     19 #include "v8/include/v8.h"
     20 
     21 namespace gin {
     22 
     23 class PerIsolateData;
     24 
     25 enum CreateFunctionTemplateFlags {
     26   HolderIsFirstArgument = 1 << 0,
     27 };
     28 
     29 namespace internal {
     30 
     31 template<typename T>
     32 struct CallbackParamTraits {
     33   typedef T LocalType;
     34 };
     35 template<typename T>
     36 struct CallbackParamTraits<const T&> {
     37   typedef T LocalType;
     38 };
     39 template<typename T>
     40 struct CallbackParamTraits<const T*> {
     41   typedef T* LocalType;
     42 };
     43 
     44 
     45 // CallbackHolder and CallbackHolderBase are used to pass a base::Callback from
     46 // CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to
     47 // DispatchToCallback, where it is invoked.
     48 
     49 // This simple base class is used so that we can share a single object template
     50 // among every CallbackHolder instance.
     51 class GIN_EXPORT CallbackHolderBase {
     52  public:
     53   v8::Handle<v8::External> GetHandle(v8::Isolate* isolate);
     54 
     55  protected:
     56   explicit CallbackHolderBase(v8::Isolate* isolate);
     57   virtual ~CallbackHolderBase();
     58 
     59  private:
     60   static void WeakCallback(
     61       const v8::WeakCallbackData<v8::External, CallbackHolderBase>& data);
     62 
     63   v8::Persistent<v8::External> v8_ref_;
     64 
     65   DISALLOW_COPY_AND_ASSIGN(CallbackHolderBase);
     66 };
     67 
     68 template<typename Sig>
     69 class CallbackHolder : public CallbackHolderBase {
     70  public:
     71   CallbackHolder(v8::Isolate* isolate,
     72                  const base::Callback<Sig>& callback,
     73                  int flags)
     74       : CallbackHolderBase(isolate), callback(callback), flags(flags) {}
     75   base::Callback<Sig> callback;
     76   int flags;
     77  private:
     78   virtual ~CallbackHolder() {}
     79 
     80   DISALLOW_COPY_AND_ASSIGN(CallbackHolder);
     81 };
     82 
     83 
     84 // This set of templates invokes a base::Callback, converts the return type to a
     85 // JavaScript value, and returns that value to script via the provided
     86 // gin::Arguments object.
     87 //
     88 // In C++, you can declare the function foo(void), but you can't pass a void
     89 // expression to foo. As a result, we must specialize the case of Callbacks that
     90 // have the void return type.
     91 template<typename R, typename P1 = void, typename P2 = void,
     92     typename P3 = void, typename P4 = void, typename P5 = void,
     93     typename P6 = void>
     94 struct Invoker {
     95   inline static void Go(
     96       Arguments* args,
     97       const base::Callback<R(P1, P2, P3, P4, P5, P6)>& callback,
     98       const P1& a1,
     99       const P2& a2,
    100       const P3& a3,
    101       const P4& a4,
    102       const P5& a5,
    103       const P6& a6) {
    104     args->Return(callback.Run(a1, a2, a3, a4, a5, a6));
    105   }
    106 };
    107 template<typename P1, typename P2, typename P3, typename P4, typename P5,
    108     typename P6>
    109 struct Invoker<void, P1, P2, P3, P4, P5, P6> {
    110   inline static void Go(
    111       Arguments* args,
    112       const base::Callback<void(P1, P2, P3, P4, P5, P6)>& callback,
    113       const P1& a1,
    114       const P2& a2,
    115       const P3& a3,
    116       const P4& a4,
    117       const P5& a5,
    118       const P6& a6) {
    119     callback.Run(a1, a2, a3, a4, a5, a6);
    120   }
    121 };
    122 
    123 template<typename R, typename P1, typename P2, typename P3, typename P4,
    124     typename P5>
    125 struct Invoker<R, P1, P2, P3, P4, P5, void> {
    126   inline static void Go(
    127       Arguments* args,
    128       const base::Callback<R(P1, P2, P3, P4, P5)>& callback,
    129       const P1& a1,
    130       const P2& a2,
    131       const P3& a3,
    132       const P4& a4,
    133       const P5& a5) {
    134     args->Return(callback.Run(a1, a2, a3, a4, a5));
    135   }
    136 };
    137 template<typename P1, typename P2, typename P3, typename P4, typename P5>
    138 struct Invoker<void, P1, P2, P3, P4, P5, void> {
    139   inline static void Go(
    140       Arguments* args,
    141       const base::Callback<void(P1, P2, P3, P4, P5)>& callback,
    142       const P1& a1,
    143       const P2& a2,
    144       const P3& a3,
    145       const P4& a4,
    146       const P5& a5) {
    147     callback.Run(a1, a2, a3, a4, a5);
    148   }
    149 };
    150 
    151 template<typename R, typename P1, typename P2, typename P3, typename P4>
    152 struct Invoker<R, P1, P2, P3, P4, void, void> {
    153   inline static void Go(
    154       Arguments* args,
    155       const base::Callback<R(P1, P2, P3, P4)>& callback,
    156       const P1& a1,
    157       const P2& a2,
    158       const P3& a3,
    159       const P4& a4) {
    160     args->Return(callback.Run(a1, a2, a3, a4));
    161   }
    162 };
    163 template<typename P1, typename P2, typename P3, typename P4>
    164 struct Invoker<void, P1, P2, P3, P4, void, void> {
    165   inline static void Go(
    166       Arguments* args,
    167       const base::Callback<void(P1, P2, P3, P4)>& callback,
    168       const P1& a1,
    169       const P2& a2,
    170       const P3& a3,
    171       const P4& a4) {
    172     callback.Run(a1, a2, a3, a4);
    173   }
    174 };
    175 
    176 template<typename R, typename P1, typename P2, typename P3>
    177 struct Invoker<R, P1, P2, P3, void, void, void> {
    178   inline static void Go(
    179       Arguments* args,
    180       const base::Callback<R(P1, P2, P3)>& callback,
    181       const P1& a1,
    182       const P2& a2,
    183       const P3& a3) {
    184     args->Return(callback.Run(a1, a2, a3));
    185   }
    186 };
    187 template<typename P1, typename P2, typename P3>
    188 struct Invoker<void, P1, P2, P3, void, void, void> {
    189   inline static void Go(
    190       Arguments* args,
    191       const base::Callback<void(P1, P2, P3)>& callback,
    192       const P1& a1,
    193       const P2& a2,
    194       const P3& a3) {
    195     callback.Run(a1, a2, a3);
    196   }
    197 };
    198 
    199 template<typename R, typename P1, typename P2>
    200 struct Invoker<R, P1, P2, void, void, void, void> {
    201   inline static void Go(
    202       Arguments* args,
    203       const base::Callback<R(P1, P2)>& callback,
    204       const P1& a1,
    205       const P2& a2) {
    206     args->Return(callback.Run(a1, a2));
    207   }
    208 };
    209 template<typename P1, typename P2>
    210 struct Invoker<void, P1, P2, void, void, void, void> {
    211   inline static void Go(
    212       Arguments* args,
    213       const base::Callback<void(P1, P2)>& callback,
    214       const P1& a1,
    215       const P2& a2) {
    216     callback.Run(a1, a2);
    217   }
    218 };
    219 
    220 template<typename R, typename P1>
    221 struct Invoker<R, P1, void, void, void, void, void> {
    222   inline static void Go(
    223       Arguments* args,
    224       const base::Callback<R(P1)>& callback,
    225       const P1& a1) {
    226     args->Return(callback.Run(a1));
    227   }
    228 };
    229 template<typename P1>
    230 struct Invoker<void, P1, void, void, void, void, void> {
    231   inline static void Go(
    232       Arguments* args,
    233       const base::Callback<void(P1)>& callback,
    234       const P1& a1) {
    235     callback.Run(a1);
    236   }
    237 };
    238 
    239 template<typename R>
    240 struct Invoker<R, void, void, void, void, void, void> {
    241   inline static void Go(
    242       Arguments* args,
    243       const base::Callback<R()>& callback) {
    244     args->Return(callback.Run());
    245   }
    246 };
    247 template<>
    248 struct Invoker<void, void, void, void, void, void, void> {
    249   inline static void Go(
    250       Arguments* args,
    251       const base::Callback<void()>& callback) {
    252     callback.Run();
    253   }
    254 };
    255 
    256 
    257 template<typename T>
    258 bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
    259                      T* result) {
    260   if (is_first && (create_flags & HolderIsFirstArgument) != 0) {
    261     return args->GetHolder(result);
    262   } else {
    263     return args->GetNext(result);
    264   }
    265 }
    266 
    267 // For advanced use cases, we allow callers to request the unparsed Arguments
    268 // object and poke around in it directly.
    269 inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
    270                             Arguments* result) {
    271   *result = *args;
    272   return true;
    273 }
    274 inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
    275                             Arguments** result) {
    276   *result = args;
    277   return true;
    278 }
    279 
    280 // It's common for clients to just need the isolate, so we make that easy.
    281 inline bool GetNextArgument(Arguments* args, int create_flags,
    282                             bool is_first, v8::Isolate** result) {
    283   *result = args->isolate();
    284   return true;
    285 }
    286 
    287 
    288 // DispatchToCallback converts all the JavaScript arguments to C++ types and
    289 // invokes the base::Callback.
    290 template<typename Sig>
    291 struct Dispatcher {
    292 };
    293 
    294 template<typename R>
    295 struct Dispatcher<R()> {
    296   static void DispatchToCallback(
    297       const v8::FunctionCallbackInfo<v8::Value>& info) {
    298     Arguments args(info);
    299     v8::Handle<v8::External> v8_holder;
    300     CHECK(args.GetData(&v8_holder));
    301     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    302         v8_holder->Value());
    303 
    304     typedef CallbackHolder<R()> HolderT;
    305     HolderT* holder = static_cast<HolderT*>(holder_base);
    306 
    307     Invoker<R>::Go(&args, holder->callback);
    308   }
    309 };
    310 
    311 template<typename R, typename P1>
    312 struct Dispatcher<R(P1)> {
    313   static void DispatchToCallback(
    314       const v8::FunctionCallbackInfo<v8::Value>& info) {
    315     Arguments args(info);
    316     v8::Handle<v8::External> v8_holder;
    317     CHECK(args.GetData(&v8_holder));
    318     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    319         v8_holder->Value());
    320 
    321     typedef CallbackHolder<R(P1)> HolderT;
    322     HolderT* holder = static_cast<HolderT*>(holder_base);
    323 
    324     typename CallbackParamTraits<P1>::LocalType a1;
    325     if (!GetNextArgument(&args, holder->flags, true, &a1)) {
    326       args.ThrowError();
    327       return;
    328     }
    329 
    330     Invoker<R, P1>::Go(&args, holder->callback, a1);
    331   }
    332 };
    333 
    334 template<typename R, typename P1, typename P2>
    335 struct Dispatcher<R(P1, P2)> {
    336   static void DispatchToCallback(
    337       const v8::FunctionCallbackInfo<v8::Value>& info) {
    338     Arguments args(info);
    339     v8::Handle<v8::External> v8_holder;
    340     CHECK(args.GetData(&v8_holder));
    341     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    342         v8_holder->Value());
    343 
    344     typedef CallbackHolder<R(P1, P2)> HolderT;
    345     HolderT* holder = static_cast<HolderT*>(holder_base);
    346 
    347     typename CallbackParamTraits<P1>::LocalType a1;
    348     typename CallbackParamTraits<P2>::LocalType a2;
    349     if (!GetNextArgument(&args, holder->flags, true, &a1) ||
    350         !GetNextArgument(&args, holder->flags, false, &a2)) {
    351       args.ThrowError();
    352       return;
    353     }
    354 
    355     Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2);
    356   }
    357 };
    358 
    359 template<typename R, typename P1, typename P2, typename P3>
    360 struct Dispatcher<R(P1, P2, P3)> {
    361   static void DispatchToCallback(
    362       const v8::FunctionCallbackInfo<v8::Value>& info) {
    363     Arguments args(info);
    364     v8::Handle<v8::External> v8_holder;
    365     CHECK(args.GetData(&v8_holder));
    366     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    367         v8_holder->Value());
    368 
    369     typedef CallbackHolder<R(P1, P2, P3)> HolderT;
    370     HolderT* holder = static_cast<HolderT*>(holder_base);
    371 
    372     typename CallbackParamTraits<P1>::LocalType a1;
    373     typename CallbackParamTraits<P2>::LocalType a2;
    374     typename CallbackParamTraits<P3>::LocalType a3;
    375     if (!GetNextArgument(&args, holder->flags, true, &a1) ||
    376         !GetNextArgument(&args, holder->flags, false, &a2) ||
    377         !GetNextArgument(&args, holder->flags, false, &a3)) {
    378       args.ThrowError();
    379       return;
    380     }
    381 
    382     Invoker<R, P1, P2, P3>::Go(&args, holder->callback, a1, a2, a3);
    383   }
    384 };
    385 
    386 template<typename R, typename P1, typename P2, typename P3, typename P4>
    387 struct Dispatcher<R(P1, P2, P3, P4)> {
    388   static void DispatchToCallback(
    389       const v8::FunctionCallbackInfo<v8::Value>& info) {
    390     Arguments args(info);
    391     v8::Handle<v8::External> v8_holder;
    392     CHECK(args.GetData(&v8_holder));
    393     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    394         v8_holder->Value());
    395 
    396     typedef CallbackHolder<R(P1, P2, P3, P4)> HolderT;
    397     HolderT* holder = static_cast<HolderT*>(holder_base);
    398 
    399     typename CallbackParamTraits<P1>::LocalType a1;
    400     typename CallbackParamTraits<P2>::LocalType a2;
    401     typename CallbackParamTraits<P3>::LocalType a3;
    402     typename CallbackParamTraits<P4>::LocalType a4;
    403     if (!GetNextArgument(&args, holder->flags, true, &a1) ||
    404         !GetNextArgument(&args, holder->flags, false, &a2) ||
    405         !GetNextArgument(&args, holder->flags, false, &a3) ||
    406         !GetNextArgument(&args, holder->flags, false, &a4)) {
    407       args.ThrowError();
    408       return;
    409     }
    410 
    411     Invoker<R, P1, P2, P3, P4>::Go(&args, holder->callback, a1, a2, a3, a4);
    412   }
    413 };
    414 
    415 template<typename R, typename P1, typename P2, typename P3, typename P4,
    416     typename P5>
    417 struct Dispatcher<R(P1, P2, P3, P4, P5)> {
    418   static void DispatchToCallback(
    419       const v8::FunctionCallbackInfo<v8::Value>& info) {
    420     Arguments args(info);
    421     v8::Handle<v8::External> v8_holder;
    422     CHECK(args.GetData(&v8_holder));
    423     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    424         v8_holder->Value());
    425 
    426     typedef CallbackHolder<R(P1, P2, P3, P4, P5)> HolderT;
    427     HolderT* holder = static_cast<HolderT*>(holder_base);
    428 
    429     typename CallbackParamTraits<P1>::LocalType a1;
    430     typename CallbackParamTraits<P2>::LocalType a2;
    431     typename CallbackParamTraits<P3>::LocalType a3;
    432     typename CallbackParamTraits<P4>::LocalType a4;
    433     typename CallbackParamTraits<P5>::LocalType a5;
    434     if (!GetNextArgument(&args, holder->flags, true, &a1) ||
    435         !GetNextArgument(&args, holder->flags, false, &a2) ||
    436         !GetNextArgument(&args, holder->flags, false, &a3) ||
    437         !GetNextArgument(&args, holder->flags, false, &a4) ||
    438         !GetNextArgument(&args, holder->flags, false, &a5)) {
    439       args.ThrowError();
    440       return;
    441     }
    442 
    443     Invoker<R, P1, P2, P3, P4, P5>::Go(&args, holder->callback, a1, a2, a3, a4,
    444         a5);
    445   }
    446 };
    447 
    448 template<typename R, typename P1, typename P2, typename P3, typename P4,
    449     typename P5, typename P6>
    450 struct Dispatcher<R(P1, P2, P3, P4, P5, P6)> {
    451   static void DispatchToCallback(
    452       const v8::FunctionCallbackInfo<v8::Value>& info) {
    453     Arguments args(info);
    454     v8::Handle<v8::External> v8_holder;
    455     CHECK(args.GetData(&v8_holder));
    456     CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
    457         v8_holder->Value());
    458 
    459     typedef CallbackHolder<R(P1, P2, P3, P4, P5, P6)> HolderT;
    460     HolderT* holder = static_cast<HolderT*>(holder_base);
    461 
    462     typename CallbackParamTraits<P1>::LocalType a1;
    463     typename CallbackParamTraits<P2>::LocalType a2;
    464     typename CallbackParamTraits<P3>::LocalType a3;
    465     typename CallbackParamTraits<P4>::LocalType a4;
    466     typename CallbackParamTraits<P5>::LocalType a5;
    467     typename CallbackParamTraits<P6>::LocalType a6;
    468     if (!GetNextArgument(&args, holder->flags, true, &a1) ||
    469         !GetNextArgument(&args, holder->flags, false, &a2) ||
    470         !GetNextArgument(&args, holder->flags, false, &a3) ||
    471         !GetNextArgument(&args, holder->flags, false, &a4) ||
    472         !GetNextArgument(&args, holder->flags, false, &a5) ||
    473         !GetNextArgument(&args, holder->flags, false, &a6)) {
    474       args.ThrowError();
    475       return;
    476     }
    477 
    478     Invoker<R, P1, P2, P3, P4, P5, P6>::Go(&args, holder->callback, a1, a2, a3,
    479         a4, a5, a6);
    480   }
    481 };
    482 
    483 }  // namespace internal
    484 
    485 
    486 // CreateFunctionTemplate creates a v8::FunctionTemplate that will create
    487 // JavaScript functions that execute a provided C++ function or base::Callback.
    488 // JavaScript arguments are automatically converted via gin::Converter, as is
    489 // the return value of the C++ function, if any.
    490 template<typename Sig>
    491 v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
    492     v8::Isolate* isolate, const base::Callback<Sig> callback,
    493     int callback_flags = 0) {
    494   typedef internal::CallbackHolder<Sig> HolderT;
    495   HolderT* holder = new HolderT(isolate, callback, callback_flags);
    496 
    497   return v8::FunctionTemplate::New(
    498       isolate,
    499       &internal::Dispatcher<Sig>::DispatchToCallback,
    500       ConvertToV8<v8::Handle<v8::External> >(isolate,
    501                                              holder->GetHandle(isolate)));
    502 }
    503 
    504 // CreateFunctionHandler installs a CallAsFunction handler on the given
    505 // object template that forwards to a provided C++ function or base::Callback.
    506 template<typename Sig>
    507 void CreateFunctionHandler(v8::Isolate* isolate,
    508                            v8::Local<v8::ObjectTemplate> tmpl,
    509                            const base::Callback<Sig> callback,
    510                            int callback_flags = 0) {
    511   typedef internal::CallbackHolder<Sig> HolderT;
    512   HolderT* holder = new HolderT(isolate, callback, callback_flags);
    513   tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback,
    514                                  ConvertToV8<v8::Handle<v8::External> >(
    515                                      isolate, holder->GetHandle(isolate)));
    516 }
    517 
    518 }  // namespace gin
    519 
    520 #endif  // GIN_FUNCTION_TEMPLATE_H_
    521