• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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