aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/embind/embind.js4
-rw-r--r--src/embind/emval.js44
-rw-r--r--system/include/emscripten/bind.h26
-rw-r--r--system/include/emscripten/val.h115
-rw-r--r--system/include/emscripten/wire.h3
5 files changed, 90 insertions, 102 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index cadee700..dfe4c014 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -270,6 +270,10 @@ function __embind_register_void(rawType, name) {
'fromWireType': function() {
return undefined;
},
+ 'toWireType': function(destructors, o) {
+ // TODO: assert if anything else is given?
+ return undefined;
+ },
});
}
diff --git a/src/embind/emval.js b/src/embind/emval.js
index c02ffa92..bfce63b6 100644
--- a/src/embind/emval.js
+++ b/src/embind/emval.js
@@ -1,4 +1,4 @@
-/*global Module*/
+/*global Module, Runtime*/
/*global HEAP32*/
/*global readLatin1String, writeStringToMemory*/
/*global requireRegisteredType, throwBindingError*/
@@ -201,29 +201,31 @@ function __emval_call(handle, argCount, argTypes) {
return __emval_register(rv);
}
-function __emval_call_method(handle, name, argCount, argTypes) {
- requireHandle(handle);
- name = getStringOrSymbol(name);
-
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 4));
- var obj = _emval_handle_array[handle].value;
- var rv = obj[name].apply(obj, args);
- return __emval_register(rv);
+function lookupTypes(argCount, argTypes, argWireTypes) {
+ var a = new Array(argCount);
+ for (var i = 0; i < argCount; ++i) {
+ a[i] = requireRegisteredType(
+ HEAP32[(argTypes >> 2) + i],
+ "parameter " + i);
+ }
+ return a;
}
-function __emval_call_void_method(handle, name, argCount, argTypes) {
- requireHandle(handle);
- name = getStringOrSymbol(name);
+function __emval_get_method_caller(argCount, argTypes) {
+ var types = lookupTypes(argCount, argTypes);
- var args = parseParameters(
- argCount,
- argTypes,
- Array.prototype.slice.call(arguments, 4));
- var obj = _emval_handle_array[handle].value;
- obj[name].apply(obj, args);
+ return Runtime.addFunction(function(handle, name) {
+ requireHandle(handle);
+ name = getStringOrSymbol(name);
+
+ var args = new Array(argCount - 1);
+ for (var i = 1; i < argCount; ++i) {
+ args[i - 1] = types[i].fromWireType(arguments[1 + i]);
+ }
+
+ var obj = _emval_handle_array[handle].value;
+ return types[0].toWireType([], obj[name].apply(obj, args));
+ });
}
function __emval_has_function(handle, name) {
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 7aa2a55e..d6d4f2c5 100644
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -18,7 +18,6 @@ namespace emscripten {
};
namespace internal {
- typedef void (*GenericFunction)();
typedef long GenericEnumValue;
// Implemented in JavaScript. Don't call these directly.
@@ -749,38 +748,19 @@ namespace emscripten {
template<typename ReturnType, typename... Args>
ReturnType call(const char* name, Args&&... args) const {
- return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ return wrapped.call<ReturnType>(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)...);
+ if (wrapped.has_function(name)) {
+ return call<ReturnType>(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, 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, std::forward<Args>(args)...);
- }
- };
-
val wrapped;
};
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index edd070e3..185cc935 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -39,34 +39,67 @@ namespace emscripten {
unsigned argCount,
internal::TYPEID argTypes[]
/*, ... */);
- EM_VAL _emval_call_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ... */);
- void _emval_call_void_method(
- EM_VAL value,
- const char* methodName,
- unsigned argCount,
- internal::TYPEID argTypes[]
- /*, ...*/);
+
+ // DO NOT call this more than once per signature. It will leak function pointer offsets!
+ GenericFunction _emval_get_method_caller(
+ unsigned argCount, // including return value
+ 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);
- }
- };
+ template<const char* address>
+ struct symbol_registrar {
+ symbol_registrar() {
+ internal::_emval_register_symbol(address);
+ }
+ };
+
+ template<typename ReturnType, typename... Args>
+ struct Signature {
+ typedef typename BindingType<ReturnType>::WireType (*MethodCaller)(EM_VAL value, const char* methodName, typename BindingType<Args>::WireType...);
+
+ static MethodCaller get_method_caller() {
+ static MethodCaller fp = reinterpret_cast<MethodCaller>(init_method_caller());
+ return fp;
+ }
+
+ private:
+ static GenericFunction init_method_caller() {
+ WithPolicies<>::ArgTypeList<ReturnType, Args...> args;
+ return _emval_get_method_caller(args.count, args.types);
+ }
+ };
+
+ template<typename ReturnType, typename... Args>
+ struct MethodCaller {
+ static ReturnType call(EM_VAL handle, const char* methodName, Args&&... args) {
+ auto caller = Signature<ReturnType, Args...>::get_method_caller();
+ auto wireType = caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ WireDeleter<ReturnType> deleter(wireType);
+ return BindingType<ReturnType>::fromWireType(wireType);
+ }
+ };
+
+ template<typename... Args>
+ struct MethodCaller<void, Args...> {
+ static void call(EM_VAL handle, const char* methodName, Args&&... args) {
+ auto caller = Signature<void, Args...>::get_method_caller();
+ return caller(
+ handle,
+ methodName,
+ toWireType(std::forward<Args>(args))...);
+ }
+ };
+ }
#define EMSCRIPTEN_SYMBOL(name) \
static const char name##_symbol[] = #name; \
- static const symbol_registrar<name##_symbol> name##_registrar
+ static const ::emscripten::internal::symbol_registrar<name##_symbol> name##_registrar
class val {
public:
@@ -158,7 +191,7 @@ namespace emscripten {
}
bool hasOwnProperty(const char* key) const {
- return val::global("Object")["prototype"]["hasOwnProperty"].call("call", *this, val(key)).as<bool>();
+ return val::global("Object")["prototype"]["hasOwnProperty"].call<bool>("call", *this, val(key));
}
template<typename... Args>
@@ -211,45 +244,11 @@ namespace emscripten {
toWireType(std::forward<Args>(args))...));
}
- template<typename ...Args>
- val call(const char* name, Args&&... args) const {
+ template<typename ReturnValue, typename... Args>
+ ReturnValue call(const char* name, Args&&... args) const {
using namespace internal;
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef EM_VAL (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_method);
- return val(
- typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...));
- }
-
- template<typename ...Args>
- void call_void(const char* name, Args&&... args) const {
- using namespace internal;
-
- WithPolicies<>::ArgTypeList<Args...> argList;
- typedef void (*TypedCall)(
- EM_VAL,
- const char* name,
- unsigned,
- TYPEID argTypes[],
- typename BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_void_method);
- return typedCall(
- handle,
- name,
- argList.count,
- argList.types,
- toWireType(std::forward<Args>(args))...);
+ return MethodCaller<ReturnValue, Args...>::call(handle, name, std::forward<Args>(args)...);
}
bool has_function(const char* name) const {
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index 6fb15fc7..e4ddfd04 100644
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -13,6 +13,8 @@
namespace emscripten {
namespace internal {
+ typedef void (*GenericFunction)();
+
typedef const struct _TYPEID* TYPEID;
// This implementation is technically not legal, as it's not
@@ -146,6 +148,7 @@ namespace emscripten {
template<>
struct BindingType<void> {
+ typedef void WireType;
};
template<>