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
78 changes: 30 additions & 48 deletions runtime/js/embind/_wrap/emval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,14 @@ bool llgo_emval_equals(EM_VAL first, EM_VAL 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);
_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;
Expand All @@ -141,7 +138,7 @@ EM_VAL llgo_emval_method_call(EM_VAL object, const char* name, EM_VAL args[], in
ret = _emval_call_method(caller, object, name, &destructors, elements.data());
} catch(const emscripten::val& jsErr) {
printf("error\n");
*error = 1;
*error = 1;
return EM_VAL(internal::_EMVAL_UNDEFINED);
}
return fromGenericWireType<val>(ret).release_ownership();
Expand All @@ -153,51 +150,36 @@ 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>();
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();
}

EM_VAL llgo_emval_memory_view_uint8(size_t length, uint8_t *data) {
val view{ typed_memory_view<uint8_t>(length,data) };
return view.release_ownership();
}

TYPEID llgo_emval_typeid_val() {
return take_typeid<val>();
}
*/

void llgo_emval_dump(EM_VAL v) {
_emval_incref(v);
val console = val::global("console");
console.call<void>("log", val::take_ownership(v));
}
Expand Down
3 changes: 3 additions & 0 deletions runtime/js/emval.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ func emval_method_call(object Value, name *c.Char, args *Value, nargs c.Int, err
//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_memory_view_uint8 C.llgo_emval_memory_view_uint8
func emval_memory_view_uint8(length c.SizeT, data *c.Uint8T) Value

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

Expand Down
15 changes: 13 additions & 2 deletions runtime/js/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package js

import (
"strconv"
"sync"
)

Expand Down Expand Up @@ -48,7 +47,8 @@ func FuncOf(fn func(this Value, args []Value) any) Func {
nextFuncID++
funcs[id] = fn
funcsMu.Unlock()
sid := strconv.Itoa(int(id))
var buf [20]byte
sid := string(itoa(buf[:], uint64(id)))
wrap := functionConstructor.New(ValueOf(`
const event = { id:` + sid + `, this: this, args: arguments };
Module._llgo_invoke(event);
Expand All @@ -60,6 +60,17 @@ func FuncOf(fn func(this Value, args []Value) any) Func {
}
}

func itoa(buf []byte, val uint64) []byte {
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return buf[i:]
}

// Release frees up resources allocated for the function.
// The function must not be invoked after calling Release.
// It is allowed to call Release while the function is still running.
Expand Down
55 changes: 53 additions & 2 deletions runtime/js/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,13 @@ func (e *ValueError) Error() string {
// It panics if src is not a Uint8Array or Uint8ClampedArray.
// It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
func CopyBytesToGo(dst []byte, src Value) int {
return 0
if !(emval_instanceof(src, uint8Array) || emval_instanceof(src, uint8ClampedArray)) {
return 0
}
toCopy := src.Call("subarray", 0, len(dst))
view := emval_memory_view_uint8(uintptr(len(dst)), *(**byte)(unsafe.Pointer(&dst)))
view.Call("set", toCopy)
return toCopy.Length()
// n, ok := copyBytesToGo(dst, src.ref)
// runtime.KeepAlive(src)
// if !ok {
Expand All @@ -675,6 +681,23 @@ func CopyBytesToGo(dst []byte, src Value) int {
// return n
}

/*
// func copyBytesToGo(dst []byte, src ref) (int, bool)
"syscall/js.copyBytesToGo": (sp) => {
sp >>>= 0;
const dst = loadSlice(sp + 8);
const src = loadValue(sp + 32);
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
this.mem.setUint8(sp + 48, 1);
},
*/

// copyBytesToGo copies bytes from src to dst.
//
// Using go:noescape is safe because the dst byte slice is only used as a dst
Expand All @@ -688,7 +711,13 @@ func CopyBytesToGo(dst []byte, src Value) int {
// It panics if dst is not a Uint8Array or Uint8ClampedArray.
// It returns the number of bytes copied, which will be the minimum of the lengths of src and dst.
func CopyBytesToJS(dst Value, src []byte) int {
return 0
if !(emval_instanceof(dst, uint8Array) || emval_instanceof(dst, uint8ClampedArray)) {
return 0
}
view := emval_memory_view_uint8(uintptr(len(src)), *(**byte)(unsafe.Pointer(&src)))
toCopy := view.Call("subarray", 0, dst.Length())
dst.Call("set", toCopy)
return toCopy.Length()
// n, ok := copyBytesToJS(dst.ref, src)
// runtime.KeepAlive(dst)
// if !ok {
Expand All @@ -697,6 +726,28 @@ func CopyBytesToJS(dst Value, src []byte) int {
// return n
}

/*
// func copyBytesToJS(dst ref, src []byte) (int, bool)
"syscall/js.copyBytesToJS": (sp) => {
sp >>>= 0;
const dst = loadValue(sp + 8);
const src = loadSlice(sp + 16);
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
this.mem.setUint8(sp + 48, 1);
},
*/

var (
uint8Array = emval_get_global(c.Str("Uint8Array"))
uint8ClampedArray = emval_get_global(c.Str("Uint8ClampedArray"))
)

// copyBytesToJS copies bytes from src to dst.
//
// Using go:noescape is safe because the src byte slice is only used as a src
Expand Down
Loading