Flutter Engine
dart_args.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIB_TONIC_DART_ARGS_H_
6 #define LIB_TONIC_DART_ARGS_H_
7 
8 #include <type_traits>
9 #include <utility>
10 
11 #include "third_party/dart/runtime/include/dart_api.h"
13 #include "tonic/dart_wrappable.h"
14 
15 namespace tonic {
16 
18  public:
19  DartArgIterator(Dart_NativeArguments args, int start_index = 1)
20  : args_(args), index_(start_index), had_exception_(false) {}
21 
22  template <typename T>
23  T GetNext() {
24  if (had_exception_)
25  return T();
26  Dart_Handle exception = nullptr;
27  T arg = DartConverter<T>::FromArguments(args_, index_++, exception);
28  if (exception) {
29  had_exception_ = true;
30  Dart_ThrowException(exception);
31  }
32  return arg;
33  }
34 
35  bool had_exception() const { return had_exception_; }
36 
37  Dart_NativeArguments args() const { return args_; }
38 
39  private:
40  Dart_NativeArguments args_;
41  int index_;
42  bool had_exception_;
43 
44  TONIC_DISALLOW_COPY_AND_ASSIGN(DartArgIterator);
45 };
46 
47 // Classes for generating and storing an argument pack of integer indices
48 // (based on well-known "indices trick", see: http://goo.gl/bKKojn):
49 template <size_t... indices>
50 struct IndicesHolder {};
51 
52 template <size_t requested_index, size_t... indices>
54  using type = typename IndicesGenerator<requested_index - 1,
55  requested_index - 1,
56  indices...>::type;
57 };
58 
59 template <size_t... indices>
60 struct IndicesGenerator<0, indices...> {
61  using type = IndicesHolder<indices...>;
62 };
63 
64 template <typename T>
66 
67 template <typename ResultType, typename... ArgTypes>
68 struct IndicesForSignature<ResultType (*)(ArgTypes...)> {
69  static const size_t count = sizeof...(ArgTypes);
71 };
72 
73 template <typename C, typename ResultType, typename... ArgTypes>
74 struct IndicesForSignature<ResultType (C::*)(ArgTypes...)> {
75  static const size_t count = sizeof...(ArgTypes);
77 };
78 
79 template <typename C, typename ResultType, typename... ArgTypes>
80 struct IndicesForSignature<ResultType (C::*)(ArgTypes...) const> {
81  static const size_t count = sizeof...(ArgTypes);
83 };
84 
85 template <size_t index, typename ArgType>
86 struct DartArgHolder {
87  using ValueType = typename std::remove_const<
88  typename std::remove_reference<ArgType>::type>::type;
89 
91 
93  : value(it->GetNext<ValueType>()) {}
94 };
95 
96 template <typename T>
97 void DartReturn(T result, Dart_NativeArguments args) {
98  DartConverter<T>::SetReturnValue(args, std::move(result));
99 }
100 
101 template <typename IndicesType, typename T>
102 class DartDispatcher {};
103 
104 template <size_t... indices, typename... ArgTypes>
105 struct DartDispatcher<IndicesHolder<indices...>, void (*)(ArgTypes...)>
107  using FunctionPtr = void (*)(ArgTypes...);
108 
110 
112  : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
113 
114  void Dispatch(FunctionPtr func) {
116  }
117 };
118 
119 template <size_t... indices, typename ResultType, typename... ArgTypes>
120 struct DartDispatcher<IndicesHolder<indices...>, ResultType (*)(ArgTypes...)>
122  using FunctionPtr = ResultType (*)(ArgTypes...);
123  using CtorResultType = ResultType;
124 
126 
128  : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
129 
130  void Dispatch(FunctionPtr func) {
132  it_->args());
133  }
134 
135  ResultType DispatchCtor(FunctionPtr func) {
136  return (*func)(DartArgHolder<indices, ArgTypes>::value...);
137  }
138 };
139 
140 template <size_t... indices, typename C, typename... ArgTypes>
141 struct DartDispatcher<IndicesHolder<indices...>, void (C::*)(ArgTypes...)>
142  : public DartArgHolder<indices, ArgTypes>... {
143  using FunctionPtr = void (C::*)(ArgTypes...);
144 
146 
148  : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
149 
150  void Dispatch(FunctionPtr func) {
151  (GetReceiver<C>(it_->args())->*func)(
153  }
154 };
155 
156 template <size_t... indices,
157  typename C,
158  typename ReturnType,
159  typename... ArgTypes>
160 struct DartDispatcher<IndicesHolder<indices...>,
161  ReturnType (C::*)(ArgTypes...) const>
162  : public DartArgHolder<indices, ArgTypes>... {
163  using FunctionPtr = ReturnType (C::*)(ArgTypes...) const;
164 
166 
168  : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
169 
170  void Dispatch(FunctionPtr func) {
171  DartReturn((GetReceiver<C>(it_->args())->*func)(
173  it_->args());
174  }
175 };
176 
177 template <size_t... indices,
178  typename C,
179  typename ResultType,
180  typename... ArgTypes>
181 struct DartDispatcher<IndicesHolder<indices...>, ResultType (C::*)(ArgTypes...)>
182  : public DartArgHolder<indices, ArgTypes>... {
183  using FunctionPtr = ResultType (C::*)(ArgTypes...);
184 
186 
188  : DartArgHolder<indices, ArgTypes>(it)..., it_(it) {}
189 
190  void Dispatch(FunctionPtr func) {
191  DartReturn((GetReceiver<C>(it_->args())->*func)(
193  it_->args());
194  }
195 };
196 
197 template <typename Sig>
198 void DartCall(Sig func, Dart_NativeArguments args) {
199  DartArgIterator it(args);
200  using Indices = typename IndicesForSignature<Sig>::type;
201  DartDispatcher<Indices, Sig> decoder(&it);
202  if (it.had_exception())
203  return;
204  decoder.Dispatch(func);
205 }
206 
207 template <typename Sig>
208 void DartCallStatic(Sig func, Dart_NativeArguments args) {
209  DartArgIterator it(args, 0);
210  using Indices = typename IndicesForSignature<Sig>::type;
211  DartDispatcher<Indices, Sig> decoder(&it);
212  if (it.had_exception())
213  return;
214  decoder.Dispatch(func);
215 }
216 
217 template <typename Sig>
218 void DartCallConstructor(Sig func, Dart_NativeArguments args) {
219  DartArgIterator it(args);
220  using Indices = typename IndicesForSignature<Sig>::type;
221  using Wrappable = typename DartDispatcher<Indices, Sig>::CtorResultType;
222  Wrappable wrappable;
223  {
224  DartDispatcher<Indices, Sig> decoder(&it);
225  if (it.had_exception())
226  return;
227  wrappable = decoder.DispatchCtor(func);
228  }
229 
230  Dart_Handle wrapper = Dart_GetNativeArgument(args, 0);
231  TONIC_CHECK(!LogIfError(wrapper));
232 
233  intptr_t native_fields[DartWrappable::kNumberOfNativeFields];
234  TONIC_CHECK(!LogIfError(Dart_GetNativeFieldsOfArgument(
235  args, 0, DartWrappable::kNumberOfNativeFields, native_fields)));
236  TONIC_CHECK(!native_fields[DartWrappable::kPeerIndex]);
238 
239  wrappable->AssociateWithDartWrapper(wrapper);
240 }
241 
242 } // namespace tonic
243 
244 #endif // LIB_TONIC_DART_ARGS_H_
typename IndicesGenerator< requested_index - 1, requested_index - 1, indices... >::type type
Definition: dart_args.h:56
typename std::remove_const< typename std::remove_reference< ArgType >::type >::type ValueType
Definition: dart_args.h:88
void DartCall(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:198
void DartCallStatic(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:208
void DartCallConstructor(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:218
typename IndicesGenerator< count >::type type
Definition: dart_args.h:76
Dart_NativeArguments args() const
Definition: dart_args.h:37
DartArgIterator(Dart_NativeArguments args, int start_index=1)
Definition: dart_args.h:19
#define TONIC_CHECK(condition)
Definition: macros.h:23
typename IndicesGenerator< count >::type type
Definition: dart_args.h:82
bool had_exception() const
Definition: dart_args.h:35
typename IndicesGenerator< count >::type type
Definition: dart_args.h:70
bool LogIfError(Dart_Handle handle)
Definition: dart_error.cc:15
DartArgHolder(DartArgIterator *it)
Definition: dart_args.h:92
void DartReturn(T result, Dart_NativeArguments args)
Definition: dart_args.h:97