aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rwxr-xr-xsystem/include/emscripten/bind.h192
-rw-r--r--system/include/emscripten/val.h57
-rwxr-xr-xsystem/include/emscripten/wire.h34
-rwxr-xr-xsystem/lib/embind/bind.cpp23
4 files changed, 191 insertions, 115 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 57e44c0c..4d2f4ac8 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -47,10 +47,15 @@ namespace emscripten {
TYPEID floatType,
const char* name);
- void _embind_register_cstring(
+ void _embind_register_std_string(
TYPEID stringType,
const char* name);
+ void _embind_register_std_wstring(
+ TYPEID stringType,
+ size_t charSize,
+ const char* name);
+
void _embind_register_emval(
TYPEID emvalType,
const char* name);
@@ -136,10 +141,12 @@ namespace emscripten {
void _embind_register_class_property(
TYPEID classType,
const char* fieldName,
- TYPEID fieldType,
+ TYPEID getterReturnType,
GenericFunction getter,
+ void* getterContext,
+ TYPEID setterArgumentType,
GenericFunction setter,
- void* context);
+ void* setterContext);
void _embind_register_class_class_function(
TYPEID classType,
@@ -223,6 +230,18 @@ namespace emscripten {
}
namespace internal {
+ template<typename ClassType, typename Signature>
+ struct MemberFunctionType {
+ typedef Signature (ClassType::*type);
+ };
+ }
+
+ template<typename Signature, typename ClassType>
+ typename internal::MemberFunctionType<ClassType, Signature>::type select_overload(Signature (ClassType::*fn)) {
+ return fn;
+ }
+
+ namespace internal {
template<typename ReturnType, typename... Args>
struct Invoker {
static typename internal::BindingType<ReturnType>::WireType invoke(
@@ -277,8 +296,8 @@ namespace emscripten {
}
template<typename WrapperType, typename ClassType, typename... Args>
- WrapperType wrapped_new(Args... args) {
- return WrapperType(new ClassType(args...));
+ WrapperType wrapped_new(Args&&... args) {
+ return WrapperType(new ClassType(std::forward<Args>(args)...));
}
template<typename ClassType, typename... Args>
@@ -711,28 +730,41 @@ namespace emscripten {
template<typename T>
class wrapper : public T {
public:
- wrapper(const val& wrapped)
- : wrapped(wrapped)
+ explicit wrapper(val&& wrapped)
+ : wrapped(std::forward<val>(wrapped))
{}
template<typename ReturnType, typename... Args>
- ReturnType call(const char* name, Args... args) const {
- return Caller<ReturnType, Args...>::call(wrapped, name, args...);
+ ReturnType call(const char* name, Args&&... args) const {
+ return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ }
+
+ template<typename ReturnType, typename... Args, typename Default>
+ ReturnType optional_call(const char* name, Default def, Args&&... args) const {
+ if (has_function(name)) {
+ return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ } else {
+ return def();
+ }
}
private:
+ bool has_function(const char* name) const {
+ return wrapped.has_function(name);
+ }
+
// this class only exists because you can't partially specialize function templates
template<typename ReturnType, typename... Args>
struct Caller {
- static ReturnType call(const val& v, const char* name, Args... args) {
- return v.call(name, args...).template as<ReturnType>();
+ static ReturnType call(const val& v, const char* name, Args&&... args) {
+ return v.call(name, std::forward<Args>(args)...).template as<ReturnType>();
}
};
template<typename... Args>
struct Caller<void, Args...> {
- static void call(const val& v, const char* name, Args... args) {
- v.call_void(name, args...);
+ static void call(const val& v, const char* name, Args&&... args) {
+ v.call_void(name, std::forward<Args>(args)...);
}
};
@@ -740,7 +772,7 @@ namespace emscripten {
};
#define EMSCRIPTEN_WRAPPER(T) \
- T(const ::emscripten::val& v): wrapper(v) {}
+ T(::emscripten::val&& v): wrapper(std::forward<::emscripten::val>(v)) {}
namespace internal {
struct NoBaseClass {
@@ -971,7 +1003,23 @@ namespace emscripten {
return *this;
}
- template<typename FieldType>
+ template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
+ class_& property(const char* fieldName, const FieldType ClassType::*field) {
+ using namespace internal;
+
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getContext(field),
+ 0,
+ 0,
+ 0);
+ return *this;
+ }
+
+ template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
class_& property(const char* fieldName, FieldType ClassType::*field) {
using namespace internal;
@@ -980,11 +1028,46 @@ namespace emscripten {
fieldName,
TypeID<FieldType>::get(),
reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getContext(field),
+ TypeID<FieldType>::get(),
reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template setWire<ClassType>),
getContext(field));
return *this;
}
+ template<typename Getter>
+ class_& property(const char* fieldName, Getter getter) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ 0,
+ 0,
+ 0);
+ return *this;
+ }
+
+ template<typename Getter, typename Setter>
+ class_& property(const char* fieldName, Getter getter, Setter setter) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ typedef SetterPolicy<Setter> SP;
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ TypeID<typename SP::ArgumentType>::get(),
+ reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ SP::getContext(setter));
+ return *this;
+ }
+
template<typename ReturnType, typename... Args, typename... Policies>
class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) {
using namespace internal;
@@ -999,11 +1082,6 @@ namespace emscripten {
reinterpret_cast<GenericFunction>(classMethod));
return *this;
}
-
- template<typename ReturnType, typename... Args, typename... Policies>
- class_& calloperator(const char* methodName, Policies... policies) {
- return function(methodName, &ClassType::operator(), policies...);
- }
};
////////////////////////////////////////////////////////////////////////////////
@@ -1210,80 +1288,6 @@ namespace emscripten {
typename std::aligned_storage<sizeof(T)>::type data;
};
}
-
- ////////////////////////////////////////////////////////////////////////////////
- // NEW INTERFACE
- ////////////////////////////////////////////////////////////////////////////////
-
- class JSInterface {
- public:
- JSInterface(internal::EM_VAL handle) {
- initialize(handle);
- }
-
- JSInterface(const JSInterface& obj)
- : jsobj(obj.jsobj)
- {}
-
- template<typename ReturnType, typename... Args>
- ReturnType call(const char* name, Args... args) {
- assertInitialized();
- return Caller<ReturnType, Args...>::call(*jsobj, name, args...);
- }
-
- static std::shared_ptr<JSInterface> cloneToSharedPtr(const JSInterface& i) {
- return std::make_shared<JSInterface>(i);
- }
-
- private:
- void initialize(internal::EM_VAL handle) {
- if (jsobj) {
- internal::_embind_fatal_error(
- "Cannot initialize interface wrapper twice",
- "JSInterface");
- }
- jsobj = val::take_ownership(handle);
- }
-
- // 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_void(name, args...);
- }
- };
-
- void assertInitialized() {
- if (!jsobj) {
- internal::_embind_fatal_error(
- "Cannot invoke call on uninitialized Javascript interface wrapper.", "JSInterface");
- }
- }
-
- internal::optional<val> jsobj;
- };
-
- namespace internal {
- extern JSInterface* create_js_interface(EM_VAL e);
- }
-
- class register_js_interface {
- public:
- register_js_interface() {
- _embind_register_interface(
- internal::TypeID<JSInterface>::get(),
- "JSInterface",
- reinterpret_cast<internal::GenericFunction>(&internal::create_js_interface),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<JSInterface>));
- }
- };
}
namespace emscripten {
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index 91f775a7..09cad80e 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -8,6 +8,8 @@ namespace emscripten {
namespace internal {
// Implemented in JavaScript. Don't call these directly.
extern "C" {
+ void _emval_register_symbol(const char*);
+
typedef struct _EM_VAL* EM_VAL;
void _emval_incref(EM_VAL value);
@@ -48,9 +50,23 @@ namespace emscripten {
unsigned argCount,
internal::TYPEID argTypes[]
/*, ...*/);
+ bool _emval_has_function(
+ EM_VAL value,
+ const char* methodName);
}
}
+ template<const char* address>
+ struct symbol_registrar {
+ symbol_registrar() {
+ internal::_emval_register_symbol(address);
+ }
+ };
+
+#define EMSCRIPTEN_SYMBOL(name) \
+ static const char name##_symbol[] = #name; \
+ static const symbol_registrar<name##_symbol> name##_registrar
+
class val {
public:
// missing operators:
@@ -98,18 +114,24 @@ namespace emscripten {
}
template<typename T>
- explicit val(const T& value) {
+ explicit val(T&& value) {
typedef internal::BindingType<T> BT;
auto taker = reinterpret_cast<internal::EM_VAL (*)(internal::TYPEID, typename BT::WireType)>(&internal::_emval_take_value);
- handle = taker(internal::TypeID<T>::get(), BT::toWireType(value));
+ handle = taker(internal::TypeID<T>::get(), BT::toWireType(std::forward<T>(value)));
}
val() = delete;
- val(const char* v)
+ explicit val(const char* v)
: handle(internal::_emval_new_cstring(v))
{}
+ val(val&& v)
+ : handle(v.handle)
+ {
+ v.handle = 0;
+ }
+
val(const val& v)
: handle(v.handle)
{
@@ -120,6 +142,13 @@ namespace emscripten {
internal::_emval_decref(handle);
}
+ val& operator=(val&& v) {
+ internal::_emval_decref(handle);
+ handle = v.handle;
+ v.handle = 0;
+ return *this;
+ }
+
val& operator=(const val& v) {
internal::_emval_incref(v.handle);
internal::_emval_decref(handle);
@@ -132,7 +161,7 @@ namespace emscripten {
}
template<typename... Args>
- val new_(Args... args) const {
+ val new_(Args&&... args) const {
using namespace internal;
WithPolicies<>::ArgTypeList<Args...> argList;
@@ -149,7 +178,7 @@ namespace emscripten {
handle,
argList.count,
argList.types,
- toWireType(args)...));
+ toWireType(std::forward<Args>(args))...));
}
template<typename T>
@@ -163,7 +192,7 @@ namespace emscripten {
}
template<typename... Args>
- val operator()(Args... args) {
+ val operator()(Args&&... args) {
using namespace internal;
WithPolicies<>::ArgTypeList<Args...> argList;
@@ -178,11 +207,11 @@ namespace emscripten {
handle,
argList.count,
argList.types,
- toWireType(args)...));
+ toWireType(std::forward<Args>(args))...));
}
template<typename ...Args>
- val call(const char* name, Args... args) const {
+ val call(const char* name, Args&&... args) const {
using namespace internal;
WithPolicies<>::ArgTypeList<Args...> argList;
@@ -199,11 +228,11 @@ namespace emscripten {
name,
argList.count,
argList.types,
- toWireType(args)...));
+ toWireType(std::forward<Args>(args))...));
}
template<typename ...Args>
- void call_void(const char* name, Args... args) const {
+ void call_void(const char* name, Args&&... args) const {
using namespace internal;
WithPolicies<>::ArgTypeList<Args...> argList;
@@ -219,7 +248,11 @@ namespace emscripten {
name,
argList.count,
argList.types,
- toWireType(args)...);
+ toWireType(std::forward<Args>(args))...);
+ }
+
+ bool has_function(const char* name) const {
+ return _emval_has_function(handle, name);
}
template<typename T>
@@ -253,7 +286,7 @@ namespace emscripten {
template<>
struct BindingType<val> {
typedef internal::EM_VAL WireType;
- static WireType toWireType(val v) {
+ static WireType toWireType(const val& v) {
_emval_incref(v.handle);
return v.handle;
}
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index 64114491..6fb15fc7 100755
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -181,11 +181,35 @@ namespace emscripten {
}
};
+ template<>
+ struct BindingType<std::wstring> {
+ typedef struct {
+ size_t length;
+ wchar_t data[1]; // trailing data
+ }* WireType;
+ static WireType toWireType(const std::wstring& v) {
+ WireType wt = (WireType)malloc(sizeof(size_t) + v.length() * sizeof(wchar_t));
+ wt->length = v.length();
+ wmemcpy(wt->data, v.data(), v.length());
+ return wt;
+ }
+ static std::wstring fromWireType(WireType v) {
+ return std::wstring(v->data, v->length);
+ }
+ static void destroy(WireType v) {
+ free(v);
+ }
+ };
+
template<typename T>
struct BindingType<const T> : public BindingType<T> {
};
template<typename T>
+ struct BindingType<T&> : public BindingType<T> {
+ };
+
+ template<typename T>
struct BindingType<const T&> : public BindingType<T> {
};
@@ -216,10 +240,14 @@ namespace emscripten {
typedef typename std::remove_reference<T>::type ActualT;
typedef ActualT* WireType;
- static WireType toWireType(T v) {
+ static WireType toWireType(const T& v) {
return new T(v);
}
+ static WireType toWireType(T&& v) {
+ return new T(std::forward<T>(v));
+ }
+
static ActualT& fromWireType(WireType p) {
return *p;
}
@@ -262,8 +290,8 @@ namespace emscripten {
{};
template<typename T>
- auto toWireType(const T& v) -> typename BindingType<T>::WireType {
- return BindingType<T>::toWireType(v);
+ auto toWireType(T&& v) -> typename BindingType<T>::WireType {
+ return BindingType<T>::toWireType(std::forward<T>(v));
}
template<typename T>
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index deb55138..35d99dad 100755
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -36,12 +36,22 @@ extern "C" {
}
}
-namespace emscripten {
- namespace internal {
- JSInterface* create_js_interface(EM_VAL e) {
- return new JSInterface(e);
- }
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *o++ = c;
+ }
+ return dest;
+}
+
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *dest++ = *src++;
}
+ return dest;
}
EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
@@ -64,6 +74,7 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
_embind_register_float(TypeID<float>::get(), "float");
_embind_register_float(TypeID<double>::get(), "double");
- _embind_register_cstring(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_string(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_wstring(TypeID<std::wstring>::get(), sizeof(wchar_t), "std::wstring");
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
}