add functions
parent
771a2d95cf
commit
fbfa1a0c93
176
bridge.go
176
bridge.go
|
@ -3,8 +3,8 @@ package wasm
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -76,6 +76,13 @@ func BridgeFromFile(name, file string, imports *wasmer.Imports) (*Bridge, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bridge) addValues() {
|
func (b *Bridge) addValues() {
|
||||||
|
var goObj *object
|
||||||
|
goObj = propObject("jsGo", map[string]interface{}{
|
||||||
|
"_makeFuncWrapper": wasmFunc(func(args []interface{}) (interface{}, error) {
|
||||||
|
return &funcWrapper{id: args[0]}, nil
|
||||||
|
}),
|
||||||
|
"_pendingEvent": nil,
|
||||||
|
})
|
||||||
b.values = []interface{}{
|
b.values = []interface{}{
|
||||||
math.NaN(),
|
math.NaN(),
|
||||||
float64(0),
|
float64(0),
|
||||||
|
@ -84,8 +91,8 @@ func (b *Bridge) addValues() {
|
||||||
false,
|
false,
|
||||||
&object{
|
&object{
|
||||||
props: map[string]interface{}{
|
props: map[string]interface{}{
|
||||||
"Object": &object{name: "Object", props: map[string]interface{}{}},
|
"Object": propObject("Object", nil),
|
||||||
"Array": &object{name: "Array", props: map[string]interface{}{}},
|
"Array": propObject("Array", nil),
|
||||||
"Int8Array": typedArray("Int8Array"),
|
"Int8Array": typedArray("Int8Array"),
|
||||||
"Int16Array": typedArray("Int16Array"),
|
"Int16Array": typedArray("Int16Array"),
|
||||||
"Int32Array": typedArray("Int32Array"),
|
"Int32Array": typedArray("Int32Array"),
|
||||||
|
@ -94,49 +101,67 @@ func (b *Bridge) addValues() {
|
||||||
"Uint32Array": typedArray("Uint32Array"),
|
"Uint32Array": typedArray("Uint32Array"),
|
||||||
"Float32Array": typedArray("Float32Array"),
|
"Float32Array": typedArray("Float32Array"),
|
||||||
"Float64Array": typedArray("Float64Array"),
|
"Float64Array": typedArray("Float64Array"),
|
||||||
"process": &object{name: "process", props: map[string]interface{}{}},
|
"process": propObject("process", nil),
|
||||||
"fs": &object{name: "fs", props: map[string]interface{}{
|
"fs": propObject("fs", map[string]interface{}{
|
||||||
"constants": &object{name: "constants", props: map[string]interface{}{
|
"constants": propObject("constants", map[string]interface{}{
|
||||||
"O_WRONLY": syscall.O_WRONLY,
|
"O_WRONLY": syscall.O_WRONLY,
|
||||||
"O_RDWR": syscall.O_RDWR,
|
"O_RDWR": syscall.O_RDWR,
|
||||||
"O_CREAT": syscall.O_CREAT,
|
"O_CREAT": syscall.O_CREAT,
|
||||||
"O_TRUNC": syscall.O_TRUNC,
|
"O_TRUNC": syscall.O_TRUNC,
|
||||||
"O_APPEND": syscall.O_APPEND,
|
"O_APPEND": syscall.O_APPEND,
|
||||||
"O_EXCL": syscall.O_EXCL,
|
"O_EXCL": syscall.O_EXCL,
|
||||||
}},
|
}),
|
||||||
}},
|
|
||||||
|
"write": wasmFunc(func(args []interface{}) (interface{}, error) {
|
||||||
|
fd := int(args[0].(float64))
|
||||||
|
offset := int(args[2].(float64))
|
||||||
|
length := int(args[3].(float64))
|
||||||
|
buf := args[1].(*array).data()[offset : offset+length]
|
||||||
|
pos := args[4]
|
||||||
|
callback := args[5].(*funcWrapper)
|
||||||
|
var err error
|
||||||
|
var n int
|
||||||
|
if pos != nil {
|
||||||
|
position := int64(pos.(float64))
|
||||||
|
n, err = syscall.Pwrite(fd, buf, position)
|
||||||
|
} else {
|
||||||
|
n, err = syscall.Write(fd, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.makeFuncWrapper(callback.id, goObj, &[]interface{}{nil, n})
|
||||||
|
}),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}, //global
|
}, //global
|
||||||
&object{
|
propObject("mem", map[string]interface{}{
|
||||||
name: "mem",
|
"buffer": &buffer{data: b.mem()}},
|
||||||
props: map[string]interface{}{
|
),
|
||||||
"buffer": &arrayBuffer{data: b.mem()},
|
goObj, // jsGo
|
||||||
},
|
|
||||||
},
|
|
||||||
&object{name: "jsGo", props: map[string]interface{}{}}, // jsGo
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run start the wasm instance.
|
// Run start the wasm instance.
|
||||||
func (b *Bridge) Run() error {
|
func (b *Bridge) Run(init chan bool, done chan error) {
|
||||||
defer b.instance.Close()
|
defer b.instance.Close()
|
||||||
|
|
||||||
run := b.instance.Exports["run"]
|
run := b.instance.Exports["run"]
|
||||||
resume := b.instance.Exports["resume"]
|
|
||||||
_, err := run(0, 0)
|
_, err := run(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
init <- false
|
||||||
|
done <- err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init <- true
|
||||||
|
// use channel from wasm exit
|
||||||
for !b.vmExit {
|
for !b.vmExit {
|
||||||
_, err = resume()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("WASM exited with code: %v\n", b.exitCode)
|
fmt.Printf("WASM exited with code: %v\n", b.exitCode)
|
||||||
return nil
|
done <- nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bridge) mem() []byte {
|
func (b *Bridge) mem() []byte {
|
||||||
|
@ -147,22 +172,37 @@ func (b *Bridge) getSP() int32 {
|
||||||
spFunc := b.instance.Exports["getsp"]
|
spFunc := b.instance.Exports["getsp"]
|
||||||
val, err := spFunc()
|
val, err := spFunc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("failed to get sp", err)
|
panic("failed to get sp")
|
||||||
}
|
}
|
||||||
|
|
||||||
return val.ToI32()
|
return val.ToI32()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) setUint8(offset int32, v uint8) {
|
||||||
|
mem := b.mem()
|
||||||
|
mem[offset] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bridge) setInt64(offset int32, v int64) {
|
func (b *Bridge) setInt64(offset int32, v int64) {
|
||||||
mem := b.mem()
|
mem := b.mem()
|
||||||
binary.LittleEndian.PutUint64(mem[offset:], uint64(v))
|
binary.LittleEndian.PutUint64(mem[offset:], uint64(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) setInt32(offset int32, v int32) {
|
||||||
|
mem := b.mem()
|
||||||
|
binary.LittleEndian.PutUint32(mem[offset:], uint32(v))
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bridge) getInt64(offset int32) int64 {
|
func (b *Bridge) getInt64(offset int32) int64 {
|
||||||
mem := b.mem()
|
mem := b.mem()
|
||||||
return int64(binary.LittleEndian.Uint64(mem[offset:]))
|
return int64(binary.LittleEndian.Uint64(mem[offset:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) getInt32(offset int32) int32 {
|
||||||
|
mem := b.mem()
|
||||||
|
return int32(binary.LittleEndian.Uint32(mem[offset:]))
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bridge) setUint32(offset int32, v uint32) {
|
func (b *Bridge) setUint32(offset int32, v uint32) {
|
||||||
mem := b.mem()
|
mem := b.mem()
|
||||||
binary.LittleEndian.PutUint32(mem[offset:], v)
|
binary.LittleEndian.PutUint32(mem[offset:], v)
|
||||||
|
@ -209,25 +249,23 @@ func (b *Bridge) loadSliceOfValues(addr int32) []interface{} {
|
||||||
arrLen := int(b.getInt64(addr + 8))
|
arrLen := int(b.getInt64(addr + 8))
|
||||||
vals := make([]interface{}, arrLen, arrLen)
|
vals := make([]interface{}, arrLen, arrLen)
|
||||||
for i := 0; i < int(arrLen); i++ {
|
for i := 0; i < int(arrLen); i++ {
|
||||||
_, vals[i] = b.loadValue(int32(arr + i*8))
|
vals[i] = b.loadValue(int32(arr + i*8))
|
||||||
}
|
}
|
||||||
|
|
||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove id once debugging is done
|
func (b *Bridge) loadValue(addr int32) interface{} {
|
||||||
func (b *Bridge) loadValue(addr int32) (uint32, interface{}) {
|
|
||||||
f := b.getFloat64(addr)
|
f := b.getFloat64(addr)
|
||||||
if f == 0 {
|
if f == 0 {
|
||||||
return 0, undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if !math.IsNaN(f) {
|
if !math.IsNaN(f) {
|
||||||
return 0, f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
id := b.getUint32(addr)
|
return b.values[b.getUint32(addr)]
|
||||||
return id, b.values[id]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bridge) storeValue(addr int32, v interface{}) {
|
func (b *Bridge) storeValue(addr int32, v interface{}) {
|
||||||
|
@ -284,13 +322,17 @@ func (b *Bridge) storeValue(addr int32, v interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
typeFlag := 0
|
typeFlag := 0
|
||||||
switch v.(type) {
|
rv := reflect.TypeOf(v)
|
||||||
case string:
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
rv = rv.Elem()
|
||||||
|
}
|
||||||
|
switch rv.Kind() {
|
||||||
|
case reflect.String:
|
||||||
typeFlag = 1
|
typeFlag = 1
|
||||||
case *object, *arrayBuffer: //TODO symbol maybe?
|
case reflect.Struct, reflect.Slice: //TODO symbol maybe?
|
||||||
typeFlag = 2
|
typeFlag = 2
|
||||||
default:
|
default:
|
||||||
log.Fatalf("unknown type: %T", v)
|
panic(fmt.Sprintf("unknown type: %T", v))
|
||||||
// TODO function
|
// TODO function
|
||||||
}
|
}
|
||||||
b.setUint32(addr+4, uint32(nanHead|typeFlag))
|
b.setUint32(addr+4, uint32(nanHead|typeFlag))
|
||||||
|
@ -300,15 +342,73 @@ func (b *Bridge) storeValue(addr int32, v interface{}) {
|
||||||
type object struct {
|
type object struct {
|
||||||
name string // TODO for debugging
|
name string // TODO for debugging
|
||||||
props map[string]interface{}
|
props map[string]interface{}
|
||||||
|
new func(args []interface{}) interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func propObject(name string, prop map[string]interface{}) *object {
|
||||||
|
return &object{name: name, props: prop}
|
||||||
|
}
|
||||||
|
|
||||||
|
type array struct {
|
||||||
|
buf *buffer
|
||||||
|
offset int
|
||||||
|
length int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *array) data() []byte {
|
||||||
|
return a.buf.data[a.offset : a.offset+a.length]
|
||||||
|
}
|
||||||
func typedArray(name string) *object {
|
func typedArray(name string) *object {
|
||||||
return &object{
|
return &object{
|
||||||
name: name,
|
name: name,
|
||||||
props: map[string]interface{}{},
|
new: func(args []interface{}) interface{} {
|
||||||
|
return &array{
|
||||||
|
buf: args[0].(*buffer),
|
||||||
|
offset: int(args[1].(float64)),
|
||||||
|
length: int(args[2].(float64)),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayBuffer struct {
|
type buffer struct {
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type wasmFunc func(args []interface{}) (interface{}, error)
|
||||||
|
|
||||||
|
func (b *Bridge) resume() error {
|
||||||
|
res := b.instance.Exports["resume"]
|
||||||
|
_, err := res()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type funcWrapper struct {
|
||||||
|
id interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) makeFuncWrapper(id, this interface{}, args *[]interface{}) (interface{}, error) {
|
||||||
|
goObj := b.values[7].(*object)
|
||||||
|
event := propObject("_pendingEvent", map[string]interface{}{
|
||||||
|
"id": id,
|
||||||
|
"this": nil,
|
||||||
|
"args": args,
|
||||||
|
})
|
||||||
|
|
||||||
|
goObj.props["_pendingEvent"] = event
|
||||||
|
err := b.resume()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return event.props["result"], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) CallFunc(fn string, args *[]interface{}) (interface{}, error) {
|
||||||
|
fw, ok := b.values[5].(*object).props[fn]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing function: %v", fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.makeFuncWrapper(fw.(*funcWrapper).id, b.values[7], args)
|
||||||
|
}
|
||||||
|
|
116
imports.go
116
imports.go
|
@ -29,7 +29,8 @@ import "C"
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"reflect"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ import (
|
||||||
|
|
||||||
//export debug
|
//export debug
|
||||||
func debug(ctx unsafe.Pointer, sp int32) {
|
func debug(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Println(sp)
|
fmt.Println(sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export wexit
|
//export wexit
|
||||||
|
@ -50,7 +51,12 @@ func wexit(ctx unsafe.Pointer, sp int32) {
|
||||||
|
|
||||||
//export wwrite
|
//export wwrite
|
||||||
func wwrite(ctx unsafe.Pointer, sp int32) {
|
func wwrite(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("wasm write", sp)
|
b := getBridge(ctx)
|
||||||
|
fd := int(b.getInt64(sp + 8))
|
||||||
|
p := int(b.getInt64(sp + 16))
|
||||||
|
l := int(b.getInt32(sp + 24))
|
||||||
|
syscall.Write(fd, b.mem()[p:p+l])
|
||||||
|
fmt.Println("wasm write", fd, p, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export nanotime
|
//export nanotime
|
||||||
|
@ -61,17 +67,23 @@ func nanotime(ctx unsafe.Pointer, sp int32) {
|
||||||
|
|
||||||
//export walltime
|
//export walltime
|
||||||
func walltime(ctx unsafe.Pointer, sp int32) {
|
func walltime(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("wall time")
|
b := getBridge(ctx)
|
||||||
|
t := time.Now().Unix()
|
||||||
|
sec := t / 1000
|
||||||
|
nanos := (t % 1000) * 1000000
|
||||||
|
b.setInt64(sp+8, sec)
|
||||||
|
b.setInt32(sp+16, int32(nanos))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//export scheduleCallback
|
//export scheduleCallback
|
||||||
func scheduleCallback(ctx unsafe.Pointer, sp int32) {
|
func scheduleCallback(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("schedule callback")
|
panic("schedule callback")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export clearScheduledCallback
|
//export clearScheduledCallback
|
||||||
func clearScheduledCallback(ctx unsafe.Pointer, sp int32) {
|
func clearScheduledCallback(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("clear scheduled callback")
|
panic("clear scheduled callback")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export getRandomData
|
//export getRandomData
|
||||||
|
@ -80,24 +92,23 @@ func getRandomData(ctx unsafe.Pointer, sp int32) {
|
||||||
_, err := rand.Read(s)
|
_, err := rand.Read(s)
|
||||||
// TODO how to pass error?
|
// TODO how to pass error?
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("failed: getRandomData", err)
|
panic("failed: getRandomData")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export stringVal
|
//export stringVal
|
||||||
func stringVal(ctx unsafe.Pointer, sp int32) {
|
func stringVal(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("stringVal")
|
panic("stringVal")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueGet
|
//export valueGet
|
||||||
func valueGet(ctx unsafe.Pointer, sp int32) {
|
func valueGet(ctx unsafe.Pointer, sp int32) {
|
||||||
b := getBridge(ctx)
|
b := getBridge(ctx)
|
||||||
str := b.loadString(sp + 16)
|
str := b.loadString(sp + 16)
|
||||||
id, val := b.loadValue(sp + 8)
|
val := b.loadValue(sp + 8)
|
||||||
sp = b.getSP()
|
sp = b.getSP()
|
||||||
obj, ok := val.(*object)
|
obj, ok := val.(*object)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Println("valueGet", str, id)
|
|
||||||
b.storeValue(sp+32, val)
|
b.storeValue(sp+32, val)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -105,70 +116,123 @@ func valueGet(ctx unsafe.Pointer, sp int32) {
|
||||||
res, ok := obj.props[str]
|
res, ok := obj.props[str]
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO
|
// TODO
|
||||||
log.Fatal("missing property", val, str)
|
panic(fmt.Sprintln("missing property", str, val))
|
||||||
}
|
}
|
||||||
fmt.Println("valueGet", str, id, obj.name)
|
fmt.Println("valueGet", str, obj.name)
|
||||||
b.storeValue(sp+32, res)
|
b.storeValue(sp+32, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueSet
|
//export valueSet
|
||||||
func valueSet(ctx unsafe.Pointer, sp int32) {
|
func valueSet(ctx unsafe.Pointer, sp int32) {
|
||||||
str := getBridge(ctx).loadString(sp + 16)
|
b := getBridge(ctx)
|
||||||
log.Fatal("valueSet", str)
|
val := b.loadValue(sp + 8)
|
||||||
|
obj := val.(*object)
|
||||||
|
prop := b.loadString(sp + 16)
|
||||||
|
propVal := b.loadValue(sp + 32)
|
||||||
|
obj.props[prop] = propVal
|
||||||
|
fmt.Println("valueSet", obj, prop, propVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueIndex
|
//export valueIndex
|
||||||
func valueIndex(ctx unsafe.Pointer, sp int32) {
|
func valueIndex(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valueIndex")
|
b := getBridge(ctx)
|
||||||
|
l := b.loadValue(sp + 8)
|
||||||
|
i := b.getInt64(sp + 16)
|
||||||
|
rv := reflect.ValueOf(l)
|
||||||
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
rv = rv.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := rv.Index(int(i))
|
||||||
|
b.storeValue(sp+24, iv.Interface())
|
||||||
|
fmt.Println("valueIndex:", iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueSetIndex
|
//export valueSetIndex
|
||||||
func valueSetIndex(ctx unsafe.Pointer, sp int32) {
|
func valueSetIndex(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valueSetIndex")
|
panic("valueSetIndex")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueCall
|
//export valueCall
|
||||||
func valueCall(ctx unsafe.Pointer, sp int32) {
|
func valueCall(ctx unsafe.Pointer, sp int32) {
|
||||||
str := getBridge(ctx).loadString(sp + 16)
|
b := getBridge(ctx)
|
||||||
log.Fatal("valueCall", str)
|
v := b.loadValue(sp + 8)
|
||||||
|
str := b.loadString(sp + 16)
|
||||||
|
args := b.loadSliceOfValues(sp + 32)
|
||||||
|
fmt.Println("valueCall: ", v.(*object).name, str, args)
|
||||||
|
f, ok := v.(*object).props[str].(wasmFunc)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintln("valueCall: prop not found in ", v, str))
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = b.getSP()
|
||||||
|
res, err := f(args)
|
||||||
|
if err != nil {
|
||||||
|
b.storeValue(sp+56, err.Error())
|
||||||
|
b.setUint8(sp+64, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b.storeValue(sp+56, res)
|
||||||
|
b.setUint8(sp+64, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueInvoke
|
//export valueInvoke
|
||||||
func valueInvoke(ctx unsafe.Pointer, sp int32) {
|
func valueInvoke(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valueInvoke")
|
panic("valueInvoke")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueNew
|
//export valueNew
|
||||||
func valueNew(ctx unsafe.Pointer, sp int32) {
|
func valueNew(ctx unsafe.Pointer, sp int32) {
|
||||||
b := getBridge(ctx)
|
b := getBridge(ctx)
|
||||||
id, val := b.loadValue(sp + 8)
|
val := b.loadValue(sp + 8)
|
||||||
args := b.loadSliceOfValues(sp + 16)
|
args := b.loadSliceOfValues(sp + 16)
|
||||||
log.Fatal("valueNew ", id, val, args)
|
res := val.(*object).new(args)
|
||||||
|
sp = b.getSP()
|
||||||
|
b.storeValue(sp+40, res)
|
||||||
|
b.setUint8(sp+48, 1)
|
||||||
|
fmt.Println("valueNew ", val, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueLength
|
//export valueLength
|
||||||
func valueLength(ctx unsafe.Pointer, sp int32) {
|
func valueLength(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valueLength")
|
b := getBridge(ctx)
|
||||||
|
val := b.loadValue(sp + 8)
|
||||||
|
rv := reflect.ValueOf(val)
|
||||||
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
rv = rv.Elem()
|
||||||
|
}
|
||||||
|
b.setInt64(sp+16, int64(rv.Len()))
|
||||||
|
fmt.Println("valueLength:", rv.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valuePrepareString
|
//export valuePrepareString
|
||||||
func valuePrepareString(ctx unsafe.Pointer, sp int32) {
|
func valuePrepareString(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valuePrepareString")
|
b := getBridge(ctx)
|
||||||
|
val := b.loadValue(sp + 8)
|
||||||
|
var str string
|
||||||
|
if val != nil {
|
||||||
|
str = val.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.storeValue(sp+16, str)
|
||||||
|
b.setInt64(sp+24, int64(len(str)))
|
||||||
|
fmt.Println("valuePrepareString", val, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueLoadString
|
//export valueLoadString
|
||||||
func valueLoadString(ctx unsafe.Pointer, sp int32) {
|
func valueLoadString(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("valueLoadString")
|
panic("valueLoadString")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export scheduleTimeoutEvent
|
//export scheduleTimeoutEvent
|
||||||
func scheduleTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
func scheduleTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("scheduleTimeoutEvent")
|
panic("scheduleTimeoutEvent")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export clearTimeoutEvent
|
//export clearTimeoutEvent
|
||||||
func clearTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
func clearTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Fatal("clearTimeoutEvent")
|
panic("clearTimeoutEvent")
|
||||||
}
|
}
|
||||||
|
|
||||||
// addImports adds go Bridge imports in "go" namespace.
|
// addImports adds go Bridge imports in "go" namespace.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
wasmgo "github.com/vedhavyas/wasm"
|
wasmgo "github.com/vedhavyas/wasm"
|
||||||
|
@ -12,7 +13,11 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := b.Run(); err != nil {
|
init, done := make(chan bool), make(chan error)
|
||||||
log.Fatal(err)
|
go b.Run(init, done)
|
||||||
}
|
<-init
|
||||||
|
res, err := b.CallFunc("printWasm", &[]interface{}{"success call"})
|
||||||
|
fmt.Println(res, err)
|
||||||
|
err = <-done
|
||||||
|
fmt.Println("wasm exited", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,19 @@ import (
|
||||||
"syscall/js"
|
"syscall/js"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: log seems to cause an issue
|
||||||
func printWasm(this js.Value, v []js.Value) interface{} {
|
func printWasm(this js.Value, v []js.Value) interface{} {
|
||||||
fmt.Println("Hello from WASM", v)
|
fmt.Println("Hello from WASM", v)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c := make(chan struct{}, 0)
|
ch := make(chan bool)
|
||||||
fmt.Println("WASM Go Initialized")
|
//fmt.Println("WASM Go Initialized")
|
||||||
|
|
||||||
// register functions
|
// register functions
|
||||||
js.Global().Set("printWasm", js.FuncOf(printWasm))
|
fun := js.FuncOf(printWasm)
|
||||||
fmt.Println("Done...")
|
js.Global().Set("printWasm", fun)
|
||||||
<-c
|
//fmt.Println("Done...")
|
||||||
|
<-ch
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue