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
21namespace gin {
22
23class PerIsolateData;
24
25enum CreateFunctionTemplateFlags {
26  HolderIsFirstArgument = 1 << 0,
27};
28
29namespace internal {
30
31template<typename T>
32struct CallbackParamTraits {
33  typedef T LocalType;
34};
35template<typename T>
36struct CallbackParamTraits<const T&> {
37  typedef T LocalType;
38};
39template<typename T>
40struct 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.
51class 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
68template<typename Sig>
69class 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.
91template<typename R, typename P1 = void, typename P2 = void,
92    typename P3 = void, typename P4 = void, typename P5 = void,
93    typename P6 = void>
94struct 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};
107template<typename P1, typename P2, typename P3, typename P4, typename P5,
108    typename P6>
109struct 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
123template<typename R, typename P1, typename P2, typename P3, typename P4,
124    typename P5>
125struct 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};
137template<typename P1, typename P2, typename P3, typename P4, typename P5>
138struct 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
151template<typename R, typename P1, typename P2, typename P3, typename P4>
152struct 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};
163template<typename P1, typename P2, typename P3, typename P4>
164struct 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
176template<typename R, typename P1, typename P2, typename P3>
177struct 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};
187template<typename P1, typename P2, typename P3>
188struct 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
199template<typename R, typename P1, typename P2>
200struct 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};
209template<typename P1, typename P2>
210struct 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
220template<typename R, typename P1>
221struct 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};
229template<typename P1>
230struct 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
239template<typename R>
240struct 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};
247template<>
248struct 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
257template<typename T>
258bool 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.
269inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
270                            Arguments* result) {
271  *result = *args;
272  return true;
273}
274inline 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.
281inline 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.
290template<typename Sig>
291struct Dispatcher {
292};
293
294template<typename R>
295struct 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
311template<typename R, typename P1>
312struct 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
334template<typename R, typename P1, typename P2>
335struct 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
359template<typename R, typename P1, typename P2, typename P3>
360struct 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
386template<typename R, typename P1, typename P2, typename P3, typename P4>
387struct 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
415template<typename R, typename P1, typename P2, typename P3, typename P4,
416    typename P5>
417struct 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
448template<typename R, typename P1, typename P2, typename P3, typename P4,
449    typename P5, typename P6>
450struct 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.
490template<typename Sig>
491v8::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.
506template<typename Sig>
507void 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