Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions runtime/js/embind/_wrap/emval.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
#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<val> _args;
_args.resize(nargs);
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;
val v = val::take_ownership(args[i]);
_args[i] = v;
writeGenericWireTypes(cursor, v);
}
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<val> _args;
_args.resize(nargs);
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;
val v = val::take_ownership(args[i]);
_args[i] = v;
writeGenericWireTypes(cursor, v);
}
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);
}
6 changes: 6 additions & 0 deletions runtime/js/embind/embind.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package embind

const (
LLGoFiles = "_wrap/emval.cpp"
LLGoPackage = "link: -lembind"
)
92 changes: 92 additions & 0 deletions runtime/js/emval.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//go:build js && wasm
// +build js,wasm

package js

import (
_ "unsafe"

c "github.com/goplus/llgo/runtime/internal/clite"
_ "github.com/goplus/llgo/runtime/js/embind"
)

var (
valueGlobal = emval_get_global(nil)
objectConstructor = emval_get_global(c.Str("Object"))
stringConstructor = emval_get_global(c.Str("String"))
arrayConstructor = emval_get_global(c.Str("Array"))
functionConstructor = emval_get_global(c.Str("Function"))
)

var (
valueUndefined = Value{2}
valueNull = Value{4}
valueTrue = Value{6}
valueFalse = Value{8}
valueNaN = emval_get_global(c.Str("NaN"))
valueZero = emval_new_double(0)
)

//go:linkname emval_get_global C.llgo_emval_get_global
func emval_get_global(name *c.Char) Value

//go:linkname emval_new_double C.llgo_emval_new_double
func emval_new_double(v float64) Value

//go:linkname emval_new_string C.llgo_emval_new_string
func emval_new_string(str *c.Char) Value

//go:linkname emval_new_object C.llgo_emval_new_object
func emval_new_object() Value

//go:linkname emval_new_array C.llgo_emval_new_array
func emval_new_array() Value

//go:linkname emval_set_property C.llgo_emval_set_property
func emval_set_property(object Value, key Value, value Value)

//go:linkname emval_get_property C.llgo_emval_get_property
func emval_get_property(object Value, key Value) Value

//go:linkname emval_delete C.llgo_emval_delete
func emval_delete(object Value, property Value) bool

//go:linkname emval_is_number C.llgo_emval_is_number
func emval_is_number(object Value) bool

//go:linkname emval_is_string C.llgo_emval_is_string
func emval_is_string(object Value) bool

//go:linkname emval_in C.llgo_emval_in
func emval_in(item Value, object Value) bool

//go:linkname emval_typeof C.llgo_emval_typeof
func emval_typeof(value Value) Value

//go:linkname emval_instanceof C.llgo_emval_instanceof
func emval_instanceof(object Value, constructor Value) bool

//go:linkname emval_as_double C.llgo_emval_as_double
func emval_as_double(v Value) float64

//go:linkname emval_as_string C.llgo_emval_as_string
func emval_as_string(v Value) string

//go:linkname emval_equals C.llgo_emval_equals
func emval_equals(first Value, second Value) bool

//go:linkname emval_method_call C.llgo_emval_method_call
func emval_method_call(object Value, name *c.Char, args *Value, nargs c.Int, err *c.Int) Value

// emval_call kind: FUNCTION = 0, CONSTRUCTOR = 1
//
//go:linkname emval_call C.llgo_emval_call
func emval_call(fn Value, args *Value, nargs c.Int, kind c.Int, err *c.Int) Value

//go:linkname emval_dump C.llgo_emval_dump
func emval_dump(v Value)

//export llgo_export_string_from
func llgo_export_string_from(data *c.Char, size c.Int) string {
return c.GoString(data, size)
}
Loading
Loading