@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.
@@ -0,0 +1,708 @@
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 <./val.h> requires building with -std=c++11 or newer!
12
+ #endif
13
+
14
+ #include <cassert>
15
+ #include <cstdlib>
16
+ #include <array>
17
+ #include <climits>
18
+ #include "./wire.h"
19
+ #include <cstdint> // uintptr_t
20
+ #include <vector>
21
+
22
+ // #include <android/log.h>
23
+ // #define APPNAME "react-native-crossbind"
24
+
25
+ namespace emscripten {
26
+ extern facebook::jsi::Runtime* jsRuntime;
27
+
28
+ class val;
29
+
30
+ typedef struct _EM_VAL* EM_VAL;
31
+
32
+ namespace internal {
33
+
34
+ template<typename WrapperType>
35
+ val wrapped_extend(const std::string&, const val&);
36
+
37
+ #if !defined(__APPLE__)
38
+ // Implemented in JavaScript. Don't call these directly.
39
+ extern "C" {
40
+ #endif
41
+
42
+ void _emval_register_symbol(const char*);
43
+
44
+ enum {
45
+ _EMVAL_UNDEFINED = 1,
46
+ _EMVAL_NULL = 2,
47
+ _EMVAL_TRUE = 3,
48
+ _EMVAL_FALSE = 4
49
+ };
50
+
51
+ typedef struct _EM_DESTRUCTORS* EM_DESTRUCTORS;
52
+ typedef struct _EM_METHOD_CALLER* EM_METHOD_CALLER;
53
+ typedef facebook::jsi::Value EM_GENERIC_WIRE_TYPE;
54
+ typedef const void* EM_VAR_ARGS;
55
+
56
+ void _emval_incref(EM_VAL value);
57
+ void _emval_decref(EM_VAL value);
58
+
59
+ void _emval_run_destructors(EM_DESTRUCTORS handle);
60
+
61
+ EM_VAL _emval_new_array();
62
+ EM_VAL _emval_new_array_from_memory_view(EM_VAL mv);
63
+ EM_VAL _emval_new_object();
64
+ EM_VAL _emval_new_cstring(const char*);
65
+ EM_VAL _emval_new_u8string(const char*);
66
+ EM_VAL _emval_new_u16string(const char16_t*);
67
+
68
+ EM_VAL _emval_take_value(TYPEID type, EM_VAR_ARGS argv);
69
+
70
+ EM_VAL _emval_new(
71
+ EM_VAL value,
72
+ unsigned argCount,
73
+ const TYPEID argTypes[],
74
+ EM_VAR_ARGS argv);
75
+
76
+ EM_VAL _emval_get_global(const char* name);
77
+ EM_VAL _emval_get_module_property(const char* name);
78
+ EM_VAL _emval_get_property(EM_VAL object, EM_VAL key);
79
+ void _emval_set_property(EM_VAL object, EM_VAL key, EM_VAL value);
80
+ EM_GENERIC_WIRE_TYPE _emval_as(EM_VAL value, TYPEID returnType, EM_DESTRUCTORS* destructors);
81
+ int64_t _emval_as_int64(EM_VAL value, TYPEID returnType);
82
+ uint64_t _emval_as_uint64(EM_VAL value, TYPEID returnType);
83
+
84
+ bool _emval_equals(EM_VAL first, EM_VAL second);
85
+ bool _emval_strictly_equals(EM_VAL first, EM_VAL second);
86
+ bool _emval_greater_than(EM_VAL first, EM_VAL second);
87
+ bool _emval_less_than(EM_VAL first, EM_VAL second);
88
+ bool _emval_not(EM_VAL object);
89
+
90
+ EM_VAL _emval_call(
91
+ EM_VAL value,
92
+ unsigned argCount,
93
+ const TYPEID argTypes[],
94
+ EM_VAR_ARGS argv);
95
+
96
+ // DO NOT call this more than once per signature. It will
97
+ // leak generated function objects!
98
+ EM_METHOD_CALLER _emval_get_method_caller(
99
+ unsigned argCount, // including return value
100
+ const TYPEID argTypes[]);
101
+ EM_GENERIC_WIRE_TYPE _emval_call_method(
102
+ EM_METHOD_CALLER caller,
103
+ EM_VAL handle,
104
+ const char* methodName,
105
+ EM_DESTRUCTORS* destructors,
106
+ EM_VAR_ARGS argv);
107
+ void _emval_call_void_method(
108
+ EM_METHOD_CALLER caller,
109
+ EM_VAL handle,
110
+ const char* methodName,
111
+ EM_VAR_ARGS argv);
112
+ EM_VAL _emval_typeof(EM_VAL value);
113
+ bool _emval_instanceof(EM_VAL object, EM_VAL constructor);
114
+ bool _emval_is_number(EM_VAL object);
115
+ bool _emval_is_string(EM_VAL object);
116
+ bool _emval_in(EM_VAL item, EM_VAL object);
117
+ bool _emval_delete(EM_VAL object, EM_VAL property);
118
+ [[noreturn]] bool _emval_throw(EM_VAL object);
119
+ EM_VAL _emval_await(EM_VAL promise);
120
+
121
+ #if !defined(__APPLE__)
122
+ } // extern "C"
123
+ #endif
124
+
125
+ template<const char* address>
126
+ struct symbol_registrar {
127
+ symbol_registrar() {
128
+ internal::_emval_register_symbol(address);
129
+ }
130
+ };
131
+
132
+ template<typename ReturnType, typename... Args>
133
+ struct Signature {
134
+ /*
135
+ typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(
136
+ EM_VAL value,
137
+ const char* methodName,
138
+ EM_DESTRUCTORS* destructors,
139
+ typename BindingType<Args>::WireType...);
140
+ */
141
+
142
+ static EM_METHOD_CALLER get_method_caller() {
143
+ constexpr WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
144
+ thread_local EM_METHOD_CALLER mc = _emval_get_method_caller(args.getCount(), args.getTypes());
145
+ return mc;
146
+ }
147
+ };
148
+
149
+ struct DestructorsRunner {
150
+ public:
151
+ explicit DestructorsRunner(EM_DESTRUCTORS d)
152
+ : destructors(d)
153
+ {}
154
+ ~DestructorsRunner() {
155
+ _emval_run_destructors(destructors);
156
+ }
157
+
158
+ DestructorsRunner(const DestructorsRunner&) = delete;
159
+ void operator=(const DestructorsRunner&) = delete;
160
+
161
+ private:
162
+ EM_DESTRUCTORS destructors;
163
+ };
164
+
165
+ template<typename WireType>
166
+ struct GenericWireTypeConverter {
167
+ static WireType from(facebook::jsi::Value& wt) {
168
+ return BindingType<WireType>::fromWireType2(*jsRuntime, wt);
169
+ }
170
+ };
171
+
172
+ template<typename Pointee>
173
+ struct GenericWireTypeConverter<Pointee*> {
174
+ static Pointee* from(facebook::jsi::Value& wt) {
175
+ return reinterpret_cast<Pointee*>(wt.asBigInt(*jsRuntime).asUint64(*jsRuntime));
176
+ }
177
+ };
178
+
179
+ template<typename T>
180
+ T fromGenericWireType(facebook::jsi::Value& g) {
181
+ if constexpr (std::is_same<T, std::string>::value) {
182
+ return g.getString(*jsRuntime).utf8(*jsRuntime);
183
+ }
184
+ typedef typename BindingType<T>::WireType WireType;
185
+ WireType wt = GenericWireTypeConverter<WireType>::from(g);
186
+ return BindingType<T>::fromWireType(wt);
187
+ }
188
+
189
+ template<typename... Args>
190
+ struct PackSize;
191
+
192
+ template<>
193
+ struct PackSize<> {
194
+ static constexpr size_t value = 0;
195
+ };
196
+
197
+ template<typename Arg, typename... Args>
198
+ struct PackSize<Arg, Args...> {
199
+ static constexpr size_t value = (sizeof(typename BindingType<Arg>::WireType) + 7) / 8 + PackSize<Args...>::value;
200
+ };
201
+
202
+ union GenericWireType {
203
+ union {
204
+ unsigned u;
205
+ float f;
206
+ // Use uint32_t for pointer values. This limits us, for now, to 32-bit
207
+ // address ranges even on wasm64. This is enforced by assertions below.
208
+ // TODO(sbc): Allow full 64-bit address range here under wasm64, most
209
+ // likely by increasing the size of GenericWireType on wasm64.
210
+ uint32_t p;
211
+ } w[2];
212
+ double d;
213
+ uint64_t u;
214
+ };
215
+ static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes");
216
+ static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned");
217
+
218
+ inline void writeGenericWireType(GenericWireType*& cursor, float wt) {
219
+ cursor->w[0].f = wt;
220
+ ++cursor;
221
+ }
222
+
223
+ inline void writeGenericWireType(GenericWireType*& cursor, double wt) {
224
+ cursor->d = wt;
225
+ ++cursor;
226
+ }
227
+
228
+ inline void writeGenericWireType(GenericWireType*& cursor, int64_t wt) {
229
+ cursor->u = wt;
230
+ ++cursor;
231
+ }
232
+
233
+ inline void writeGenericWireType(GenericWireType*& cursor, uint64_t wt) {
234
+ cursor->u = wt;
235
+ ++cursor;
236
+ }
237
+
238
+ template<typename T>
239
+ void writeGenericWireType(GenericWireType*& cursor, T* wt) {
240
+ uint64_t short_ptr = reinterpret_cast<uint64_t>(wt);
241
+ // assert(short_ptr <= UINT32_MAX);
242
+ cursor->u = short_ptr;
243
+ ++cursor;
244
+ }
245
+
246
+ template<typename ElementType>
247
+ inline void writeGenericWireType(GenericWireType*& cursor, const memory_view<ElementType>& wt) {
248
+ uintptr_t short_ptr = reinterpret_cast<uintptr_t>(wt.data);
249
+ // This wire slot stores the data pointer in 32 bits (upstream wasm32 layout). On 64-bit
250
+ // native a pointer above 4 GiB cannot fit; abort loudly rather than silently truncating to
251
+ // a bogus address (release builds compile out the assert). Full 64-bit memory_view support
252
+ // needs a wider wire encoding on both the writer and the reader.
253
+ assert(short_ptr <= UINT32_MAX);
254
+ if (short_ptr > UINT32_MAX) {
255
+ abort();
256
+ }
257
+ cursor->w[0].u = wt.size;
258
+ cursor->w[1].p = static_cast<uint32_t>(short_ptr);
259
+ ++cursor;
260
+ }
261
+
262
+ template<typename T>
263
+ void writeGenericWireType(GenericWireType*& cursor, T wt) {
264
+ cursor->w[0].u = static_cast<unsigned>(wt);
265
+ ++cursor;
266
+ }
267
+
268
+ inline void writeGenericWireTypes(GenericWireType*&) {
269
+ }
270
+
271
+ template<typename First, typename... Rest>
272
+ EMSCRIPTEN_ALWAYS_INLINE void writeGenericWireTypes(GenericWireType*& cursor, First&& first, Rest&&... rest) {
273
+ writeGenericWireType(cursor, BindingType<First>::toWireType(std::forward<First>(first)));
274
+ writeGenericWireTypes(cursor, std::forward<Rest>(rest)...);
275
+ }
276
+
277
+ template<typename... Args>
278
+ struct WireTypePack {
279
+ WireTypePack(Args&&... args) {
280
+ GenericWireType* cursor = elements.data();
281
+ writeGenericWireTypes(cursor, std::forward<Args>(args)...);
282
+ }
283
+
284
+ operator EM_VAR_ARGS() const {
285
+ return elements.data();
286
+ }
287
+
288
+ private:
289
+ std::array<GenericWireType, PackSize<Args...>::value> elements;
290
+ };
291
+
292
+ template<typename ReturnType, typename... Args>
293
+ struct MethodCaller {
294
+ static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) {
295
+ auto caller = Signature<ReturnType, Args...>::get_method_caller();
296
+
297
+ WireTypePack<Args...> argv(std::forward<Args>(args)...);
298
+ EM_DESTRUCTORS destructors;
299
+ EM_GENERIC_WIRE_TYPE result = _emval_call_method(
300
+ caller,
301
+ handle,
302
+ methodName,
303
+ &destructors,
304
+ argv);
305
+ DestructorsRunner rd(destructors);
306
+ return fromGenericWireType<ReturnType>(result);
307
+ }
308
+ };
309
+
310
+ template<typename... Args>
311
+ struct MethodCaller<void, Args...> {
312
+ static void call(EM_VAL handle, const char* methodName, Args&&... args) {
313
+ auto caller = Signature<void, Args...>::get_method_caller();
314
+
315
+ WireTypePack<Args...> argv(std::forward<Args>(args)...);
316
+ _emval_call_void_method(
317
+ caller,
318
+ handle,
319
+ methodName,
320
+ argv);
321
+ }
322
+ };
323
+
324
+ } // end namespace internal
325
+
326
+ #define EMSCRIPTEN_SYMBOL(name) \
327
+ static const char name##_symbol[] = #name; \
328
+ static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
329
+
330
+ class val {
331
+ public:
332
+ // missing operators:
333
+ // * ~ - + ++ --
334
+ // * * / %
335
+ // * + -
336
+ // * << >> >>>
337
+ // * & ^ | && || ?:
338
+ //
339
+ // exposing void, comma, and conditional is unnecessary
340
+ // same with: = += -= *= /= %= <<= >>= >>>= &= ^= |=
341
+
342
+ static val array() {
343
+ return val(internal::_emval_new_array());
344
+ }
345
+
346
+ template<typename Iter>
347
+ static val array(Iter begin, Iter end) {
348
+ #if _LIBCPP_STD_VER >= 20
349
+ if constexpr (std::contiguous_iterator<Iter> &&
350
+ internal::typeSupportsMemoryView<
351
+ typename std::iterator_traits<Iter>::value_type>()) {
352
+ val view{ typed_memory_view(std::distance(begin, end), std::to_address(begin)) };
353
+ return val(internal::_emval_new_array_from_memory_view(view.as_handle()));
354
+ }
355
+ // For numeric arrays, following codes are unreachable and the compiler
356
+ // will do 'dead code elimination'.
357
+ // Others fallback old way.
358
+ #endif
359
+ val new_array = array();
360
+ for (auto it = begin; it != end; ++it) {
361
+ new_array.call<void>("push", *it);
362
+ }
363
+ return new_array;
364
+ }
365
+
366
+ template<typename T>
367
+ static val array(const std::vector<T>& vec) {
368
+ if constexpr (internal::typeSupportsMemoryView<T>()) {
369
+ // for numeric types, pass memory view and copy in JS side one-off
370
+ val view{ typed_memory_view(vec.size(), vec.data()) };
371
+ return val(internal::_emval_new_array_from_memory_view(view.as_handle()));
372
+ } else {
373
+ return array(vec.begin(), vec.end());
374
+ }
375
+ }
376
+
377
+ static val object() {
378
+ return val(internal::_emval_new_object());
379
+ }
380
+
381
+ static val u8string(const char* s) {
382
+ return val(internal::_emval_new_u8string(s));
383
+ }
384
+
385
+ static val u16string(const char16_t* s) {
386
+ return val(internal::_emval_new_u16string(s));
387
+ }
388
+
389
+ static val undefined() {
390
+ return val(EM_VAL(internal::_EMVAL_UNDEFINED));
391
+ }
392
+
393
+ static val null() {
394
+ return val(EM_VAL(internal::_EMVAL_NULL));
395
+ }
396
+
397
+ static val take_ownership(EM_VAL e) {
398
+ return val(e);
399
+ }
400
+
401
+ static val global(const char* name = "") {
402
+ return val(internal::_emval_get_global(name));
403
+ }
404
+
405
+ static val module_property(const char* name) {
406
+ return val(internal::_emval_get_module_property(name));
407
+ }
408
+
409
+ template<typename T>
410
+ explicit val(T&& value) {
411
+ using namespace internal;
412
+
413
+ typedef internal::BindingType<T> BT;
414
+ WireTypePack<T> argv(std::forward<T>(value));
415
+ handle = _emval_take_value(internal::TypeID<T>::get(), argv);
416
+ }
417
+
418
+ val() : handle(EM_VAL(internal::_EMVAL_UNDEFINED)) {}
419
+
420
+ explicit val(const char* v)
421
+ : handle(internal::_emval_new_cstring(v))
422
+ {}
423
+
424
+ val(val&& v) : handle(v.handle) {
425
+ v.handle = 0;
426
+ }
427
+
428
+ val(const val& v) : handle(v.handle) {
429
+ internal::_emval_incref(handle);
430
+ }
431
+
432
+ ~val() {
433
+ internal::_emval_decref(handle);
434
+ }
435
+
436
+ EM_VAL as_handle() const {
437
+ return handle;
438
+ }
439
+
440
+ val& operator=(val&& v) & {
441
+ internal::_emval_decref(handle);
442
+ handle = v.handle;
443
+ v.handle = 0;
444
+ return *this;
445
+ }
446
+
447
+ val& operator=(const val& v) & {
448
+ internal::_emval_incref(v.handle);
449
+ internal::_emval_decref(handle);
450
+ handle = v.handle;
451
+ return *this;
452
+ }
453
+
454
+ bool hasOwnProperty(const char* key) const {
455
+ return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key));
456
+ }
457
+
458
+ bool isNull() const {
459
+ return handle == EM_VAL(internal::_EMVAL_NULL);
460
+ }
461
+
462
+ bool isUndefined() const {
463
+ return handle == EM_VAL(internal::_EMVAL_UNDEFINED);
464
+ }
465
+
466
+ bool isTrue() const {
467
+ return handle == EM_VAL(internal::_EMVAL_TRUE);
468
+ }
469
+
470
+ bool isFalse() const {
471
+ return handle == EM_VAL(internal::_EMVAL_FALSE);
472
+ }
473
+
474
+ bool isNumber() const {
475
+ return internal::_emval_is_number(handle);
476
+ }
477
+
478
+ bool isString() const {
479
+ return internal::_emval_is_string(handle);
480
+ }
481
+
482
+ bool isArray() const {
483
+ return instanceof(global("Array"));
484
+ }
485
+
486
+ bool equals(const val& v) const {
487
+ return internal::_emval_equals(handle, v.handle);
488
+ }
489
+
490
+ bool operator==(const val& v) const {
491
+ return internal::_emval_equals(handle, v.handle);
492
+ }
493
+
494
+ bool operator!=(const val& v) const {
495
+ return !(*this == v);
496
+ }
497
+
498
+ bool strictlyEquals(const val& v) const {
499
+ return internal::_emval_strictly_equals(handle, v.handle);
500
+ }
501
+
502
+ bool operator>(const val& v) const {
503
+ return internal::_emval_greater_than(handle, v.handle);
504
+ }
505
+
506
+ bool operator>=(const val& v) const {
507
+ return (*this > v) || (*this == v);
508
+ }
509
+
510
+ bool operator<(const val& v) const {
511
+ return internal::_emval_less_than(handle, v.handle);
512
+ }
513
+
514
+ bool operator<=(const val& v) const {
515
+ return (*this < v) || (*this == v);
516
+ }
517
+
518
+ bool operator!() const {
519
+ return internal::_emval_not(handle);
520
+ }
521
+
522
+ template<typename... Args>
523
+ val new_(Args&&... args) const {
524
+ return internalCall(internal::_emval_new, std::forward<Args>(args)...);
525
+ }
526
+
527
+ template<typename T>
528
+ val operator[](const T& key) const {
529
+ return val(internal::_emval_get_property(handle, val_ref(key).handle));
530
+ }
531
+
532
+ template<typename K, typename V>
533
+ void set(const K& key, const V& value) {
534
+ internal::_emval_set_property(handle, val_ref(key).handle, val_ref(value).handle);
535
+ }
536
+
537
+ template<typename T>
538
+ bool delete_(const T& property) const {
539
+ return internal::_emval_delete(handle, val_ref(property).handle);
540
+ }
541
+
542
+ template<typename... Args>
543
+ val operator()(Args&&... args) const {
544
+ return internalCall(internal::_emval_call, std::forward<Args>(args)...);
545
+ }
546
+
547
+ template<typename ReturnValue, typename... Args>
548
+ ReturnValue call(const char* name, Args&&... args) const {
549
+ using namespace internal;
550
+
551
+ return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
552
+ }
553
+
554
+ template<typename T, typename ...Policies>
555
+ T as(Policies...) const {
556
+ using namespace internal;
557
+
558
+ typedef BindingType<T> BT;
559
+ typename WithPolicies<Policies...>::template ArgTypeList<T> targetType;
560
+
561
+ EM_DESTRUCTORS destructors;
562
+ EM_GENERIC_WIRE_TYPE result = _emval_as(
563
+ handle,
564
+ targetType.getTypes()[0],
565
+ &destructors);
566
+ DestructorsRunner dr(destructors);
567
+ return fromGenericWireType<T>(result);
568
+ }
569
+
570
+ template<>
571
+ int64_t as<int64_t>() const {
572
+ using namespace internal;
573
+
574
+ typedef BindingType<int64_t> BT;
575
+ typename WithPolicies<>::template ArgTypeList<int64_t> targetType;
576
+
577
+ return _emval_as_int64(handle, targetType.getTypes()[0]);
578
+ }
579
+
580
+ template<>
581
+ uint64_t as<uint64_t>() const {
582
+ using namespace internal;
583
+
584
+ typedef BindingType<uint64_t> BT;
585
+ typename WithPolicies<>::template ArgTypeList<uint64_t> targetType;
586
+
587
+ return _emval_as_uint64(handle, targetType.getTypes()[0]);
588
+ }
589
+
590
+ // If code is not being compiled with GNU extensions enabled, typeof() is not a reserved keyword, so support that as a member function.
591
+ #if __STRICT_ANSI__
592
+ val typeof() const {
593
+ return val(internal::_emval_typeof(handle));
594
+ }
595
+ #endif
596
+
597
+ // Prefer calling val::typeOf() over val::typeof(), since this form works in both C++11 and GNU++11 build modes. "typeof" is a reserved word in GNU++11 extensions.
598
+ val typeOf() const {
599
+ return val(internal::_emval_typeof(handle));
600
+ }
601
+
602
+ bool instanceof(const val& v) const {
603
+ return internal::_emval_instanceof(handle, v.handle);
604
+ }
605
+
606
+ bool in(const val& v) const {
607
+ return internal::_emval_in(handle, v.handle);
608
+ }
609
+
610
+ [[noreturn]] void throw_() const {
611
+ internal::_emval_throw(handle);
612
+ }
613
+
614
+ val await() const {
615
+ return val(internal::_emval_await(handle));
616
+ }
617
+
618
+ private:
619
+ // takes ownership, assumes handle already incref'd
620
+ explicit val(EM_VAL handle)
621
+ : handle(handle)
622
+ {}
623
+
624
+ template<typename WrapperType>
625
+ friend val internal::wrapped_extend(const std::string& , const val& );
626
+
627
+ template<typename Implementation, typename... Args>
628
+ val internalCall(Implementation impl, Args&&... args) const {
629
+ using namespace internal;
630
+
631
+ WithPolicies<>::ArgTypeList<Args...> argList;
632
+ WireTypePack<Args...> argv(std::forward<Args>(args)...);
633
+ return val(impl(handle, argList.getCount(), argList.getTypes(), argv));
634
+ }
635
+
636
+ template<typename T>
637
+ val val_ref(const T& v) const {
638
+ return val(v);
639
+ }
640
+
641
+ const val& val_ref(const val& v) const {
642
+ return v;
643
+ }
644
+
645
+ EM_VAL handle;
646
+
647
+ friend struct internal::BindingType<val>;
648
+ };
649
+
650
+ namespace internal {
651
+
652
+ template<>
653
+ struct BindingType<val> {
654
+ typedef EM_VAL WireType;
655
+ typedef const facebook::jsi::Value WireType2;
656
+
657
+ static WireType toWireType(const val& v) {
658
+ _emval_incref(v.handle);
659
+ return v.handle;
660
+ }
661
+ static val fromWireType(WireType v) {
662
+ return val::take_ownership(v);
663
+ }
664
+
665
+ static WireType2 toWireType2(facebook::jsi::Runtime& rt, const val& v) {
666
+ _emval_incref(v.handle);
667
+ return facebook::jsi::BigInt::fromUint64(rt, reinterpret_cast<uint64_t>(v.handle));
668
+ }
669
+ static val fromWireType2(facebook::jsi::Runtime& rt, WireType2& v) {
670
+ // return val::undefined();
671
+ // return val::take_ownership(reinterpret_cast<EM_VAL>((int) v.getNumber()));
672
+ return val::take_ownership(reinterpret_cast<EM_VAL>(v.asBigInt(rt).asUint64(rt)));
673
+ }
674
+ };
675
+
676
+ }
677
+
678
+ template <typename T, typename... Policies>
679
+ std::vector<T> vecFromJSArray(const val& v, Policies... policies) {
680
+ const size_t l = v["length"].as<size_t>();
681
+
682
+ std::vector<T> rv;
683
+ rv.reserve(l);
684
+ for (size_t i = 0; i < l; ++i) {
685
+ rv.push_back(v[i].as<T>(std::forward<Policies>(policies)...));
686
+ }
687
+
688
+ return rv;
689
+ }
690
+
691
+ template <typename T>
692
+ std::vector<T> convertJSArrayToNumberVector(const val& v) {
693
+ const size_t l = v["length"].as<size_t>();
694
+
695
+ std::vector<T> rv;
696
+ rv.resize(l);
697
+
698
+ // Copy the array into our vector through the use of typed arrays.
699
+ // It will try to convert each element through Number().
700
+ // See https://www.ecma-international.org/ecma-262/6.0/#sec-%typedarray%.prototype.set-array-offset
701
+ // and https://www.ecma-international.org/ecma-262/6.0/#sec-tonumber
702
+ val memoryView{ typed_memory_view(l, rv.data()) };
703
+ memoryView.call<void>("set", v);
704
+
705
+ return rv;
706
+ }
707
+
708
+ } // end namespace emscripten