@crossbind/core-embind-jsi 2.0.0-beta.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +16 -0
- package/cpp/CMakeLists.txt +16 -0
- package/cpp/src/emscripten/bind.cpp +1158 -0
- package/cpp/src/emscripten/bind.h +2880 -0
- package/cpp/src/emscripten/em_macros.h +43 -0
- package/cpp/src/emscripten/val.h +708 -0
- package/cpp/src/emscripten/wire.h +610 -0
- package/crossbind.config.mjs +5 -0
- package/js/embind.js +4908 -0
- package/package.json +27 -0
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2012 The Emscripten Authors. All rights reserved.
|
|
3
|
+
* Emscripten is available under two separate licenses, the MIT license and the
|
|
4
|
+
* University of Illinois/NCSA Open Source License. Both these licenses can be
|
|
5
|
+
* found in the LICENSE file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#if __cplusplus < 201103L
|
|
11
|
+
#error Including <./wire.h> requires building with -std=c++11 or newer!
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
// A value moving between JavaScript and C++ has three representations:
|
|
15
|
+
// - The original JS value: a String
|
|
16
|
+
// - The native on-the-wire value: a stack-allocated char*, say
|
|
17
|
+
// - The C++ value: std::string
|
|
18
|
+
//
|
|
19
|
+
// We'll call the on-the-wire type WireType.
|
|
20
|
+
|
|
21
|
+
#include <cstdio>
|
|
22
|
+
#include <cstdlib>
|
|
23
|
+
#include <memory>
|
|
24
|
+
#include <optional>
|
|
25
|
+
#include <string>
|
|
26
|
+
|
|
27
|
+
#include <jsi/jsi.h>
|
|
28
|
+
|
|
29
|
+
// #include <android/log.h>
|
|
30
|
+
// #define APPNAME "react-native-crossbind"
|
|
31
|
+
|
|
32
|
+
#define EMSCRIPTEN_ALWAYS_INLINE __attribute__((always_inline))
|
|
33
|
+
|
|
34
|
+
#ifndef EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES
|
|
35
|
+
#define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 1
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
namespace emscripten {
|
|
39
|
+
|
|
40
|
+
#if EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES
|
|
41
|
+
constexpr bool has_unbound_type_names = true;
|
|
42
|
+
#else
|
|
43
|
+
constexpr bool has_unbound_type_names = false;
|
|
44
|
+
#endif
|
|
45
|
+
|
|
46
|
+
namespace internal {
|
|
47
|
+
|
|
48
|
+
typedef const void* TYPEID;
|
|
49
|
+
|
|
50
|
+
// Defined in bind.cpp: registers a JS-side ArrayBuffer window covering `ptr` so
|
|
51
|
+
// heap reads on values we hand out by pointer cannot miss every window.
|
|
52
|
+
void ensureWindowFor(uint64_t ptr);
|
|
53
|
+
|
|
54
|
+
// We don't need the full std::type_info implementation. We
|
|
55
|
+
// just need a unique identifier per type and polymorphic type
|
|
56
|
+
// identification.
|
|
57
|
+
|
|
58
|
+
template<typename T>
|
|
59
|
+
struct CanonicalizedID {
|
|
60
|
+
static char c;
|
|
61
|
+
static constexpr TYPEID get() {
|
|
62
|
+
return &c;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
template<typename T>
|
|
67
|
+
char CanonicalizedID<T>::c;
|
|
68
|
+
|
|
69
|
+
template<typename T>
|
|
70
|
+
struct Canonicalized {
|
|
71
|
+
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
template<typename T>
|
|
75
|
+
struct LightTypeID {
|
|
76
|
+
static constexpr TYPEID get() {
|
|
77
|
+
if (has_unbound_type_names) {
|
|
78
|
+
#if __has_feature(cxx_rtti)
|
|
79
|
+
return &typeid(T);
|
|
80
|
+
#else
|
|
81
|
+
static_assert(!has_unbound_type_names,
|
|
82
|
+
"Unbound type names are illegal with RTTI disabled. "
|
|
83
|
+
"Either add -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 to or remove -fno-rtti "
|
|
84
|
+
"from the compiler arguments");
|
|
85
|
+
#endif
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
typedef typename Canonicalized<T>::type C;
|
|
89
|
+
return CanonicalizedID<C>::get();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
template<typename T>
|
|
94
|
+
constexpr TYPEID getLightTypeID(const T& value) {
|
|
95
|
+
if (has_unbound_type_names) {
|
|
96
|
+
#if __has_feature(cxx_rtti)
|
|
97
|
+
return &typeid(value);
|
|
98
|
+
#else
|
|
99
|
+
static_assert(!has_unbound_type_names,
|
|
100
|
+
"Unbound type names are illegal with RTTI disabled. "
|
|
101
|
+
"Either add -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 to or remove -fno-rtti "
|
|
102
|
+
"from the compiler arguments");
|
|
103
|
+
#endif
|
|
104
|
+
}
|
|
105
|
+
return LightTypeID<T>::get();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The second typename is an unused stub so it's possible to
|
|
109
|
+
// specialize groups of classes via SFINAE.
|
|
110
|
+
template<typename T, typename = void>
|
|
111
|
+
struct TypeID {
|
|
112
|
+
static constexpr TYPEID get() {
|
|
113
|
+
return LightTypeID<T>::get();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
template<typename T>
|
|
118
|
+
struct TypeID<std::unique_ptr<T>> {
|
|
119
|
+
static constexpr TYPEID get() {
|
|
120
|
+
return TypeID<T>::get();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
template<typename T>
|
|
125
|
+
struct TypeID<T*> {
|
|
126
|
+
static_assert(!std::is_pointer<T*>::value, "Implicitly binding raw pointers is illegal. Specify allow_raw_pointer<arg<?>>");
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
template<typename T>
|
|
130
|
+
struct AllowedRawPointer {
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
template<typename T>
|
|
134
|
+
struct TypeID<AllowedRawPointer<T>> {
|
|
135
|
+
static constexpr TYPEID get() {
|
|
136
|
+
return LightTypeID<T*>::get();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// ExecutePolicies<>
|
|
141
|
+
|
|
142
|
+
template<typename... Policies>
|
|
143
|
+
struct ExecutePolicies;
|
|
144
|
+
|
|
145
|
+
template<>
|
|
146
|
+
struct ExecutePolicies<> {
|
|
147
|
+
template<typename T, int Index>
|
|
148
|
+
struct With {
|
|
149
|
+
typedef T type;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
template<typename Policy, typename... Remaining>
|
|
154
|
+
struct ExecutePolicies<Policy, Remaining...> {
|
|
155
|
+
template<typename T, int Index>
|
|
156
|
+
struct With {
|
|
157
|
+
typedef typename Policy::template Transform<
|
|
158
|
+
typename ExecutePolicies<Remaining...>::template With<T, Index>::type,
|
|
159
|
+
Index
|
|
160
|
+
>::type type;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// TypeList<>
|
|
165
|
+
|
|
166
|
+
template<typename...>
|
|
167
|
+
struct TypeList {};
|
|
168
|
+
|
|
169
|
+
// Cons :: T, TypeList<types...> -> Cons<T, types...>
|
|
170
|
+
|
|
171
|
+
template<typename First, typename TypeList>
|
|
172
|
+
struct Cons;
|
|
173
|
+
|
|
174
|
+
template<typename First, typename... Rest>
|
|
175
|
+
struct Cons<First, TypeList<Rest...>> {
|
|
176
|
+
typedef TypeList<First, Rest...> type;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Apply :: T, TypeList<types...> -> T<types...>
|
|
180
|
+
|
|
181
|
+
template<template<typename...> class Output, typename TypeList>
|
|
182
|
+
struct Apply;
|
|
183
|
+
|
|
184
|
+
template<template<typename...> class Output, typename... Types>
|
|
185
|
+
struct Apply<Output, TypeList<Types...>> {
|
|
186
|
+
typedef Output<Types...> type;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// MapWithIndex_
|
|
190
|
+
|
|
191
|
+
template<template<size_t, typename> class Mapper, size_t CurrentIndex, typename... Args>
|
|
192
|
+
struct MapWithIndex_;
|
|
193
|
+
|
|
194
|
+
template<template<size_t, typename> class Mapper, size_t CurrentIndex, typename First, typename... Rest>
|
|
195
|
+
struct MapWithIndex_<Mapper, CurrentIndex, First, Rest...> {
|
|
196
|
+
typedef typename Cons<
|
|
197
|
+
typename Mapper<CurrentIndex, First>::type,
|
|
198
|
+
typename MapWithIndex_<Mapper, CurrentIndex + 1, Rest...>::type
|
|
199
|
+
>::type type;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
template<template<size_t, typename> class Mapper, size_t CurrentIndex>
|
|
203
|
+
struct MapWithIndex_<Mapper, CurrentIndex> {
|
|
204
|
+
typedef TypeList<> type;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
template<template<typename...> class Output, template<size_t, typename> class Mapper, typename... Args>
|
|
208
|
+
struct MapWithIndex {
|
|
209
|
+
typedef typename internal::Apply<
|
|
210
|
+
Output,
|
|
211
|
+
typename MapWithIndex_<Mapper, 0, Args...>::type
|
|
212
|
+
>::type type;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
template<typename ArgList>
|
|
217
|
+
struct ArgArrayGetter;
|
|
218
|
+
|
|
219
|
+
template<typename... Args>
|
|
220
|
+
struct ArgArrayGetter<TypeList<Args...>> {
|
|
221
|
+
static const TYPEID* get() {
|
|
222
|
+
static constexpr TYPEID types[] = { TypeID<Args>::get()... };
|
|
223
|
+
return types;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// WithPolicies<...>::ArgTypeList<...>
|
|
228
|
+
|
|
229
|
+
template<typename... Policies>
|
|
230
|
+
struct WithPolicies {
|
|
231
|
+
template<size_t Index, typename T>
|
|
232
|
+
struct MapWithPolicies {
|
|
233
|
+
typedef typename ExecutePolicies<Policies...>::template With<T, Index>::type type;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
template<typename... Args>
|
|
237
|
+
struct ArgTypeList {
|
|
238
|
+
unsigned getCount() const {
|
|
239
|
+
return sizeof...(Args);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const TYPEID* getTypes() const {
|
|
243
|
+
return ArgArrayGetter<
|
|
244
|
+
typename MapWithIndex<TypeList, MapWithPolicies, Args...>::type
|
|
245
|
+
>::get();
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
// BindingType<T>
|
|
251
|
+
|
|
252
|
+
// The second typename is an unused stub so it's possible to
|
|
253
|
+
// specialize groups of classes via SFINAE.
|
|
254
|
+
template<typename T, typename = void>
|
|
255
|
+
struct BindingType;
|
|
256
|
+
|
|
257
|
+
#define EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(type) \
|
|
258
|
+
template<> \
|
|
259
|
+
struct BindingType<type> { \
|
|
260
|
+
typedef type WireType; \
|
|
261
|
+
typedef const facebook::jsi::Value WireType2; \
|
|
262
|
+
\
|
|
263
|
+
static WireType toWireType(type b) { \
|
|
264
|
+
return b; \
|
|
265
|
+
} \
|
|
266
|
+
static type fromWireType(WireType wt) { \
|
|
267
|
+
return wt; \
|
|
268
|
+
} \
|
|
269
|
+
\
|
|
270
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType b) { \
|
|
271
|
+
return WireType2((double) b); \
|
|
272
|
+
} \
|
|
273
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) { \
|
|
274
|
+
return (WireType) wt.getNumber(); \
|
|
275
|
+
} \
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(char);
|
|
280
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(signed char);
|
|
281
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(unsigned char);
|
|
282
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(signed short);
|
|
283
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(unsigned short);
|
|
284
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(int);
|
|
285
|
+
// EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(signed int);
|
|
286
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(unsigned int);
|
|
287
|
+
// EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(signed long);
|
|
288
|
+
// EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(unsigned long);
|
|
289
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(float);
|
|
290
|
+
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE_NUMBER(double);
|
|
291
|
+
// EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(int64_t);
|
|
292
|
+
// EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(uint64_t);
|
|
293
|
+
|
|
294
|
+
template<>
|
|
295
|
+
struct BindingType<void> {
|
|
296
|
+
typedef void WireType;
|
|
297
|
+
typedef void WireType2;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
template<>
|
|
301
|
+
struct BindingType<bool> {
|
|
302
|
+
typedef bool WireType;
|
|
303
|
+
typedef const facebook::jsi::Value WireType2;
|
|
304
|
+
static WireType toWireType(bool b) {
|
|
305
|
+
return b;
|
|
306
|
+
}
|
|
307
|
+
static bool fromWireType(WireType wt) {
|
|
308
|
+
return wt;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType b) {
|
|
312
|
+
return WireType2(b);
|
|
313
|
+
}
|
|
314
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
315
|
+
return wt.getBool();
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
template<>
|
|
320
|
+
struct BindingType<int64_t> {
|
|
321
|
+
typedef int64_t WireType;
|
|
322
|
+
typedef const facebook::jsi::Value WireType2;
|
|
323
|
+
|
|
324
|
+
static WireType toWireType(WireType b) {
|
|
325
|
+
return b;
|
|
326
|
+
}
|
|
327
|
+
static WireType fromWireType(WireType wt) {
|
|
328
|
+
return wt;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType b) {
|
|
332
|
+
return facebook::jsi::BigInt::fromInt64(rt, b);
|
|
333
|
+
}
|
|
334
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
335
|
+
return wt.asBigInt(rt).asInt64(rt);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
template<>
|
|
340
|
+
struct BindingType<uint64_t> {
|
|
341
|
+
typedef uint64_t WireType;
|
|
342
|
+
typedef const facebook::jsi::Value WireType2;
|
|
343
|
+
|
|
344
|
+
static WireType toWireType(WireType b) {
|
|
345
|
+
return b;
|
|
346
|
+
}
|
|
347
|
+
static WireType fromWireType(WireType wt) {
|
|
348
|
+
return wt;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType b) {
|
|
352
|
+
return facebook::jsi::BigInt::fromUint64(rt, b);
|
|
353
|
+
}
|
|
354
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
355
|
+
return wt.asBigInt(rt).asUint64(rt);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
template<>
|
|
360
|
+
struct BindingType<facebook::jsi::Value> {
|
|
361
|
+
typedef const facebook::jsi::Value WireType;
|
|
362
|
+
typedef const facebook::jsi::Value WireType2;
|
|
363
|
+
|
|
364
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType& b) {
|
|
365
|
+
return WireType2(rt, b);
|
|
366
|
+
}
|
|
367
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
368
|
+
return WireType(rt, wt);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
template<typename T>
|
|
373
|
+
struct BindingType<std::basic_string<T>> {
|
|
374
|
+
using String = std::basic_string<T>;
|
|
375
|
+
static_assert(std::is_trivially_copyable<T>::value, "basic_string elements are memcpy'd");
|
|
376
|
+
typedef struct {
|
|
377
|
+
size_t length;
|
|
378
|
+
T data[1]; // trailing data
|
|
379
|
+
}* WireType;
|
|
380
|
+
typedef const facebook::jsi::Value WireType2;
|
|
381
|
+
static WireType toWireType(const String& v) {
|
|
382
|
+
WireType wt = (WireType)malloc(sizeof(size_t) + v.length() * sizeof(T));
|
|
383
|
+
wt->length = v.length();
|
|
384
|
+
memcpy(wt->data, v.data(), v.length() * sizeof(T));
|
|
385
|
+
return wt;
|
|
386
|
+
}
|
|
387
|
+
static String fromWireType(WireType v) {
|
|
388
|
+
return String(v->data, v->length);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, String v) {
|
|
392
|
+
return facebook::jsi::String::createFromUtf8(rt, v);
|
|
393
|
+
}
|
|
394
|
+
static String fromWireType2(facebook::jsi::Runtime& rt, WireType2& v) {
|
|
395
|
+
return v.getString(rt).utf8(rt);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
template<typename T>
|
|
400
|
+
struct BindingType<std::optional<T>> {
|
|
401
|
+
typedef std::optional<T> WireType;
|
|
402
|
+
typedef const facebook::jsi::Value WireType2;
|
|
403
|
+
|
|
404
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, const std::optional<T>& v) {
|
|
405
|
+
if (!v.has_value()) return facebook::jsi::Value::undefined();
|
|
406
|
+
return WireType2(rt, BindingType<T>::toWireType2(rt, *v));
|
|
407
|
+
}
|
|
408
|
+
static std::optional<T> fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
409
|
+
if (wt.isUndefined() || wt.isNull()) return std::nullopt;
|
|
410
|
+
return BindingType<T>::fromWireType2(rt, wt);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
template<typename T>
|
|
415
|
+
struct BindingType<const T> : public BindingType<T> {
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
template<typename T>
|
|
419
|
+
struct BindingType<T&> : public BindingType<T> {
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
template<typename T>
|
|
423
|
+
struct BindingType<const T&> : public BindingType<T> {
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
template<typename T>
|
|
427
|
+
struct BindingType<T&&> {
|
|
428
|
+
typedef typename BindingType<T>::WireType WireType;
|
|
429
|
+
typedef const facebook::jsi::Value WireType2;
|
|
430
|
+
|
|
431
|
+
static WireType toWireType(const T& v) {
|
|
432
|
+
return BindingType<T>::toWireType(v);
|
|
433
|
+
}
|
|
434
|
+
static T fromWireType(WireType wt) {
|
|
435
|
+
return BindingType<T>::fromWireType(wt);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, const T& v) {
|
|
439
|
+
return BindingType<T>::toWireType2(rt, v);
|
|
440
|
+
}
|
|
441
|
+
static T fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
442
|
+
return BindingType<T>::fromWireType2(rt, wt);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
template<typename T>
|
|
447
|
+
struct BindingType<T*> {
|
|
448
|
+
typedef T* WireType;
|
|
449
|
+
typedef const facebook::jsi::Value WireType2;
|
|
450
|
+
|
|
451
|
+
static WireType toWireType(T* p) {
|
|
452
|
+
return p;
|
|
453
|
+
}
|
|
454
|
+
static T* fromWireType(WireType wt) {
|
|
455
|
+
return wt;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, WireType b) {
|
|
459
|
+
return facebook::jsi::BigInt::fromUint64(rt, reinterpret_cast<uint64_t>(b));
|
|
460
|
+
}
|
|
461
|
+
static WireType fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
462
|
+
return (WireType) wt.asBigInt(rt).asUint64(rt);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
template<typename T>
|
|
467
|
+
struct GenericBindingType {
|
|
468
|
+
typedef typename std::remove_reference<T>::type ActualT;
|
|
469
|
+
typedef ActualT* WireType;
|
|
470
|
+
typedef const facebook::jsi::Value WireType2;
|
|
471
|
+
|
|
472
|
+
static WireType toWireType(const T& v) {
|
|
473
|
+
return new T(v);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
static WireType toWireType(T&& v) {
|
|
477
|
+
return new T(std::forward<T>(v));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
static ActualT& fromWireType(WireType p) {
|
|
481
|
+
return *p;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, const T& v) {
|
|
485
|
+
// By-value returns allocate fresh heap blocks; without a covering window JS-side
|
|
486
|
+
// memory reads on the new object die with "Heap error ... no covering window".
|
|
487
|
+
uint64_t ptr = reinterpret_cast<uint64_t>(new T(v));
|
|
488
|
+
ensureWindowFor(ptr);
|
|
489
|
+
return facebook::jsi::BigInt::fromUint64(rt, ptr);
|
|
490
|
+
}
|
|
491
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, T&& v) {
|
|
492
|
+
uint64_t ptr = reinterpret_cast<uint64_t>(new T(std::forward<T>(v)));
|
|
493
|
+
ensureWindowFor(ptr);
|
|
494
|
+
return facebook::jsi::BigInt::fromUint64(rt, ptr);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
static ActualT& fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
498
|
+
return *reinterpret_cast<WireType>(wt.getBigInt(rt).getUint64(rt));
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
template<typename T>
|
|
503
|
+
struct GenericBindingType<std::unique_ptr<T>> {
|
|
504
|
+
typedef typename BindingType<T*>::WireType WireType;
|
|
505
|
+
typedef const facebook::jsi::Value WireType2;
|
|
506
|
+
|
|
507
|
+
static WireType toWireType(std::unique_ptr<T> p) {
|
|
508
|
+
return BindingType<T*>::toWireType(p.release());
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
static std::unique_ptr<T> fromWireType(WireType wt) {
|
|
512
|
+
return std::unique_ptr<T>(BindingType<T*>::fromWireType(wt));
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, std::unique_ptr<T> p) {
|
|
516
|
+
return BindingType<T*>::toWireType2(rt, p.release());
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
static std::unique_ptr<T> fromWireType2(facebook::jsi::Runtime& rt, WireType2& wt) {
|
|
520
|
+
return std::unique_ptr<T>(BindingType<T*>::fromWireType2(rt, wt));
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
template<typename Enum>
|
|
525
|
+
struct EnumBindingType {
|
|
526
|
+
typedef Enum WireType;
|
|
527
|
+
typedef const facebook::jsi::Value WireType2;
|
|
528
|
+
|
|
529
|
+
static WireType toWireType(Enum v) {
|
|
530
|
+
return v;
|
|
531
|
+
}
|
|
532
|
+
static Enum fromWireType(WireType v) {
|
|
533
|
+
return v;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
static WireType2 toWireType2(facebook::jsi::Runtime& rt, Enum v) {
|
|
537
|
+
return WireType2((int) v);
|
|
538
|
+
}
|
|
539
|
+
static Enum fromWireType2(facebook::jsi::Runtime& rt, WireType2& v) {
|
|
540
|
+
return (WireType) v.asBigInt(rt).asUint64(rt);
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// catch-all generic binding
|
|
545
|
+
template<typename T, typename>
|
|
546
|
+
struct BindingType : std::conditional<
|
|
547
|
+
std::is_enum<T>::value,
|
|
548
|
+
EnumBindingType<T>,
|
|
549
|
+
GenericBindingType<T> >::type
|
|
550
|
+
{};
|
|
551
|
+
|
|
552
|
+
template<typename T>
|
|
553
|
+
auto toWireType(T&& v) -> typename BindingType<T>::WireType {
|
|
554
|
+
return BindingType<T>::toWireType(std::forward<T>(v));
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
template<typename T>
|
|
558
|
+
constexpr bool typeSupportsMemoryView() {
|
|
559
|
+
return (std::is_floating_point<T>::value &&
|
|
560
|
+
(sizeof(T) == 4 || sizeof(T) == 8)) ||
|
|
561
|
+
(std::is_integral<T>::value &&
|
|
562
|
+
(sizeof(T) == 1 || sizeof(T) == 2 ||
|
|
563
|
+
sizeof(T) == 4 || sizeof(T) == 8));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
} // namespace internal
|
|
567
|
+
|
|
568
|
+
template<typename ElementType>
|
|
569
|
+
struct memory_view {
|
|
570
|
+
memory_view() = delete;
|
|
571
|
+
explicit memory_view(size_t size, const ElementType* data)
|
|
572
|
+
: size(size)
|
|
573
|
+
, data(data)
|
|
574
|
+
{}
|
|
575
|
+
|
|
576
|
+
const size_t size; // in elements, not bytes
|
|
577
|
+
const void* const data;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
// Note that 'data' is marked const just so it can accept both
|
|
581
|
+
// const and nonconst pointers. It is certainly possible for
|
|
582
|
+
// JavaScript to modify the C heap through the typed array given,
|
|
583
|
+
// as it merely aliases the C heap.
|
|
584
|
+
template<typename T>
|
|
585
|
+
inline memory_view<T> typed_memory_view(size_t size, const T* data) {
|
|
586
|
+
static_assert(internal::typeSupportsMemoryView<T>(),
|
|
587
|
+
"type of typed_memory_view is invalid");
|
|
588
|
+
return memory_view<T>(size, data);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
namespace internal {
|
|
592
|
+
|
|
593
|
+
template<typename ElementType>
|
|
594
|
+
struct BindingType<memory_view<ElementType>> {
|
|
595
|
+
// This non-word-sized WireType only works because I
|
|
596
|
+
// happen to know that clang will pass aggregates as
|
|
597
|
+
// pointers to stack elements and we never support
|
|
598
|
+
// converting JavaScript typed arrays back into
|
|
599
|
+
// memory_view. (That is, fromWireType is not implemented
|
|
600
|
+
// on the C++ side, nor is toWireType implemented in
|
|
601
|
+
// JavaScript.)
|
|
602
|
+
typedef memory_view<ElementType> WireType;
|
|
603
|
+
static WireType toWireType(const memory_view<ElementType>& mv) {
|
|
604
|
+
return mv;
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
} // namespace internal
|
|
609
|
+
|
|
610
|
+
} // namespace emscripten
|