Files
llgo/runtime/js/embind/_wrap/emval.cpp
2025-07-02 14:36:08 +08:00

207 lines
5.2 KiB
C++

#include <string>
#include <emscripten.h>
#include <emscripten/val.h>
#include <emscripten/bind.h>
using namespace emscripten;
using namespace emscripten::internal;
template<typename T>
TYPEID take_typeid() {
typename WithPolicies<>::template ArgTypeList<T> targetType;
return targetType.getTypes()[0];
}
template<typename T, typename... Policies>
EM_VAL take_value(T&& value, Policies...) {
typename WithPolicies<Policies...>::template ArgTypeList<T> valueType;
WireTypePack<T> argv(std::forward<T>(value));
return _emval_take_value(valueType.getTypes()[0], argv);
}
template<typename T, typename ...Policies>
T as_value(EM_VAL val, Policies...) {
typedef BindingType<T> BT;
typename WithPolicies<Policies...>::template ArgTypeList<T> targetType;
EM_DESTRUCTORS destructors = nullptr;
EM_GENERIC_WIRE_TYPE result = _emval_as(
val,
targetType.getTypes()[0],
&destructors);
DestructorsRunner dr(destructors);
return fromGenericWireType<T>(result);
}
struct GoString {
char *data;
int len;
};
static TYPEID typeid_val = take_typeid<val>();
extern "C" {
// export from llgo
extern GoString llgo_export_string_from(const char *data, int n);
extern bool llgo_export_invoke(EM_VAL args);
EM_VAL llgo_emval_get_global(const char *name) {
return _emval_get_global(name);
}
EM_VAL llgo_emval_new_double(double v) {
return take_value(v);
}
EM_VAL llgo_emval_new_string(const char *str) {
return _emval_new_u8string(str);
}
EM_VAL llgo_emval_new_object() {
return _emval_new_object();
}
EM_VAL llgo_emval_new_array() {
return _emval_new_array();
}
void llgo_emval_incref(EM_VAL value) {
_emval_incref(value);
}
void llgo_emval_decref(EM_VAL value) {
_emval_decref(value);
}
void llgo_emval_set_property(EM_VAL object, EM_VAL key, EM_VAL value) {
_emval_set_property(object, key, value);
}
EM_VAL llgo_emval_get_property(EM_VAL object, EM_VAL key) {
return _emval_get_property(object, key);
}
bool llgo_emval_is_number(EM_VAL object) {
return _emval_is_number(object);
}
bool llgo_emval_is_string(EM_VAL object) {
return _emval_is_string(object);
}
bool llgo_emval_in(EM_VAL item, EM_VAL object) {
return _emval_in(item, object);
}
bool llgo_emval_delete(EM_VAL object, EM_VAL property) {
return _emval_delete(object, property);
}
EM_VAL llgo_emval_typeof(EM_VAL value) {
return _emval_typeof(value);
}
bool llgo_emval_instanceof(EM_VAL object, EM_VAL constructor) {
return _emval_instanceof(object, constructor);
}
double llgo_emval_as_double(EM_VAL v) {
return as_value<double>(v);
}
GoString llgo_emval_as_string(EM_VAL v) {
std::string value = as_value<std::string>(v);
return llgo_export_string_from(value.c_str(), int(value.size()));
}
bool llgo_emval_equals(EM_VAL first, EM_VAL second) {
return _emval_equals(first, second);
}
EM_VAL llgo_emval_method_call(EM_VAL object, const char* name, EM_VAL args[], int nargs, int *error) {
std::vector<TYPEID> arr;
arr.resize(nargs+1);
std::vector<GenericWireType> elements;
elements.resize(nargs);
GenericWireType *cursor = elements.data();
arr[0] = typeid_val;
for (int i = 0; i < nargs; i++) {
arr[i+1] = typeid_val;
_emval_incref(args[i]);
writeGenericWireTypes(cursor, args[i]);
}
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND::FUNCTION);
EM_GENERIC_WIRE_TYPE ret;
try {
EM_DESTRUCTORS destructors = nullptr;
ret = _emval_call_method(caller, object, name, &destructors, elements.data());
} catch(const emscripten::val& jsErr) {
printf("error\n");
*error = 1;
return EM_VAL(internal::_EMVAL_UNDEFINED);
}
return fromGenericWireType<val>(ret).release_ownership();
}
/*
kind:
FUNCTION = 0,
CONSTRUCTOR = 1,
*/
EM_VAL llgo_emval_call(EM_VAL fn, EM_VAL args[], int nargs, int kind, int *error) {
std::vector<TYPEID> arr;
arr.resize(nargs+1);
std::vector<GenericWireType> elements;
elements.resize(nargs);
GenericWireType *cursor = elements.data();
arr[0] = typeid_val;
for (int i = 0; i < nargs; i++) {
arr[i+1] = typeid_val;
_emval_incref(args[i]);
writeGenericWireTypes(cursor, args[i]);
}
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND(kind));
EM_GENERIC_WIRE_TYPE ret;
try {
EM_DESTRUCTORS destructors = nullptr;
ret = _emval_call(caller, fn, &destructors, elements.data());
} catch(const emscripten::val& jsErr) {
*error = 1;
return EM_VAL(internal::_EMVAL_UNDEFINED);
}
return fromGenericWireType<val>(ret).release_ownership();
}
/*
TYPEID llgo_emval_typeid_void() {
return take_typeid<void>();
}
TYPEID llgo_emval_typeid_double() {
return take_typeid<double>();
}
TYPEID llgo_emval_typeid_string() {
return take_typeid<std::string>();
}
TYPEID llgo_emval_typeid_val() {
return take_typeid<val>();
}
*/
void llgo_emval_dump(EM_VAL v) {
val console = val::global("console");
console.call<void>("log", val::take_ownership(v));
}
}
bool invoke(val args) {
return llgo_export_invoke(args.as_handle());
}
EMSCRIPTEN_BINDINGS(my_module) {
function("_llgo_invoke", &invoke);
}