Merge pull request #1182 from visualfc/emjs
runtime/js: impl CopyBytesToGo/CopyBytesToJS
This commit is contained in:
@@ -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) {
|
EM_VAL llgo_emval_method_call(EM_VAL object, const char* name, EM_VAL args[], int nargs, int *error) {
|
||||||
std::vector<TYPEID> arr;
|
std::vector<TYPEID> arr;
|
||||||
arr.resize(nargs+1);
|
arr.resize(nargs+1);
|
||||||
std::vector<val> _args;
|
|
||||||
_args.resize(nargs);
|
|
||||||
std::vector<GenericWireType> elements;
|
std::vector<GenericWireType> elements;
|
||||||
elements.resize(nargs);
|
elements.resize(nargs);
|
||||||
GenericWireType *cursor = elements.data();
|
GenericWireType *cursor = elements.data();
|
||||||
arr[0] = typeid_val;
|
arr[0] = typeid_val;
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
arr[i+1] = typeid_val;
|
arr[i+1] = typeid_val;
|
||||||
val v = val::take_ownership(args[i]);
|
_emval_incref(args[i]);
|
||||||
_args[i] = v;
|
writeGenericWireTypes(cursor, args[i]);
|
||||||
writeGenericWireTypes(cursor, v);
|
|
||||||
}
|
}
|
||||||
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND::FUNCTION);
|
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND::FUNCTION);
|
||||||
EM_GENERIC_WIRE_TYPE ret;
|
EM_GENERIC_WIRE_TYPE ret;
|
||||||
@@ -155,17 +152,14 @@ CONSTRUCTOR = 1,
|
|||||||
EM_VAL llgo_emval_call(EM_VAL fn, EM_VAL args[], int nargs, int kind, int *error) {
|
EM_VAL llgo_emval_call(EM_VAL fn, EM_VAL args[], int nargs, int kind, int *error) {
|
||||||
std::vector<TYPEID> arr;
|
std::vector<TYPEID> arr;
|
||||||
arr.resize(nargs+1);
|
arr.resize(nargs+1);
|
||||||
std::vector<val> _args;
|
|
||||||
_args.resize(nargs);
|
|
||||||
std::vector<GenericWireType> elements;
|
std::vector<GenericWireType> elements;
|
||||||
elements.resize(nargs);
|
elements.resize(nargs);
|
||||||
GenericWireType *cursor = elements.data();
|
GenericWireType *cursor = elements.data();
|
||||||
arr[0] = typeid_val;
|
arr[0] = typeid_val;
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
arr[i+1] = typeid_val;
|
arr[i+1] = typeid_val;
|
||||||
val v = val::take_ownership(args[i]);
|
_emval_incref(args[i]);
|
||||||
_args[i] = v;
|
writeGenericWireTypes(cursor, args[i]);
|
||||||
writeGenericWireTypes(cursor, v);
|
|
||||||
}
|
}
|
||||||
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND(kind));
|
EM_METHOD_CALLER caller = _emval_get_method_caller(nargs+1,&arr[0],EM_METHOD_CALLER_KIND(kind));
|
||||||
EM_GENERIC_WIRE_TYPE ret;
|
EM_GENERIC_WIRE_TYPE ret;
|
||||||
@@ -179,25 +173,13 @@ EM_VAL llgo_emval_call(EM_VAL fn, EM_VAL args[], int nargs, int kind, int *error
|
|||||||
return fromGenericWireType<val>(ret).release_ownership();
|
return fromGenericWireType<val>(ret).release_ownership();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
EM_VAL llgo_emval_memory_view_uint8(size_t length, uint8_t *data) {
|
||||||
TYPEID llgo_emval_typeid_void() {
|
val view{ typed_memory_view<uint8_t>(length,data) };
|
||||||
return take_typeid<void>();
|
return view.release_ownership();
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void llgo_emval_dump(EM_VAL v) {
|
||||||
|
_emval_incref(v);
|
||||||
val console = val::global("console");
|
val console = val::global("console");
|
||||||
console.call<void>("log", val::take_ownership(v));
|
console.call<void>("log", val::take_ownership(v));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
//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
|
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
|
//go:linkname emval_dump C.llgo_emval_dump
|
||||||
func emval_dump(v Value)
|
func emval_dump(v Value)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
package js
|
package js
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,7 +47,8 @@ func FuncOf(fn func(this Value, args []Value) any) Func {
|
|||||||
nextFuncID++
|
nextFuncID++
|
||||||
funcs[id] = fn
|
funcs[id] = fn
|
||||||
funcsMu.Unlock()
|
funcsMu.Unlock()
|
||||||
sid := strconv.Itoa(int(id))
|
var buf [20]byte
|
||||||
|
sid := string(itoa(buf[:], uint64(id)))
|
||||||
wrap := functionConstructor.New(ValueOf(`
|
wrap := functionConstructor.New(ValueOf(`
|
||||||
const event = { id:` + sid + `, this: this, args: arguments };
|
const event = { id:` + sid + `, this: this, args: arguments };
|
||||||
Module._llgo_invoke(event);
|
Module._llgo_invoke(event);
|
||||||
@@ -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.
|
// Release frees up resources allocated for the function.
|
||||||
// The function must not be invoked after calling Release.
|
// The function must not be invoked after calling Release.
|
||||||
// It is allowed to call Release while the function is still running.
|
// It is allowed to call Release while the function is still running.
|
||||||
|
|||||||
@@ -666,7 +666,13 @@ func (e *ValueError) Error() string {
|
|||||||
// It panics if src is not a Uint8Array or Uint8ClampedArray.
|
// 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.
|
// 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 {
|
func CopyBytesToGo(dst []byte, src Value) int {
|
||||||
|
if !(emval_instanceof(src, uint8Array) || emval_instanceof(src, uint8ClampedArray)) {
|
||||||
return 0
|
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)
|
// n, ok := copyBytesToGo(dst, src.ref)
|
||||||
// runtime.KeepAlive(src)
|
// runtime.KeepAlive(src)
|
||||||
// if !ok {
|
// if !ok {
|
||||||
@@ -675,6 +681,23 @@ func CopyBytesToGo(dst []byte, src Value) int {
|
|||||||
// return n
|
// 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.
|
// copyBytesToGo copies bytes from src to dst.
|
||||||
//
|
//
|
||||||
// Using go:noescape is safe because the dst byte slice is only used as a dst
|
// Using go:noescape is safe because the dst byte slice is only used as a dst
|
||||||
@@ -688,7 +711,13 @@ func CopyBytesToGo(dst []byte, src Value) int {
|
|||||||
// It panics if dst is not a Uint8Array or Uint8ClampedArray.
|
// 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.
|
// 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 {
|
func CopyBytesToJS(dst Value, src []byte) int {
|
||||||
|
if !(emval_instanceof(dst, uint8Array) || emval_instanceof(dst, uint8ClampedArray)) {
|
||||||
return 0
|
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)
|
// n, ok := copyBytesToJS(dst.ref, src)
|
||||||
// runtime.KeepAlive(dst)
|
// runtime.KeepAlive(dst)
|
||||||
// if !ok {
|
// if !ok {
|
||||||
@@ -697,6 +726,28 @@ func CopyBytesToJS(dst Value, src []byte) int {
|
|||||||
// return n
|
// 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.
|
// copyBytesToJS copies bytes from src to dst.
|
||||||
//
|
//
|
||||||
// Using go:noescape is safe because the src byte slice is only used as a src
|
// Using go:noescape is safe because the src byte slice is only used as a src
|
||||||
|
|||||||
Reference in New Issue
Block a user