Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: gin/function_template.h

Issue 671433004: [gin] Use variadic templates in gin/function_template.h (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added missing exception throwing. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gin/function_template.h.pump » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // This file was GENERATED by command: 1 // 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.
2 // pump.py function_template.h.pump 2 // Use of this source code is governed by a BSD-style license that can be
3 // DO NOT EDIT BY HAND!!! 3 // found in the LICENSE file.
4 4
5
6
7 #ifndef GIN_FUNCTION_TEMPLATE_H_ 5 #ifndef GIN_FUNCTION_TEMPLATE_H_
8 #define GIN_FUNCTION_TEMPLATE_H_ 6 #define GIN_FUNCTION_TEMPLATE_H_
9 7
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" 8 #include "base/callback.h"
15 #include "base/logging.h" 9 #include "base/logging.h"
16 #include "gin/arguments.h" 10 #include "gin/arguments.h"
17 #include "gin/converter.h" 11 #include "gin/converter.h"
18 #include "gin/gin_export.h" 12 #include "gin/gin_export.h"
19 #include "v8/include/v8.h" 13 #include "v8/include/v8.h"
20 14
21 namespace gin { 15 namespace gin {
22 16
23 class PerIsolateData; 17 class PerIsolateData;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 int flags) 67 int flags)
74 : CallbackHolderBase(isolate), callback(callback), flags(flags) {} 68 : CallbackHolderBase(isolate), callback(callback), flags(flags) {}
75 base::Callback<Sig> callback; 69 base::Callback<Sig> callback;
76 int flags; 70 int flags;
77 private: 71 private:
78 virtual ~CallbackHolder() {} 72 virtual ~CallbackHolder() {}
79 73
80 DISALLOW_COPY_AND_ASSIGN(CallbackHolder); 74 DISALLOW_COPY_AND_ASSIGN(CallbackHolder);
81 }; 75 };
82 76
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> 77 template<typename T>
258 bool GetNextArgument(Arguments* args, int create_flags, bool is_first, 78 bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
259 T* result) { 79 T* result) {
260 if (is_first && (create_flags & HolderIsFirstArgument) != 0) { 80 if (is_first && (create_flags & HolderIsFirstArgument) != 0) {
261 return args->GetHolder(result); 81 return args->GetHolder(result);
262 } else { 82 } else {
263 return args->GetNext(result); 83 return args->GetNext(result);
264 } 84 }
265 } 85 }
266 86
(...skipping 10 matching lines...) Expand all
277 return true; 97 return true;
278 } 98 }
279 99
280 // It's common for clients to just need the isolate, so we make that easy. 100 // It's common for clients to just need the isolate, so we make that easy.
281 inline bool GetNextArgument(Arguments* args, int create_flags, 101 inline bool GetNextArgument(Arguments* args, int create_flags,
282 bool is_first, v8::Isolate** result) { 102 bool is_first, v8::Isolate** result) {
283 *result = args->isolate(); 103 *result = args->isolate();
284 return true; 104 return true;
285 } 105 }
286 106
107 // Classes for generating and storing an argument pack of integer indices
108 // (based on well-known "indices trick", see: http://goo.gl/bKKojn):
109 template <size_t... indices>
110 struct IndicesHolder {};
111
112 template <size_t requested_index, size_t... indices>
113 struct IndicesGenerator {
114 using type = typename IndicesGenerator<requested_index - 1,
115 requested_index - 1,
116 indices...>::type;
117 };
118 template <size_t... indices>
119 struct IndicesGenerator<0, indices...> {
120 using type = IndicesHolder<indices...>;
121 };
122
123 // Class template for extracting and storing single argument for callback
124 // at position |index|.
125 template <size_t index, typename ArgType>
126 struct ArgumentHolder {
127 using ArgLocalType = typename CallbackParamTraits<ArgType>::LocalType;
128
129 ArgLocalType value;
130 bool ok;
131
132 ArgumentHolder(Arguments* args, int create_flags)
133 : 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
134 if (!ok)
135 args->ThrowError();
136 }
137 };
138
139 // Class template for converting arguments from JavaScript to C++ and running
140 // the callback with them.
141 template <typename IndicesType, typename... ArgTypes>
142 class Invoker {};
143
144 template <size_t... indices, typename... ArgTypes>
145 class Invoker<IndicesHolder<indices...>, ArgTypes...>
146 : public ArgumentHolder<indices, ArgTypes>... {
147 public:
148 // Invoker<> inherits from ArgumentHolder<> for each argument.
149 // C++ has always been strict about the class initialization order,
150 // so it is guaranteed ArgumentHolders will be initialized (and thus, will
151 // extract arguments from Arguments) in the right order.
152 Invoker(Arguments* args, int create_flags)
153 : ArgumentHolder<indices, ArgTypes>(args, create_flags)...,
154 args_(args) {}
155
156 bool IsOK() {
157 return And(ArgumentHolder<indices, ArgTypes>::ok...);
158 }
159
160 template <typename ReturnType>
161 void DispatchToCallback(base::Callback<ReturnType(ArgTypes...)> callback) {
162 args_->Return(callback.Run(ArgumentHolder<indices, ArgTypes>::value...));
163 }
164
165 // In C++, you can declare the function foo(void), but you can't pass a void
166 // expression to foo. As a result, we must specialize the case of Callbacks
167 // that have the void return type.
168 void DispatchToCallback(base::Callback<void(ArgTypes...)> callback) {
169 callback.Run(ArgumentHolder<indices, ArgTypes>::value...);
170 }
171
172 private:
173 static bool And() { return true; }
174 template <typename... T>
175 static bool And(bool arg1, T... args) {
176 return arg1 && And(args...);
177 }
178
179 Arguments* args_;
180 };
287 181
288 // DispatchToCallback converts all the JavaScript arguments to C++ types and 182 // DispatchToCallback converts all the JavaScript arguments to C++ types and
289 // invokes the base::Callback. 183 // invokes the base::Callback.
290 template<typename Sig> 184 template <typename Sig>
291 struct Dispatcher { 185 struct Dispatcher {};
292 };
293 186
294 template<typename R> 187 template <typename ReturnType, typename... ArgTypes>
295 struct Dispatcher<R()> { 188 struct Dispatcher<ReturnType(ArgTypes...)> {
296 static void DispatchToCallback( 189 static void DispatchToCallback(
297 const v8::FunctionCallbackInfo<v8::Value>& info) { 190 const v8::FunctionCallbackInfo<v8::Value>& info) {
298 Arguments args(info); 191 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; 192 v8::Handle<v8::External> v8_holder;
455 CHECK(args.GetData(&v8_holder)); 193 CHECK(args.GetData(&v8_holder));
456 CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>( 194 CallbackHolderBase* holder_base = reinterpret_cast<CallbackHolderBase*>(
457 v8_holder->Value()); 195 v8_holder->Value());
458 196
459 typedef CallbackHolder<R(P1, P2, P3, P4, P5, P6)> HolderT; 197 typedef CallbackHolder<ReturnType(ArgTypes...)> HolderT;
460 HolderT* holder = static_cast<HolderT*>(holder_base); 198 HolderT* holder = static_cast<HolderT*>(holder_base);
461 199
462 typename CallbackParamTraits<P1>::LocalType a1; 200 using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type;
463 typename CallbackParamTraits<P2>::LocalType a2; 201 Invoker<Indices, ArgTypes...> invoker(&args, holder->flags);
464 typename CallbackParamTraits<P3>::LocalType a3; 202 if (invoker.IsOK())
465 typename CallbackParamTraits<P4>::LocalType a4; 203 invoker.DispatchToCallback(holder->callback);
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 } 204 }
481 }; 205 };
482 206
483 } // namespace internal 207 } // namespace internal
484 208
485 209
486 // CreateFunctionTemplate creates a v8::FunctionTemplate that will create 210 // CreateFunctionTemplate creates a v8::FunctionTemplate that will create
487 // JavaScript functions that execute a provided C++ function or base::Callback. 211 // JavaScript functions that execute a provided C++ function or base::Callback.
488 // JavaScript arguments are automatically converted via gin::Converter, as is 212 // JavaScript arguments are automatically converted via gin::Converter, as is
489 // the return value of the C++ function, if any. 213 // the return value of the C++ function, if any.
(...skipping 21 matching lines...) Expand all
511 typedef internal::CallbackHolder<Sig> HolderT; 235 typedef internal::CallbackHolder<Sig> HolderT;
512 HolderT* holder = new HolderT(isolate, callback, callback_flags); 236 HolderT* holder = new HolderT(isolate, callback, callback_flags);
513 tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback, 237 tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback,
514 ConvertToV8<v8::Handle<v8::External> >( 238 ConvertToV8<v8::Handle<v8::External> >(
515 isolate, holder->GetHandle(isolate))); 239 isolate, holder->GetHandle(isolate)));
516 } 240 }
517 241
518 } // namespace gin 242 } // namespace gin
519 243
520 #endif // GIN_FUNCTION_TEMPLATE_H_ 244 #endif // GIN_FUNCTION_TEMPLATE_H_
OLDNEW
« no previous file with comments | « no previous file | gin/function_template.h.pump » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698