aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/include/emscripten/bind.h646
-rw-r--r--system/include/emscripten/emscripten.h65
-rw-r--r--system/include/emscripten/val.h177
-rw-r--r--system/include/emscripten/wire.h223
-rw-r--r--system/include/jansson.h305
-rw-r--r--system/include/jansson_config.h54
-rwxr-xr-xsystem/lib/embind/bind.cpp34
7 files changed, 1500 insertions, 4 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
new file mode 100644
index 00000000..4a82eacb
--- /dev/null
+++ b/system/include/emscripten/bind.h
@@ -0,0 +1,646 @@
+#pragma once
+
+#include <stddef.h>
+#include <assert.h>
+#include <string>
+#include <type_traits>
+#include <emscripten/val.h>
+#include <emscripten/wire.h>
+
+namespace emscripten {
+ namespace internal {
+ typedef void (*GenericFunction)();
+ typedef long GenericEnumValue;
+
+ // Implemented in JavaScript. Don't call these directly.
+ extern "C" {
+ void _embind_fatal_error(
+ const char* name,
+ const char* payload) __attribute__((noreturn));
+
+ void _embind_register_void(
+ TypeID voidType,
+ const char* name);
+
+ void _embind_register_bool(
+ TypeID boolType,
+ const char* name,
+ bool trueValue,
+ bool falseValue);
+
+ void _embind_register_integer(
+ TypeID integerType,
+ const char* name);
+
+ void _embind_register_float(
+ TypeID floatType,
+ const char* name);
+
+ void _embind_register_cstring(
+ TypeID stringType,
+ const char* name);
+
+ void _embind_register_emval(
+ TypeID emvalType,
+ const char* name);
+
+ void _embind_register_function(
+ const char* name,
+ TypeID returnType,
+ unsigned argCount,
+ TypeID argTypes[],
+ GenericFunction invoker,
+ GenericFunction function);
+
+ void _embind_register_tuple(
+ TypeID tupleType,
+ const char* name,
+ GenericFunction constructor,
+ GenericFunction destructor);
+
+ void _embind_register_tuple_element(
+ TypeID tupleType,
+ TypeID elementType,
+ GenericFunction getter,
+ GenericFunction setter,
+ size_t memberPointerSize,
+ void* memberPointer);
+
+ void _embind_register_tuple_element_accessor(
+ TypeID tupleType,
+ TypeID elementType,
+ GenericFunction staticGetter,
+ size_t getterSize,
+ void* getter,
+ GenericFunction staticSetter,
+ size_t setterSize,
+ void* setter);
+
+ void _embind_register_struct(
+ TypeID structType,
+ const char* name,
+ GenericFunction constructor,
+ GenericFunction destructor);
+
+ void _embind_register_struct_field(
+ TypeID structType,
+ const char* name,
+ TypeID fieldType,
+ GenericFunction getter,
+ GenericFunction setter,
+ size_t memberPointerSize,
+ void* memberPointer);
+
+ void _embind_register_class(
+ TypeID classType,
+ const char* className,
+ GenericFunction destructor);
+
+ void _embind_register_class_constructor(
+ TypeID classType,
+ unsigned argCount,
+ TypeID argTypes[],
+ GenericFunction constructor);
+
+ void _embind_register_class_method(
+ TypeID classType,
+ const char* methodName,
+ TypeID returnType,
+ unsigned argCount,
+ TypeID argTypes[],
+ GenericFunction invoker,
+ size_t memberFunctionSize,
+ void* memberFunction);
+
+ void _embind_register_class_field(
+ TypeID classType,
+ const char* fieldName,
+ TypeID fieldType,
+ GenericFunction getter,
+ GenericFunction setter,
+ size_t memberPointerSize,
+ void* memberPointer);
+
+ void _embind_register_class_classmethod(
+ TypeID classType,
+ const char* methodName,
+ TypeID returnType,
+ unsigned argCount,
+ TypeID argTypes[],
+ GenericFunction method);
+
+ void _embind_register_enum(
+ TypeID enumType,
+ const char* name);
+
+ void _embind_register_enum_value(
+ TypeID enumType,
+ const char* valueName,
+ GenericEnumValue value);
+
+ void _embind_register_interface(
+ TypeID interfaceType,
+ const char* name,
+ GenericFunction constructor,
+ GenericFunction destructor);
+ }
+
+ extern void registerStandardTypes();
+
+ class BindingsDefinition {
+ public:
+ template<typename Function>
+ BindingsDefinition(Function fn) {
+ fn();
+ }
+ };
+ }
+}
+
+namespace emscripten {
+ namespace internal {
+ template<typename ReturnType, typename... Args>
+ struct Invoker {
+ static typename internal::BindingType<ReturnType>::WireType invoke(
+ ReturnType (fn)(Args...),
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return internal::BindingType<ReturnType>::toWireType(
+ fn(
+ internal::BindingType<Args>::fromWireType(args)...
+ )
+ );
+ }
+ };
+
+ template<typename... Args>
+ struct Invoker<void, Args...> {
+ static void invoke(
+ void (fn)(Args...),
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return fn(
+ internal::BindingType<Args>::fromWireType(args)...
+ );
+ }
+ };
+ }
+
+ template<typename ReturnType, typename... Args>
+ void function(const char* name, ReturnType (fn)(Args...)) {
+ internal::registerStandardTypes();
+
+ internal::ArgTypeList<Args...> args;
+ internal::_embind_register_function(
+ name,
+ internal::getTypeID<ReturnType>(),
+ args.count,
+ args.types,
+ reinterpret_cast<internal::GenericFunction>(&internal::Invoker<ReturnType, Args...>::invoke),
+ reinterpret_cast<internal::GenericFunction>(fn));
+ }
+
+ namespace internal {
+ template<typename ClassType, typename... Args>
+ ClassType* raw_constructor(
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return new ClassType(
+ internal::BindingType<Args>::fromWireType(args)...
+ );
+ }
+
+ template<typename ClassType>
+ void raw_destructor(ClassType* ptr) {
+ delete ptr;
+ }
+
+ template<typename ClassType, typename ReturnType, typename... Args>
+ struct MethodInvoker {
+ typedef ReturnType (ClassType::*MemberPointer)(Args...);
+ typename internal::BindingType<ReturnType>::WireType invoke(
+ ClassType* ptr,
+ const MemberPointer& method,
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return internal::BindingType<ReturnType>::toWireType(
+ (ptr->*method)(
+ internal::BindingType<Args>::fromWireType(args)...
+ )
+ );
+ }
+ };
+
+ template<typename ClassType, typename... Args>
+ struct MethodInvoker<ClassType, void, Args...> {
+ typedef void (ClassType::*MemberPointer)(Args...);
+ static void invoke(
+ ClassType* ptr,
+ const MemberPointer& method,
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return (ptr->*method)(
+ internal::BindingType<Args>::fromWireType(args)...
+ );
+ }
+ };
+
+ template<typename ClassType, typename ReturnType, typename... Args>
+ struct ConstMethodInvoker {
+ typedef ReturnType (ClassType::*MemberPointer)(Args...) const;
+ static typename internal::BindingType<ReturnType>::WireType invoke(
+ const ClassType* ptr,
+ const MemberPointer& method,
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return internal::BindingType<ReturnType>::toWireType(
+ (ptr->*method)(
+ internal::BindingType<Args>::fromWireType(args)...
+ )
+ );
+ }
+ };
+
+ template<typename ClassType, typename... Args>
+ struct ConstMethodInvoker<ClassType, void, Args...> {
+ typedef void (ClassType::*MemberPointer)(Args...) const;
+ static void invoke(
+ const ClassType* ptr,
+ const MemberPointer& method,
+ typename internal::BindingType<Args>::WireType... args
+ ) {
+ return (ptr->*method)(
+ internal::BindingType<Args>::fromWireType(args)...
+ );
+ }
+ };
+
+ template<typename ClassType, typename FieldType>
+ struct FieldAccess {
+ typedef FieldType ClassType::*MemberPointer;
+ typedef internal::BindingType<FieldType> FieldBinding;
+ typedef typename FieldBinding::WireType WireType;
+
+ static WireType get(
+ ClassType& ptr,
+ const MemberPointer& field
+ ) {
+ return FieldBinding::toWireType(ptr.*field);
+ }
+
+ static void set(
+ ClassType& ptr,
+ const MemberPointer& field,
+ WireType value
+ ) {
+ ptr.*field = FieldBinding::fromWireType(value);
+ }
+
+ template<typename Getter>
+ static WireType propertyGet(
+ ClassType& ptr,
+ const Getter& getter
+ ) {
+ return FieldBinding::toWireType(getter(ptr));
+ }
+
+ template<typename Setter>
+ static void propertySet(
+ ClassType& ptr,
+ const Setter& setter,
+ WireType value
+ ) {
+ setter(ptr, FieldBinding::fromWireType(value));
+ }
+ };
+ }
+
+ template<typename ClassType>
+ class value_tuple {
+ public:
+ value_tuple(const char* name) {
+ internal::registerStandardTypes();
+ internal::_embind_register_tuple(
+ internal::getTypeID<ClassType>(),
+ name,
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ }
+
+ template<typename ElementType>
+ value_tuple& element(ElementType ClassType::*field) {
+ internal::_embind_register_tuple_element(
+ internal::getTypeID<ClassType>(),
+ internal::getTypeID<ElementType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::get),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::set),
+ sizeof(field),
+ &field);
+
+ return *this;
+ }
+
+ template<typename ElementType>
+ value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType)) {
+ internal::_embind_register_tuple_element_accessor(
+ internal::getTypeID<ClassType>(),
+ internal::getTypeID<ElementType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
+ sizeof(getter),
+ &getter,
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
+ sizeof(setter),
+ &setter);
+ return *this;
+ }
+
+ template<typename ElementType>
+ value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&)) {
+ internal::_embind_register_tuple_element_accessor(
+ internal::getTypeID<ClassType>(),
+ internal::getTypeID<ElementType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
+ sizeof(getter),
+ &getter,
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
+ sizeof(setter),
+ &setter);
+ return *this;
+ }
+
+ template<typename ElementType>
+ value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&&)) {
+ internal::_embind_register_tuple_element_accessor(
+ internal::getTypeID<ClassType>(),
+ internal::getTypeID<ElementType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
+ sizeof(getter),
+ &getter,
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
+ sizeof(setter),
+ &setter);
+ return *this;
+ }
+
+ template<typename ElementType>
+ value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType&)) {
+ internal::_embind_register_tuple_element_accessor(
+ internal::getTypeID<ClassType>(),
+ internal::getTypeID<ElementType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
+ sizeof(getter),
+ &getter,
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
+ sizeof(setter),
+ &setter);
+ return *this;
+ }
+ };
+
+ template<typename ClassType>
+ class value_struct {
+ public:
+ value_struct(const char* name) {
+ internal::registerStandardTypes();
+ internal::_embind_register_struct(
+ internal::getTypeID<ClassType>(),
+ name,
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ }
+
+ template<typename FieldType>
+ value_struct& field(const char* fieldName, FieldType ClassType::*field) {
+ internal::_embind_register_struct_field(
+ internal::getTypeID<ClassType>(),
+ fieldName,
+ internal::getTypeID<FieldType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::get),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::set),
+ sizeof(field),
+ &field);
+
+ return *this;
+ }
+ };
+
+ // TODO: support class definitions without constructors.
+ // TODO: support external class constructors
+ template<typename ClassType>
+ class class_ {
+ public:
+ class_(const char* name) {
+ internal::registerStandardTypes();
+ internal::_embind_register_class(
+ internal::getTypeID<ClassType>(),
+ name,
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ }
+
+ template<typename... ConstructorArgs>
+ class_& constructor() {
+ internal::ArgTypeList<ConstructorArgs...> args;
+ internal::_embind_register_class_constructor(
+ internal::getTypeID<ClassType>(),
+ args.count,
+ args.types,
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType, ConstructorArgs...>));
+ }
+
+ template<typename ReturnType, typename... Args>
+ class_& method(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...)) {
+ internal::ArgTypeList<Args...> args;
+ internal::_embind_register_class_method(
+ internal::getTypeID<ClassType>(),
+ methodName,
+ internal::getTypeID<ReturnType>(),
+ args.count,
+ args.types,
+ reinterpret_cast<internal::GenericFunction>(&internal::MethodInvoker<ClassType, ReturnType, Args...>::invoke),
+ sizeof(memberFunction),
+ &memberFunction);
+ return *this;
+ }
+
+ template<typename ReturnType, typename... Args>
+ class_& method(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const) {
+ internal::ArgTypeList<Args...> args;
+ internal::_embind_register_class_method(
+ internal::getTypeID<ClassType>(),
+ methodName,
+ internal::getTypeID<ReturnType>(),
+ args.count,
+ args.types,
+ reinterpret_cast<internal::GenericFunction>(&internal::ConstMethodInvoker<ClassType, ReturnType, Args...>::invoke),
+ sizeof(memberFunction),
+ &memberFunction);
+ return *this;
+ }
+
+ template<typename FieldType>
+ class_& field(const char* fieldName, FieldType ClassType::*field) {
+ internal::_embind_register_class_field(
+ internal::getTypeID<ClassType>(),
+ fieldName,
+ internal::getTypeID<FieldType>(),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::get),
+ reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::set),
+ sizeof(field),
+ &field);
+ return *this;
+ }
+
+ template<typename ReturnType, typename... Args>
+ class_& classmethod(const char* methodName, ReturnType (*classMethod)(Args...)) {
+ internal::ArgTypeList<Args...> args;
+ internal::_embind_register_class_classmethod(
+ internal::getTypeID<ClassType>(),
+ methodName,
+ internal::getTypeID<ReturnType>(),
+ args.count,
+ args.types,
+ reinterpret_cast<internal::GenericFunction>(classMethod));
+ return *this;
+ }
+ };
+
+ template<typename EnumType>
+ class enum_ {
+ public:
+ enum_(const char* name) {
+ _embind_register_enum(
+ internal::getTypeID<EnumType>(),
+ name);
+ }
+
+ enum_& value(const char* name, EnumType value) {
+ // TODO: there's still an issue here.
+ // if EnumType is an unsigned long, then JS may receive it as a signed long
+ static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue");
+
+ _embind_register_enum_value(
+ internal::getTypeID<EnumType>(),
+ name,
+ static_cast<internal::GenericEnumValue>(value));
+ return *this;
+ }
+ };
+
+ namespace internal {
+ template<typename T>
+ class optional {
+ public:
+ optional()
+ : initialized(false)
+ {}
+
+ ~optional() {
+ if (initialized) {
+ get()->~T();
+ }
+ }
+
+ optional(const optional&) = delete;
+
+ T& operator*() {
+ assert(initialized);
+ return *get();
+ }
+
+ explicit operator bool() const {
+ return initialized;
+ }
+
+ optional& operator=(const T& v) {
+ if (initialized) {
+ get()->~T();
+ }
+ new(get()) T(v);
+ initialized = true;
+ }
+
+ private:
+ T* get() {
+ return reinterpret_cast<T*>(&data);
+ }
+
+ bool initialized;
+ typename std::aligned_storage<sizeof(T)>::type data;
+ };
+ }
+
+ template<typename InterfaceType>
+ class wrapper : public InterfaceType {
+ public:
+ // Not necessary in any example so far, but appeases a compiler warning.
+ virtual ~wrapper() {}
+
+ typedef InterfaceType interface;
+
+ void initialize(internal::EM_VAL handle) {
+ if (jsobj) {
+ internal::_embind_fatal_error(
+ "Cannot initialize interface wrapper twice",
+ typeid(InterfaceType).name());
+ }
+ jsobj = val::take_ownership(handle);
+ }
+
+ template<typename ReturnType, typename... Args>
+ ReturnType call(const char* name, Args... args) {
+ assertInitialized();
+ return Caller<ReturnType, Args...>::call(*jsobj, name, args...);
+ }
+
+ private:
+ // this class only exists because you can't partially specialize function templates
+ template<typename ReturnType, typename... Args>
+ struct Caller {
+ static ReturnType call(val& v, const char* name, Args... args) {
+ return v.call(name, args...).template as<ReturnType>();
+ }
+ };
+
+ template<typename... Args>
+ struct Caller<void, Args...> {
+ static void call(val& v, const char* name, Args... args) {
+ v.call(name, args...);
+ }
+ };
+
+ void assertInitialized() {
+ if (!jsobj) {
+ internal::_embind_fatal_error(
+ "Cannot invoke call on uninitialized interface wrapper.",
+ typeid(InterfaceType).name());
+ }
+ }
+
+ internal::optional<val> jsobj;
+ };
+
+ namespace internal {
+ template<typename WrapperType>
+ WrapperType* create_interface_wrapper(EM_VAL e) {
+ WrapperType* p = new WrapperType;
+ p->initialize(e);
+ return p;
+ }
+ }
+
+ template<typename WrapperType>
+ class interface {
+ public:
+ typedef typename WrapperType::interface InterfaceType;
+
+ interface(const char* name) {
+ _embind_register_interface(
+ internal::getTypeID<InterfaceType>(),
+ name,
+ reinterpret_cast<internal::GenericFunction>(&internal::create_interface_wrapper<WrapperType>),
+ reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<WrapperType>));
+ }
+ };
+}
+
+#define EMSCRIPTEN_BINDINGS(fn) static emscripten::internal::BindingsDefinition anon_symbol(fn);
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index 8c42a18a..ed078acd 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -11,6 +11,10 @@
extern "C" {
#endif
+#if !EMSCRIPTEN
+#include <SDL/SDL.h> /* for SDL_Delay in async_call */
+#endif
+
/*
* Forces LLVM to not dead-code-eliminate a function. Note that
* closure may still eliminate it at the JS level, for which you
@@ -42,11 +46,32 @@ extern void emscripten_async_run_script(const char *script, int millis);
* code assumes that), so you can break the code up into
* asynchronous callbacks, but you must pause the main
* loop until they complete.
+ *
+ * @simulate_infinite_loop If true, this function will throw an
+ * exception in order to stop execution of the caller. This
+ * will lead to the main loop being entered instead of code
+ * after the call to emscripten_set_main_loop being run, which
+ * is the closest we can get to simulating an infinite loop
+ * (we do something similar in glutMainLoop in GLUT). If this
+ * parameter is false, then the behavior is the same as it
+ * was before this parameter was added to the API, which is
+ * that execution continues normally. Note that in both cases
+ * we do not run global destructors, atexit, etc., since we
+ * know the main loop will still be running, but if we do
+ * not simulate an infinite loop then the stack will be unwinded.
+ * That means that if simulate_infinite_loop is false, and
+ * you created an object on the stack, it will be cleaned up
+ * before the main loop will be called the first time.
*/
-extern void emscripten_set_main_loop(void (*func)(), int fps);
+#if EMSCRIPTEN
+extern void emscripten_set_main_loop(void (*func)(), int fps, int simulate_infinite_loop);
extern void emscripten_pause_main_loop();
extern void emscripten_resume_main_loop();
extern void emscripten_cancel_main_loop();
+#else
+#define emscripten_set_main_loop(func, fps, simulateInfiniteLoop) \
+ while (1) func();
+#endif
/*
* Add a function to a queue of events that will execute
@@ -148,14 +173,46 @@ float emscripten_random();
*/
/*
- * Load file from url in asynchronous way.
- * When file is loaded then 'onload' callback will called.
+ * Load file from url in asynchronous way. In addition to
+ * fetching the URL from the network, the contents are
+ * prepared so that the data is usable in IMG_Load and
+ * so forth (we asynchronously do the work to make the
+ * browser decode the image or audio and so forth).
+ * When file is ready then 'onload' callback will called.
* If any error occurred 'onerror' will called.
* The callbacks are called with the file as their argument.
- */
+ */
void emscripten_async_wget(const char* url, const char* file, void (*onload)(const char*), void (*onerror)(const char*));
/*
+ * Prepare a file in asynchronous way. This does just the
+ * preparation part of emscripten_async_wget, that is, it
+ * works on file data already present, and asynchronously
+ * prepares it for use in IMG_Load, Mix_LoadWAV, etc.
+ * When file is loaded then 'onload' callback will called.
+ * If any error occurred 'onerror' will called.
+ * The callbacks are called with the file as their argument.
+ * @return 0 if successful, -1 if the file does not exist
+ */
+int emscripten_async_prepare(const char* file, void (*onload)(const char*), void (*onerror)(const char*));
+
+/*
+ * Data version of emscripten_async_prepare, which receives
+ * raw data as input instead of a filename (this can prevent
+ * the need to write data to a file first). onload and
+ * onerror are called back with the given arg pointer as the
+ * first parameter. onload also receives a second
+ * parameter, which is a 'fake' filename which you can
+ * then pass into IMG_Load (it is not an actual file,
+ * but it identifies this image for IMG_Load to be able
+ * to process it). Note that the user of this API is
+ * responsible for free()ing the memory allocated for
+ * the fake filename.
+ * @suffix The file suffix, e.g. 'png' or 'jpg'.
+ */
+void emscripten_async_prepare_data(char* data, int size, const char *suffix, void *arg, void (*onload)(void*, const char*), void (*onerror)(void*));
+
+/*
* Profiling tools.
* INIT must be called first, with the maximum identifier that
* will be used. BEGIN will add some code that marks
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
new file mode 100644
index 00000000..96db9326
--- /dev/null
+++ b/system/include/emscripten/val.h
@@ -0,0 +1,177 @@
+#pragma once
+
+#include <stdint.h> // uintptr_t
+#include <emscripten/wire.h>
+
+namespace emscripten {
+ namespace internal {
+ // Implemented in JavaScript. Don't call these directly.
+ extern "C" {
+ typedef struct _EM_VAL* EM_VAL;
+
+ void _emval_incref(EM_VAL value);
+ void _emval_decref(EM_VAL value);
+ EM_VAL _emval_new_object();
+ EM_VAL _emval_new_long(long value);
+ EM_VAL _emval_new_cstring(const char* str);
+ EM_VAL _emval_get_property(EM_VAL object, const char* key);
+ EM_VAL _emval_get_property_by_long(EM_VAL object, long key);
+ EM_VAL _emval_get_property_by_unsigned_long(EM_VAL object, unsigned long key);
+ void _emval_set_property(EM_VAL object, const char* key, EM_VAL value);
+ void _emval_set_property_by_int(EM_VAL object, long key, EM_VAL value);
+ void _emval_as(EM_VAL value, emscripten::internal::TypeID returnType);
+ EM_VAL _emval_call(
+ EM_VAL value,
+ unsigned argCount,
+ internal::TypeID argTypes[]
+ /*, ... */);
+ EM_VAL _emval_call_method(
+ EM_VAL value,
+ const char* methodName,
+ unsigned argCount,
+ internal::TypeID argTypes[]
+ /*, ... */);
+ }
+ }
+
+ class val {
+ public:
+ static val object() {
+ return val(internal::_emval_new_object());
+ };
+
+ static val take_ownership(internal::EM_VAL e) {
+ return val(e);
+ }
+
+ explicit val(long l)
+ : handle(internal::_emval_new_long(l))
+ {}
+
+ explicit val(const char* str)
+ : handle(internal::_emval_new_cstring(str))
+ {}
+
+ val() = delete;
+
+ val(const val& v)
+ : handle(v.handle)
+ {
+ internal::_emval_incref(handle);
+ }
+
+ ~val() {
+ internal::_emval_decref(handle);
+ }
+
+ val& operator=(const val& v) {
+ internal::_emval_incref(v.handle);
+ internal::_emval_decref(handle);
+ handle = v.handle;
+ return *this;
+ }
+
+ val get(const char* key) const {
+ return val(internal::_emval_get_property(handle, key));
+ }
+
+ val get(int key) const {
+ return get(long(key));
+ }
+
+ val get(unsigned int key) const {
+ typedef unsigned long T;
+ return get(T(key));
+ }
+
+ val get(long key) const {
+ return val(internal::_emval_get_property_by_long(handle, key));
+ }
+
+ val get(unsigned long key) const {
+ return val(internal::_emval_get_property_by_unsigned_long(handle, key));
+ }
+
+ void set(const char* key, val v) {
+ internal::_emval_set_property(handle, key, v.handle);
+ }
+
+ void set(long key, val v) {
+ internal::_emval_set_property_by_int(handle, key, v.handle);
+ }
+
+ template<typename ...Args>
+ val operator()(Args... args) {
+ internal::ArgTypeList<Args...> argList;
+ typedef internal::EM_VAL (*TypedCall)(
+ internal::EM_VAL,
+ unsigned,
+ internal::TypeID argTypes[],
+ typename internal::BindingType<Args>::WireType...);
+ TypedCall typedCall = reinterpret_cast<TypedCall>(&internal::_emval_call);
+ return val(
+ typedCall(
+ handle,
+ argList.count,
+ argList.types,
+ internal::toWireType(args)...));
+ }
+
+ template<typename ...Args>
+ val call(const char* name, Args... args) {
+ internal::ArgTypeList<Args...> argList;
+ typedef internal::EM_VAL (*TypedCall)(
+ internal::EM_VAL,
+ const char* name,
+ unsigned,
+ internal::TypeID argTypes[],
+ typename internal::BindingType<Args>::WireType...);
+ TypedCall typedCall = reinterpret_cast<TypedCall>(&internal::_emval_call_method);
+ return val(
+ typedCall(
+ handle,
+ name,
+ argList.count,
+ argList.types,
+ internal::toWireType(args)...));
+ }
+
+ template<typename T>
+ T as() const {
+ typedef internal::BindingType<T> BT;
+
+ typedef typename BT::WireType (*TypedAs)(
+ internal::EM_VAL value,
+ emscripten::internal::TypeID returnType);
+ TypedAs typedAs = reinterpret_cast<TypedAs>(&internal::_emval_as);
+
+ typename BT::WireType wt = typedAs(handle, internal::getTypeID<T>());
+ internal::WireDeleter<T> deleter(wt);
+ return BT::fromWireType(wt);
+ }
+
+ private:
+ // takes ownership, assumes handle already incref'd
+ explicit val(internal::EM_VAL handle)
+ : handle(handle)
+ {}
+
+ internal::EM_VAL handle;
+
+ friend struct internal::BindingType<val>;
+ };
+
+ namespace internal {
+ template<>
+ struct BindingType<val> {
+ typedef internal::EM_VAL WireType;
+ static WireType toWireType(val v) {
+ _emval_incref(v.handle);