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 <emscripten/val.h> requires building with -std=c++11 or newer!
12 #endif
13 
14 #include <stdint.h> // uintptr_t
15 #include <emscripten/wire.h>
16 #include <array>
17 #include <vector>
18 
19 
20 namespace emscripten {
21 
22     class val;
23 
24     namespace internal {
25 
26         template<typename WrapperType>
27         val wrapped_extend(const std::string&, const val&);
28 
29         // Implemented in JavaScript.  Don't call these directly.
30         extern "C" {
31             void _emval_register_symbol(const char*);
32 
33             enum {
34                 _EMVAL_UNDEFINED = 1,
35                 _EMVAL_NULL = 2,
36                 _EMVAL_TRUE = 3,
37                 _EMVAL_FALSE = 4
38             };
39 
40             typedef struct _EM_VAL* EM_VAL;
41             typedef struct _EM_DESTRUCTORS* EM_DESTRUCTORS;
42             typedef struct _EM_METHOD_CALLER* EM_METHOD_CALLER;
43             typedef double EM_GENERIC_WIRE_TYPE;
44             typedef const void* EM_VAR_ARGS;
45 
46             void _emval_incref(EM_VAL value);
47             void _emval_decref(EM_VAL value);
48 
49             void _emval_run_destructors(EM_DESTRUCTORS handle);
50 
51             EM_VAL _emval_new_array();
52             EM_VAL _emval_new_object();
53             EM_VAL _emval_new_cstring(const char*);
54 
55             EM_VAL _emval_take_value(TYPEID type, EM_VAR_ARGS argv);
56 
57             EM_VAL _emval_new(
58                 EM_VAL value,
59                 unsigned argCount,
60                 const TYPEID argTypes[],
61                 EM_VAR_ARGS argv);
62 
63             EM_VAL _emval_get_global(const char* name);
64             EM_VAL _emval_get_module_property(const char* name);
65             EM_VAL _emval_get_property(EM_VAL object, EM_VAL key);
66             void _emval_set_property(EM_VAL object, EM_VAL key, EM_VAL value);
67             EM_GENERIC_WIRE_TYPE _emval_as(EM_VAL value, TYPEID returnType, EM_DESTRUCTORS* destructors);
68 
69             bool _emval_equals(EM_VAL first, EM_VAL second);
70             bool _emval_strictly_equals(EM_VAL first, EM_VAL second);
71             bool _emval_greater_than(EM_VAL first, EM_VAL second);
72             bool _emval_less_than(EM_VAL first, EM_VAL second);
73             bool _emval_not(EM_VAL object);
74 
75             EM_VAL _emval_call(
76                 EM_VAL value,
77                 unsigned argCount,
78                 const TYPEID argTypes[],
79                 EM_VAR_ARGS argv);
80 
81             // DO NOT call this more than once per signature. It will
82             // leak generated function objects!
83             EM_METHOD_CALLER _emval_get_method_caller(
84                 unsigned argCount, // including return value
85                 const TYPEID argTypes[]);
86             EM_GENERIC_WIRE_TYPE _emval_call_method(
87                 EM_METHOD_CALLER caller,
88                 EM_VAL handle,
89                 const char* methodName,
90                 EM_DESTRUCTORS* destructors,
91                 EM_VAR_ARGS argv);
92             void _emval_call_void_method(
93                 EM_METHOD_CALLER caller,
94                 EM_VAL handle,
95                 const char* methodName,
96                 EM_VAR_ARGS argv);
97             EM_VAL _emval_typeof(EM_VAL value);
98             bool _emval_instanceof(EM_VAL object, EM_VAL constructor);
99             bool _emval_is_number(EM_VAL object);
100             bool _emval_is_string(EM_VAL object);
101             bool _emval_in(EM_VAL item, EM_VAL object);
102             bool _emval_delete(EM_VAL object, EM_VAL property);
103             bool _emval_throw(EM_VAL object);
104             EM_VAL _emval_await(EM_VAL promise);
105         }
106 
107         template<const char* address>
108         struct symbol_registrar {
symbol_registrarsymbol_registrar109             symbol_registrar() {
110                 internal::_emval_register_symbol(address);
111             }
112         };
113 
114         template<typename ReturnType, typename... Args>
115         struct Signature {
116             /*
117             typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(
118                 EM_VAL value,
119                 const char* methodName,
120                 EM_DESTRUCTORS* destructors,
121                 typename BindingType<Args>::WireType...);
122             */
123 
get_method_callerSignature124             static EM_METHOD_CALLER get_method_caller() {
125                 static EM_METHOD_CALLER mc = init_method_caller();
126                 return mc;
127             }
128 
129         private:
init_method_callerSignature130             static EM_METHOD_CALLER init_method_caller() {
131                 WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
132                 return _emval_get_method_caller(args.getCount(), args.getTypes());
133             }
134         };
135 
136         struct DestructorsRunner {
137         public:
DestructorsRunnerDestructorsRunner138             explicit DestructorsRunner(EM_DESTRUCTORS d)
139                 : destructors(d)
140             {}
~DestructorsRunnerDestructorsRunner141             ~DestructorsRunner() {
142                 _emval_run_destructors(destructors);
143             }
144 
145             DestructorsRunner(const DestructorsRunner&) = delete;
146             void operator=(const DestructorsRunner&) = delete;
147 
148         private:
149             EM_DESTRUCTORS destructors;
150         };
151 
152         template<typename WireType>
153         struct GenericWireTypeConverter {
fromGenericWireTypeConverter154             static WireType from(double wt) {
155                 return static_cast<WireType>(wt);
156             }
157         };
158 
159         template<typename Pointee>
160         struct GenericWireTypeConverter<Pointee*> {
161             static Pointee* from(double wt) {
162                 return reinterpret_cast<Pointee*>(static_cast<uintptr_t>(wt));
163             }
164         };
165 
166         template<typename T>
167         T fromGenericWireType(double g) {
168             typedef typename BindingType<T>::WireType WireType;
169             WireType wt = GenericWireTypeConverter<WireType>::from(g);
170             return BindingType<T>::fromWireType(wt);
171         }
172 
173         template<typename... Args>
174         struct PackSize;
175 
176         template<>
177         struct PackSize<> {
178             static constexpr size_t value = 0;
179         };
180 
181         template<typename Arg, typename... Args>
182         struct PackSize<Arg, Args...> {
183             static constexpr size_t value = (sizeof(typename BindingType<Arg>::WireType) + 7) / 8 + PackSize<Args...>::value;
184         };
185 
186         union GenericWireType {
187             union {
188                 unsigned u;
189                 float f;
190                 const void* p;
191             } w[2];
192             double d;
193         };
194         static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes");
195         static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned");
196 
197         inline void writeGenericWireType(GenericWireType*& cursor, float wt) {
198             cursor->w[0].f = wt;
199             ++cursor;
200         }
201 
202         inline void writeGenericWireType(GenericWireType*& cursor, double wt) {
203             cursor->d = wt;
204             ++cursor;
205         }
206 
207         template<typename T>
208         void writeGenericWireType(GenericWireType*& cursor, T* wt) {
209             cursor->w[0].p = wt;
210             ++cursor;
211         }
212 
213         template<typename ElementType>
214         inline void writeGenericWireType(GenericWireType*& cursor, const memory_view<ElementType>& wt) {
215             cursor->w[0].u = wt.size;
216             cursor->w[1].p = wt.data;
217             ++cursor;
218         }
219 
220         template<typename T>
221         void writeGenericWireType(GenericWireType*& cursor, T wt) {
222             cursor->w[0].u = static_cast<unsigned>(wt);
223             ++cursor;
224         }
225 
226         inline void writeGenericWireTypes(GenericWireType*&) {
227         }
228 
229         template<typename First, typename... Rest>
230         EMSCRIPTEN_ALWAYS_INLINE void writeGenericWireTypes(GenericWireType*& cursor, First&& first, Rest&&... rest) {
231             writeGenericWireType(cursor, BindingType<First>::toWireType(std::forward<First>(first)));
232             writeGenericWireTypes(cursor, std::forward<Rest>(rest)...);
233         }
234 
235         template<typename... Args>
236         struct WireTypePack {
237             WireTypePack(Args&&... args) {
238                 GenericWireType* cursor = elements.data();
239                 writeGenericWireTypes(cursor, std::forward<Args>(args)...);
240             }
241 
242             operator EM_VAR_ARGS() const {
243                 return elements.data();
244             }
245 
246         private:
247             std::array<GenericWireType, PackSize<Args...>::value> elements;
248         };
249 
250         template<typename ReturnType, typename... Args>
251         struct MethodCaller {
252             static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) {
253                 auto caller = Signature<ReturnType, Args...>::get_method_caller();
254 
255                 WireTypePack<Args...> argv(std::forward<Args>(args)...);
256                 EM_DESTRUCTORS destructors;
257                 EM_GENERIC_WIRE_TYPE result = _emval_call_method(
258                     caller,
259                     handle,
260                     methodName,
261                     &destructors,
262                     argv);
263                 DestructorsRunner rd(destructors);
264                 return fromGenericWireType<ReturnType>(result);
265             }
266         };
267 
268         template<typename... Args>
269         struct MethodCaller<void, Args...> {
270             static void call(EM_VAL handle, const char* methodName, Args&&... args) {
271                 auto caller = Signature<void, Args...>::get_method_caller();
272 
273                 WireTypePack<Args...> argv(std::forward<Args>(args)...);
274                 _emval_call_void_method(
275                     caller,
276                     handle,
277                     methodName,
278                     argv);
279             }
280         };
281     }
282 
283 #define EMSCRIPTEN_SYMBOL(name)                                         \
284     static const char name##_symbol[] = #name;                          \
285     static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
286 
287     class val {
288     public:
289         // missing operators:
290         // * ~ - + ++ --
291         // * * / %
292         // * + -
293         // * << >> >>>
294         // * & ^ | && || ?:
295         //
296         // exposing void, comma, and conditional is unnecessary
297         // same with: = += -= *= /= %= <<= >>= >>>= &= ^= |=
298 
299         static val array() {
300             return val(internal::_emval_new_array());
301         }
302 
303         template<typename Iter>
304         static val array(Iter begin, Iter end) {
305             val new_array = array();
306             for (auto it = begin; it != end; ++it) {
307                 new_array.call<void>("push", *it);
308             }
309             return new_array;
310         }
311 
312         template<typename T>
313         static val array(const std::vector<T>& vec) {
314             return array(vec.begin(), vec.end());
315         }
316 
317         static val object() {
318             return val(internal::_emval_new_object());
319         }
320 
321         static val undefined() {
322             return val(internal::EM_VAL(internal::_EMVAL_UNDEFINED));
323         }
324 
325         static val null() {
326             return val(internal::EM_VAL(internal::_EMVAL_NULL));
327         }
328 
329         static val take_ownership(internal::EM_VAL e) {
330             return val(e);
331         }
332 
333         static val global(const char* name = 0) {
334             return val(internal::_emval_get_global(name));
335         }
336 
337         static val module_property(const char* name) {
338             return val(internal::_emval_get_module_property(name));
339         }
340 
341         template<typename T>
342         explicit val(T&& value) {
343             using namespace internal;
344 
345             typedef internal::BindingType<T> BT;
346             WireTypePack<T> argv(std::forward<T>(value));
347             handle = _emval_take_value(
348                 internal::TypeID<T>::get(),
349                 argv);
350         }
351 
352         val() = delete;
353 
354         explicit val(const char* v)
355             : handle(internal::_emval_new_cstring(v))
356         {}
357 
358         val(val&& v)
359             : handle(v.handle)
360         {
361             v.handle = 0;
362         }
363 
364         val(const val& v)
365             : handle(v.handle)
366         {
367             internal::_emval_incref(handle);
368         }
369 
370         ~val() {
371             internal::_emval_decref(handle);
372         }
373 
374         val& operator=(val&& v) {
375             internal::_emval_decref(handle);
376             handle = v.handle;
377             v.handle = 0;
378             return *this;
379         }
380 
381         val& operator=(const val& v) {
382             internal::_emval_incref(v.handle);
383             internal::_emval_decref(handle);
384             handle = v.handle;
385             return *this;
386         }
387 
388         bool hasOwnProperty(const char* key) const {
389             return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key));
390         }
391 
392         bool isNull() const {
393             return handle == internal::EM_VAL(internal::_EMVAL_NULL);
394         }
395 
396         bool isUndefined() const {
397             return handle == internal::EM_VAL(internal::_EMVAL_UNDEFINED);
398         }
399 
400         bool isTrue() const {
401             return handle == internal::EM_VAL(internal::_EMVAL_TRUE);
402         }
403 
404         bool isFalse() const {
405             return handle == internal::EM_VAL(internal::_EMVAL_FALSE);
406         }
407 
408         bool isNumber() const {
409             return internal::_emval_is_number(handle);
410         }
411 
412         bool isString() const {
413             return internal::_emval_is_string(handle);
414         }
415 
416         bool isArray() const {
417             return instanceof(global("Array"));
418         }
419 
420         bool equals(const val& v) const {
421             return internal::_emval_equals(handle, v.handle);
422         }
423 
424         bool operator==(const val& v) const {
425             return internal::_emval_equals(handle, v.handle);
426         }
427 
428         bool operator!=(const val& v) const {
429             return !(*this == v);
430         }
431 
432         bool strictlyEquals(const val& v) const {
433             return internal::_emval_strictly_equals(handle, v.handle);
434         }
435 
436         bool operator>(const val& v) const {
437             return internal::_emval_greater_than(handle, v.handle);
438         }
439 
440         bool operator>=(const val& v) const {
441             return (*this > v) || (*this == v);
442         }
443 
444         bool operator<(const val& v) const {
445             return internal::_emval_less_than(handle, v.handle);
446         }
447 
448         bool operator<=(const val& v) const {
449             return (*this < v) || (*this == v);
450         }
451 
452         bool operator!() const {
453             return internal::_emval_not(handle);
454         }
455 
456         template<typename... Args>
457         val new_(Args&&... args) const {
458             return internalCall(internal::_emval_new,std::forward<Args>(args)...);
459         }
460 
461         template<typename T>
462         val operator[](const T& key) const {
463             return val(internal::_emval_get_property(handle, val(key).handle));
464         }
465 
466         template<typename K>
467         void set(const K& key, const val& v) {
468             internal::_emval_set_property(handle, val(key).handle, v.handle);
469         }
470 
471         template<typename K, typename V>
472         void set(const K& key, const V& value) {
473             internal::_emval_set_property(handle, val(key).handle, val(value).handle);
474         }
475 
476         template<typename... Args>
477         val operator()(Args&&... args) const {
478             return internalCall(internal::_emval_call, std::forward<Args>(args)...);
479         }
480 
481         template<typename ReturnValue, typename... Args>
482         ReturnValue call(const char* name, Args&&... args) const {
483             using namespace internal;
484 
485             return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
486         }
487 
488         template<typename T, typename ...Policies>
489         T as(Policies...) const {
490             using namespace internal;
491 
492             typedef BindingType<T> BT;
493             typename WithPolicies<Policies...>::template ArgTypeList<T> targetType;
494 
495             EM_DESTRUCTORS destructors;
496             EM_GENERIC_WIRE_TYPE result = _emval_as(
497                 handle,
498                 targetType.getTypes()[0],
499                 &destructors);
500             DestructorsRunner dr(destructors);
501             return fromGenericWireType<T>(result);
502         }
503 
504 // If code is not being compiled with GNU extensions enabled, typeof() is not a reserved keyword, so support that as a member function.
505 #if __STRICT_ANSI__
506         val typeof() const {
507             return val(_emval_typeof(handle));
508         }
509 #endif
510 
511 // 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.
512         val typeOf() const {
513             return val(_emval_typeof(handle));
514         }
515 
516         bool instanceof(const val& v) const {
517             return internal::_emval_instanceof(handle, v.handle);
518         }
519 
520         bool in(const val& v) const {
521             return internal::_emval_in(handle, v.handle);
522         }
523 
524         template<typename T>
525         bool delete_(const T& property) const {
526             return internal::_emval_delete(handle, val(property).handle);
527         }
528 
529         void throw_() const {
530             internal::_emval_throw(handle);
531         }
532 
533         val await() const {
534             return val(internal::_emval_await(handle));
535         }
536 
537     private:
538         // takes ownership, assumes handle already incref'd
539         explicit val(internal::EM_VAL handle)
540             : handle(handle)
541         {}
542 
543         template<typename WrapperType>
544         friend val internal::wrapped_extend(const std::string& , const val& );
545 
546         internal::EM_VAL __get_handle() const {
547             return handle;
548         }
549 
550         template<typename Implementation, typename... Args>
551         val internalCall(Implementation impl, Args&&... args) const {
552             using namespace internal;
553 
554             WithPolicies<>::ArgTypeList<Args...> argList;
555             WireTypePack<Args...> argv(std::forward<Args>(args)...);
556             return val(
557                 impl(
558                     handle,
559                     argList.getCount(),
560                     argList.getTypes(),
561                     argv));
562         }
563 
564         internal::EM_VAL handle;
565 
566         friend struct internal::BindingType<val>;
567     };
568 
569     namespace internal {
570         template<>
571         struct BindingType<val> {
572             typedef internal::EM_VAL WireType;
573             static WireType toWireType(const val& v) {
574                 _emval_incref(v.handle);
575                 return v.handle;
576             }
577             static val fromWireType(WireType v) {
578                 return val::take_ownership(v);
579             }
580         };
581     }
582 
583     template<typename T>
584     std::vector<T> vecFromJSArray(val v) {
585         auto l = v["length"].as<unsigned>();
586 
587         std::vector<T> rv;
588         for(unsigned i = 0; i < l; ++i) {
589             rv.push_back(v[i].as<T>());
590         }
591 
592         return rv;
593     };
594 }
595