diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..67fda6a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.DS_Store
+.idea
+inkwasm/.DS_Store
+inkwasm/inkwasm_js_test.go
+inkwasm/inkwasm_js_test.js
+inkwasm/inkwasm_js_test.s
\ No newline at end of file
diff --git a/bind/bind.go b/bind/bind.go
index 58da39a..8594558 100644
--- a/bind/bind.go
+++ b/bind/bind.go
@@ -30,6 +30,7 @@ type BridgeFuncInfo struct {
var BridgeFunc = map[ArgumentMode]map[string]BridgeFuncInfo{
ModeStatic: {
+ "interface{}": {JS: "globalThis.inkwasm.Load.Interface", Size: 16},
"float32": {JS: "globalThis.inkwasm.Load.Float32", Size: 4},
"float64": {JS: "globalThis.inkwasm.Load.Float64", Size: 8},
"uintptr": {JS: "globalThis.inkwasm.Load.UintPtr", Size: 8},
@@ -51,20 +52,21 @@ var BridgeFunc = map[ArgumentMode]map[string]BridgeFuncInfo{
"inkwasm.object": {JS: "globalThis.inkwasm.Load.InkwasmObject", Size: 16},
},
ModeArray: {
- "default": {JS: "globalThis.inkwasm.Load.Array", Size: -1},
- "float32": {JS: "globalThis.inkwasm.Load.ArrayFloat32", Size: 4},
- "float64": {JS: "globalThis.inkwasm.Load.ArrayFloat64", Size: 8},
- "uintptr": {JS: "globalThis.inkwasm.Load.ArrayUintPtr", Size: 8},
- "byte": {JS: "globalThis.inkwasm.Load.ArrayByte", Size: 1},
- "uint8": {JS: "globalThis.inkwasm.Load.ArrayUint8", Size: 1},
- "uint16": {JS: "globalThis.inkwasm.Load.ArrayUint16", Size: 2},
- "uint32": {JS: "globalThis.inkwasm.Load.ArrayUint32", Size: 4},
- "uint64": {JS: "globalThis.inkwasm.Load.ArrayUint64", Size: 8},
- "int8": {JS: "globalThis.inkwasm.Load.ArrayInt8", Size: 1},
- "int16": {JS: "globalThis.inkwasm.Load.ArrayInt16", Size: 2},
- "int32": {JS: "globalThis.inkwasm.Load.ArrayInt32", Size: 4},
- "int64": {JS: "globalThis.inkwasm.Load.ArrayInt64", Size: 8},
- "rune": {JS: "globalThis.inkwasm.Load.ArrayRune", Size: 8},
+ "default": {JS: "globalThis.inkwasm.Load.Array", Size: -1},
+ "interface{}": {JS: "globalThis.inkwasm.Load.ArrayInterface", Size: 16},
+ "float32": {JS: "globalThis.inkwasm.Load.ArrayFloat32", Size: 4},
+ "float64": {JS: "globalThis.inkwasm.Load.ArrayFloat64", Size: 8},
+ "uintptr": {JS: "globalThis.inkwasm.Load.ArrayUintPtr", Size: 8},
+ "byte": {JS: "globalThis.inkwasm.Load.ArrayByte", Size: 1},
+ "uint8": {JS: "globalThis.inkwasm.Load.ArrayUint8", Size: 1},
+ "uint16": {JS: "globalThis.inkwasm.Load.ArrayUint16", Size: 2},
+ "uint32": {JS: "globalThis.inkwasm.Load.ArrayUint32", Size: 4},
+ "uint64": {JS: "globalThis.inkwasm.Load.ArrayUint64", Size: 8},
+ "int8": {JS: "globalThis.inkwasm.Load.ArrayInt8", Size: 1},
+ "int16": {JS: "globalThis.inkwasm.Load.ArrayInt16", Size: 2},
+ "int32": {JS: "globalThis.inkwasm.Load.ArrayInt32", Size: 4},
+ "int64": {JS: "globalThis.inkwasm.Load.ArrayInt64", Size: 8},
+ "rune": {JS: "globalThis.inkwasm.Load.ArrayRune", Size: 8},
},
ModeSlice: {
"default": {JS: "globalThis.inkwasm.Load.Slice", Size: 24},
diff --git a/inkwasm/args_js.go b/inkwasm/args_js.go
index 6c8c487..76abe5d 100644
--- a/inkwasm/args_js.go
+++ b/inkwasm/args_js.go
@@ -2,123 +2,43 @@ package inkwasm
import (
"fmt"
- "math/big"
- "unsafe"
)
-var (
- decodeObject = newBasicDecoder("InkwasmObject")
- decodeString = newBasicDecoder("String")
- decodeFloat32 = newBasicDecoder("Float32")
- decodeFloat64 = newBasicDecoder("Float64")
- decodeBool = newBasicDecoder("Bool")
- decodeUintptr = newBasicDecoder("UintPtr")
- decodeInt = newBasicDecoder("Int")
- decodeUint = newBasicDecoder("Uint")
- decodeUint8 = newBasicDecoder("Uint8")
- decodeInt8 = newBasicDecoder("Int8")
- decodeUint16 = newBasicDecoder("Uint16")
- decodeInt16 = newBasicDecoder("Int16")
- decodeUint32 = newBasicDecoder("Uint32")
- decodeInt32 = newBasicDecoder("Int32")
- decodeUint64 = newBasicDecoder("Uint64")
- decodeInt64 = newBasicDecoder("Int64")
- decodeBigInt = newBasicDecoder("BigInt")
- decodeUnsafePointer = newBasicDecoder("UnsafePointer")
- decodeSliceUint8 = newSliceDecoder("ArrayUint8")
- decodeSliceUint16 = newSliceDecoder("ArrayUint16")
- decodeSliceUint32 = newSliceDecoder("ArrayUint32")
- decodeSliceUint64 = newSliceDecoder("ArrayUint64")
- decodeSliceInt8 = newSliceDecoder("ArrayInt8")
- decodeSliceInt16 = newSliceDecoder("ArrayInt16")
- decodeSliceInt32 = newSliceDecoder("ArrayInt32")
- decodeSliceInt64 = newSliceDecoder("ArrayInt64")
-)
-
-func newSliceDecoder(s string) uint64 {
- v := getSliceDecoder(getBasicDecoder(s))
- return *(*uint64)(unsafe.Pointer(&v))
-}
-
-func newBasicDecoder(s string) uint64 {
- v := getBasicDecoder(s).value
- return *(*uint64)(unsafe.Pointer(&v))
-}
-
-//inkwasm:get globalThis.inkwasm.Load
-func getBasicDecoder(s string) Object
-
-//inkwasm:func globalThis.inkwasm.Load.SliceOf
-func getSliceDecoder(f Object) Object
-
-// createArgs changes the given interface{}. It is two-word size. To
-// avoid allocs, we replace the "type-pointer" to decodeObject.
-func createArgs(args []interface{}) ([]int32, error) {
- for i, a := range args {
- var argDecoder uint64
+// createArgs is now a no-op
+// The JS will be responsible to identify the type of the arguments,
+// using Go internal structures.
+//
+// That is used to avoid wrong types of arguments.
+func createArgs(args []interface{}) ([]interface{}, error) {
+ for _, a := range args {
switch a.(type) {
case Object:
- argDecoder = decodeObject
case string:
- argDecoder = decodeString
case float32:
- argDecoder = decodeFloat32
case float64:
- argDecoder = decodeFloat64
case uintptr:
- argDecoder = decodeUintptr
case bool:
- argDecoder = decodeBool
case int:
- argDecoder = decodeInt
case uint:
- argDecoder = decodeUint
case uint8:
- argDecoder = decodeUint8
case int8:
- argDecoder = decodeInt8
case uint16:
- argDecoder = decodeUint16
case int16:
- argDecoder = decodeInt16
case uint32:
- argDecoder = decodeUint32
case int32:
- argDecoder = decodeInt32
case uint64:
- argDecoder = decodeUint64
case int64:
- argDecoder = decodeInt64
- case big.Int:
- argDecoder = decodeBigInt
- case unsafe.Pointer:
- argDecoder = decodeUnsafePointer
case []uint8:
- argDecoder = decodeSliceUint8
case []int8:
- argDecoder = decodeSliceInt8
case []uint16:
- argDecoder = decodeSliceUint16
case []int16:
- argDecoder = decodeSliceInt16
case []uint32:
- argDecoder = decodeSliceUint32
case []int32:
- argDecoder = decodeSliceInt32
case []uint64:
- argDecoder = decodeSliceUint64
case []int64:
- argDecoder = decodeSliceInt64
default:
return nil, fmt.Errorf("unsupported argument type of %T", a)
}
-
- // Replace the "type information" from interface{}
- // to the Object which decodes current argument.
- *(*uint64)(unsafe.Pointer(&args[i])) = argDecoder
}
-
- v := *(*[]int32)(unsafe.Pointer(&args))
- (*[3]uint64)(unsafe.Pointer(&v))[1] *= 4
- return v, nil
+ return args, nil
}
diff --git a/inkwasm/inkwasm_js.go b/inkwasm/inkwasm_js.go
index cf1507b..86d17f9 100644
--- a/inkwasm/inkwasm_js.go
+++ b/inkwasm/inkwasm_js.go
@@ -6,25 +6,6 @@ import (
"runtime"
)
-func _getBasicDecoder(s string) (_ Object) {
- r0 := __getBasicDecoder(s)
- runtime.KeepAlive(s)
-
- return r0
-}
-
-//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__getBasicDecoder
-func __getBasicDecoder(s string) (_ Object)
-
-func _getSliceDecoder(f Object) (_ Object) {
- r0 := __getSliceDecoder(f)
-
- return r0
-}
-
-//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__getSliceDecoder
-func __getSliceDecoder(f Object) (_ Object)
-
func _newObjectFromSyscall(i uint32) (_ Object) {
r0 := __newObjectFromSyscall(i)
@@ -79,7 +60,7 @@ func _free(ref int) {
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__free
func __free(ref int)
-func _call(o Object, k string, args []int32) (_ Object, _ bool) {
+func _call(o Object, k string, args []interface{}) (_ Object, _ bool) {
r0, r1 := __call(o, k, args)
runtime.KeepAlive(k)
runtime.KeepAlive(args)
@@ -88,9 +69,9 @@ func _call(o Object, k string, args []int32) (_ Object, _ bool) {
}
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__call
-func __call(o Object, k string, args []int32) (_ Object, _ bool)
+func __call(o Object, k string, args []interface{}) (_ Object, _ bool)
-func _callVoid(o Object, k string, args []int32) (_ bool, ok bool) {
+func _callVoid(o Object, k string, args []interface{}) (_ bool, ok bool) {
r0, r1 := __callVoid(o, k, args)
runtime.KeepAlive(k)
runtime.KeepAlive(args)
@@ -99,9 +80,9 @@ func _callVoid(o Object, k string, args []int32) (_ bool, ok bool) {
}
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__callVoid
-func __callVoid(o Object, k string, args []int32) (_ bool, ok bool)
+func __callVoid(o Object, k string, args []interface{}) (_ bool, ok bool)
-func _invoke(o Object, args []int32) (_ Object, _ bool) {
+func _invoke(o Object, args []interface{}) (_ Object, _ bool) {
r0, r1 := __invoke(o, args)
runtime.KeepAlive(args)
@@ -109,9 +90,9 @@ func _invoke(o Object, args []int32) (_ Object, _ bool) {
}
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__invoke
-func __invoke(o Object, args []int32) (_ Object, _ bool)
+func __invoke(o Object, args []interface{}) (_ Object, _ bool)
-func _invokeVoid(o Object, args []int32) (_ bool, ok bool) {
+func _invokeVoid(o Object, args []interface{}) (_ bool, ok bool) {
r0, r1 := __invokeVoid(o, args)
runtime.KeepAlive(args)
@@ -119,9 +100,9 @@ func _invokeVoid(o Object, args []int32) (_ bool, ok bool) {
}
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__invokeVoid
-func __invokeVoid(o Object, args []int32) (_ bool, ok bool)
+func __invokeVoid(o Object, args []interface{}) (_ bool, ok bool)
-func _newObj(o Object, args []int32) (_ Object, _ bool) {
+func _newObj(o Object, args []interface{}) (_ Object, _ bool) {
r0, r1 := __newObj(o, args)
runtime.KeepAlive(args)
@@ -129,7 +110,7 @@ func _newObj(o Object, args []int32) (_ Object, _ bool) {
}
//go:wasmimport gojs github.com/inkeliz/go_inkwasm/inkwasm.__newObj
-func __newObj(o Object, args []int32) (_ Object, _ bool)
+func __newObj(o Object, args []interface{}) (_ Object, _ bool)
func _getIndex(o Object, i int) (_ Object) {
r0 := __getIndex(o, i)
diff --git a/inkwasm/inkwasm_js.js b/inkwasm/inkwasm_js.js
index f5e3a36..7db4f41 100644
--- a/inkwasm/inkwasm_js.js
+++ b/inkwasm/inkwasm_js.js
@@ -9,18 +9,6 @@
(() => {
Object.assign(go.importObject.gojs, {
- "github.com/inkeliz/go_inkwasm/inkwasm.__getBasicDecoder": (sp) => {
- let r = globalThis.inkwasm.Load[globalThis.inkwasm.Load.String(go, sp, 8)]
- sp = go._inst.exports.getsp() >>> 0
- globalThis.inkwasm.Set.InkwasmObject(go, sp, 24, r)
- },
-
- "github.com/inkeliz/go_inkwasm/inkwasm.__getSliceDecoder": (sp) => {
- let r = globalThis.inkwasm.Load.SliceOf(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8))
- sp = go._inst.exports.getsp() >>> 0
- globalThis.inkwasm.Set.InkwasmObject(go, sp, 24, r)
- },
-
"github.com/inkeliz/go_inkwasm/inkwasm.__newObjectFromSyscall": (sp) => {
let r = go._values[globalThis.inkwasm.Load.Uint32(go, sp, 8)]
sp = go._inst.exports.getsp() >>> 0
@@ -58,7 +46,7 @@
"github.com/inkeliz/go_inkwasm/inkwasm.__call": (sp) => {
try {
- let r = globalThis.inkwasm.Internal.Call(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.String(go, sp, 24),globalThis.inkwasm.Load.Slice(go, sp, 40, globalThis.inkwasm.Load.ArrayInt32))
+ let r = globalThis.inkwasm.Internal.Call(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.String(go, sp, 24),globalThis.inkwasm.Load.Slice(go, sp, 40, globalThis.inkwasm.Load.ArrayInterface))
sp = go._inst.exports.getsp() >>> 0
globalThis.inkwasm.Set.InkwasmObject(go, sp, 64, r)
globalThis.inkwasm.Set.Bool(go, sp, 80, true)
@@ -70,7 +58,7 @@
"github.com/inkeliz/go_inkwasm/inkwasm.__callVoid": (sp) => {
try {
- let r = globalThis.inkwasm.Internal.Call(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.String(go, sp, 24),globalThis.inkwasm.Load.Slice(go, sp, 40, globalThis.inkwasm.Load.ArrayInt32))
+ let r = globalThis.inkwasm.Internal.Call(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.String(go, sp, 24),globalThis.inkwasm.Load.Slice(go, sp, 40, globalThis.inkwasm.Load.ArrayInterface))
sp = go._inst.exports.getsp() >>> 0
globalThis.inkwasm.Set.Bool(go, sp, 64, r)
globalThis.inkwasm.Set.Bool(go, sp, 65, true)
@@ -82,7 +70,7 @@
"github.com/inkeliz/go_inkwasm/inkwasm.__invoke": (sp) => {
try {
- let r = globalThis.inkwasm.Internal.Invoke(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInt32))
+ let r = globalThis.inkwasm.Internal.Invoke(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInterface))
sp = go._inst.exports.getsp() >>> 0
globalThis.inkwasm.Set.InkwasmObject(go, sp, 48, r)
globalThis.inkwasm.Set.Bool(go, sp, 64, true)
@@ -94,7 +82,7 @@
"github.com/inkeliz/go_inkwasm/inkwasm.__invokeVoid": (sp) => {
try {
- let r = globalThis.inkwasm.Internal.Invoke(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInt32))
+ let r = globalThis.inkwasm.Internal.Invoke(globalThis.inkwasm.Load.InkwasmObject(go, sp, 8),globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInterface))
sp = go._inst.exports.getsp() >>> 0
globalThis.inkwasm.Set.Bool(go, sp, 48, r)
globalThis.inkwasm.Set.Bool(go, sp, 49, true)
@@ -106,7 +94,7 @@
"github.com/inkeliz/go_inkwasm/inkwasm.__newObj": (sp) => {
try {
- let r = new globalThis.inkwasm.Load.InkwasmObject(go, sp, 8)(globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInt32))
+ let r = new globalThis.inkwasm.Load.InkwasmObject(go, sp, 8)(globalThis.inkwasm.Load.Slice(go, sp, 24, globalThis.inkwasm.Load.ArrayInterface))
sp = go._inst.exports.getsp() >>> 0
globalThis.inkwasm.Set.InkwasmObject(go, sp, 48, r)
globalThis.inkwasm.Set.Bool(go, sp, 64, true)
diff --git a/inkwasm/inkwasm_js.s b/inkwasm/inkwasm_js.s
index 850d7e1..7d2ea21 100644
--- a/inkwasm/inkwasm_js.s
+++ b/inkwasm/inkwasm_js.s
@@ -1,14 +1,6 @@
// Code generated by INKWASM BUILD; DO NOT EDIT
#include "textflag.h"
-TEXT ·getBasicDecoder(SB), NOSPLIT, $0
- JMP ·_getBasicDecoder(SB)
- RET
-
-TEXT ·getSliceDecoder(SB), NOSPLIT, $0
- JMP ·_getSliceDecoder(SB)
- RET
-
TEXT ·newObjectFromSyscall(SB), NOSPLIT, $0
JMP ·_newObjectFromSyscall(SB)
RET
diff --git a/inkwasm/tests_js_test.go b/inkwasm/tests_js_test.go
index fe45477..899b231 100644
--- a/inkwasm/tests_js_test.go
+++ b/inkwasm/tests_js_test.go
@@ -11,21 +11,20 @@ import (
)
func testInvoke(t *testing.T, obj Object, args ...interface{}) {
- t.Helper()
defer obj.Free()
objInvoked, err := obj.Invoke(args...)
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
defer objInvoked.Free()
r, err := objInvoked.Bool()
if err != nil {
- t.Error(err)
+ t.Fatal(err)
}
if r != true {
- t.Error("not true")
+ t.Fatal("not true")
}
}
@@ -135,13 +134,10 @@ func TestObjectType_String(t *testing.T) {
func gen_nonExistentFunction(s string) (Object, bool)
func TestNonExistentFunction(t *testing.T) {
- v, ok := gen_nonExistentFunction("Hello, 世界")
+ _, ok := gen_nonExistentFunction("Hello, 世界")
if ok {
t.Error("non existent function should return false")
}
- if v.Truthy() {
- t.Error("non existent function should return undefined")
- }
}
//inkwasm:func globalThis.TestObjectType_String
@@ -278,6 +274,48 @@ func TestInt64_Static(t *testing.T) {
}
}
+//inkwasm:func globalThis.TestSumFromArray
+func gen_TestSumFromArray([]uint32) uint32
+
+func TestArgsReuse(t *testing.T) {
+ args := []interface{}{
+ []uint32{1, 2, 3, 4, 5},
+ }
+
+ if gen_TestSumFromArray(args[0].([]uint32)) != 15 {
+ t.Error("args reuse error")
+ }
+
+ obj := Global().GetProperty("TestSumFromArray")
+ res, err := obj.Invoke(args...)
+ if err != nil {
+ t.Error(err)
+ }
+
+ v, err := res.Int()
+ if err != nil {
+ t.Error(err)
+ }
+
+ if v != 15 {
+ t.Error("args reuse error")
+ }
+
+ resReused, err := obj.Invoke(args...)
+ if err != nil {
+ t.Error(err)
+ }
+
+ v, err = resReused.Int()
+ if err != nil {
+ t.Error(err)
+ }
+
+ if v != 15 {
+ t.Error("args reuse error")
+ }
+}
+
//inkwasm:func globalThis.TestObject_Bytes
func gen_TestObject_Bytes() []byte
@@ -360,13 +398,14 @@ func Benchmark_GetLocalStorage_JS_SYSCALL(b *testing.B) {
}
//inkwasm:get globalThis.location.hostname
-func gen_GetLocationHostname() string
+func gen_GetLocationHostname() Object
func Benchmark_GetLocationHostname_INKWASM(b *testing.B) {
b.ReportAllocs()
+ fn := gen_GetLocationHostname()
for i := 0; i < b.N; i++ {
- if gen_GetLocationHostname() == "" {
+ if r, err := fn.String(); r == "" || err != nil {
b.Fail()
}
}
@@ -389,16 +428,26 @@ func gen_createElement(v string) Object
//inkwasm:set .innerHTML
func gen_setInnerHTML(o Object, v string)
-//inkwasm:func globalThis.document.body.appendChild
-func gen_appendChild(c Object)
+//inkwasm:func .appendChild
+func gen_appendChild(o Object, v Object)
+
+//inkwasm:get globalThis.document.body
+func gen_getBody() Object
func Benchmark_DOM_INKWASM(b *testing.B) {
b.ReportAllocs()
+ body := gen_getBody()
+
for i := 0; i < b.N; i++ {
div := gen_createElement("div")
gen_setInnerHTML(div, "foo bar baz "+strconv.Itoa(i))
- gen_appendChild(div)
+ gen_appendChild(body, div)
+ div.Free()
+
+ if i%100 == 0 {
+ gen_setInnerHTML(body, "")
+ }
}
}
@@ -407,17 +456,25 @@ func Benchmark_DOM_RUNTIME_INKWASM(b *testing.B) {
doc := Global().GetProperty("document")
defer doc.Free()
+
createElement, _ := doc.GetProperty("createElement").Call("bind", doc)
defer createElement.Free()
+
body := doc.GetProperty("body")
defer body.Free()
+
appendChild, _ := body.GetProperty("appendChild").Call("bind", body)
defer appendChild.Free()
+
for i := 0; i < b.N; i++ {
div, _ := createElement.Invoke("div")
div.SetProperty("innerHTML", "foo bar baz "+strconv.Itoa(i))
appendChild.InvokeVoid(div)
div.Free()
+
+ if i%100 == 0 {
+ body.SetProperty("innerHTML", "")
+ }
}
}
@@ -425,13 +482,21 @@ func Benchmark_DOM_JS_SYSCALL(b *testing.B) {
b.ReportAllocs()
doc := js.Global().Get("document")
+
createElement := doc.Get("createElement").Call("bind", doc)
+
body := doc.Get("body")
+
appendChild := body.Get("appendChild").Call("bind", body)
+
for i := 0; i < b.N; i++ {
div := createElement.Invoke("div")
div.Set("innerHTML", "foo bar baz "+strconv.Itoa(i))
appendChild.Invoke(div)
+
+ if i%100 == 0 {
+ body.Set("innerHTML", "")
+ }
}
}
@@ -439,10 +504,15 @@ func Benchmark_DOM_BAD_JS_SYSCALL(b *testing.B) {
b.ReportAllocs()
doc := js.Global().Get("document")
+
for i := 0; i < b.N; i++ {
div := doc.Call("createElement", "div")
div.Set("innerHTML", "foo bar baz "+strconv.Itoa(i))
doc.Get("body").Call("appendChild", div)
+
+ if i%100 == 0 {
+ doc.Get("body").Set("innerHTML", "")
+ }
}
}
@@ -451,10 +521,15 @@ func Benchmark_DOM_BAD_RUNTIME_INKWASM(b *testing.B) {
doc := Global().GetProperty("document")
defer doc.Free()
+
for i := 0; i < b.N; i++ {
div, _ := doc.Call("createElement", "div")
div.SetProperty("innerHTML", "foo bar baz "+strconv.Itoa(i))
doc.GetProperty("body").Call("appendChild", div)
div.Free()
+
+ if i%100 == 0 {
+ doc.GetProperty("body").SetProperty("innerHTML", "")
+ }
}
}
diff --git a/inkwasm/tests_js_test.js b/inkwasm/tests_js_test.js
index 2ecc5be..f30ccd0 100644
--- a/inkwasm/tests_js_test.js
+++ b/inkwasm/tests_js_test.js
@@ -72,4 +72,11 @@
globalThis.TestUint64_Add = function (e, e2) {
return e + e2
}
+ globalThis.TestSumFromArray = function (e) {
+ let sum = 0
+ for (let i = 0; i < e.length; i++) {
+ sum += e[i]
+ }
+ return sum
+ }
})();
\ No newline at end of file
diff --git a/inkwasm/wasm_js.go b/inkwasm/wasm_js.go
index 30d26b3..5d741ff 100644
--- a/inkwasm/wasm_js.go
+++ b/inkwasm/wasm_js.go
@@ -71,7 +71,7 @@ func (o Object) Call(method string, args ...interface{}) (Object, error) {
}
//inkwasm:func globalThis.inkwasm.Internal.Call
-func call(o Object, k string, args []int32) (Object, bool)
+func call(o Object, k string, args []interface{}) (Object, bool)
// CallVoid is similar to Call, but doesn't return the resulting Object.
// Look at Call function for more details.
@@ -87,7 +87,7 @@ func (o Object) CallVoid(method string, args ...interface{}) error {
}
//inkwasm:func globalThis.inkwasm.Internal.Call
-func callVoid(o Object, k string, args []int32) (_, ok bool)
+func callVoid(o Object, k string, args []interface{}) (_, ok bool)
// Invoke invokes the current Object, calling itself with the
// provided args as arguments of the function.
@@ -108,7 +108,7 @@ func (o Object) Invoke(args ...interface{}) (Object, error) {
}
//inkwasm:func globalThis.inkwasm.Internal.Invoke
-func invoke(o Object, args []int32) (Object, bool)
+func invoke(o Object, args []interface{}) (Object, bool)
// InvokeVoid is similar to Invoke, but doesn't return the resulting Object.
// Look at Invoke function for more details.
@@ -124,7 +124,7 @@ func (o Object) InvokeVoid(args ...interface{}) error {
}
//inkwasm:func globalThis.inkwasm.Internal.Invoke
-func invokeVoid(o Object, args []int32) (_, ok bool)
+func invokeVoid(o Object, args []interface{}) (_, ok bool)
// New uses the "new" operator from Javascript with the current object
// as the constructor and the given arg as arguments.
@@ -141,7 +141,7 @@ func (o Object) New(args ...interface{}) (Object, error) {
}
//inkwasm:new .
-func newObj(o Object, args []int32) (Object, bool)
+func newObj(o Object, args []interface{}) (Object, bool)
// GetIndex returns given index of the current Object.
func (o Object) GetIndex(index int) Object {
diff --git a/inkwasm/wasm_js.js b/inkwasm/wasm_js.js
index 300756c..9b600da 100644
--- a/inkwasm/wasm_js.js
+++ b/inkwasm/wasm_js.js
@@ -40,20 +40,11 @@
})
Object.assign(globalThis.inkwasm.Internal, {
- parseArgs: function (args) {
- let a = new Array(args.length >> 2);
- for (let i = 0; i < args.length; i += 4) {
- const k = args[i] + (args[i + 1] * 4294967296);
- const v = args[i + 2] + (args[i + 3] * 4294967296);
- a[i >> 2] = Objects[k](go, v, 0);
- }
- return a;
- },
Invoke: function (o, args) {
if (args === null || args.length === 0) {
return o()
}
- return o(...globalThis.inkwasm.Internal.parseArgs(args))
+ return o(...args)
},
Free: function (id) {
ObjectsUnused.push(id)
@@ -62,13 +53,13 @@
if (args === null || args.length === 0) {
return o[k]()
}
- return o[k](...globalThis.inkwasm.Internal.parseArgs(args))
+ return o[k](...args)
},
New: function (o, args) {
if (args === null || args.length === 0) {
return new o()
}
- return new o(...globalThis.inkwasm.Internal.parseArgs(args))
+ return new o(...args)
},
Make: function (args) {
if (args === null || args.length === 0) {
@@ -228,6 +219,144 @@
return globalThis.inkwasm.Load.ArrayUint32(go, sp, offset, len)
},
+ ArrayInterface: function (go, sp, offset, len) {
+ let result = []
+ for (let i = 0; i < len; i++) {
+ result.push(globalThis.inkwasm.Load.Interface(go, sp, offset + (i * 16)))
+ }
+ return result
+ },
+ Interface: function (go, sp, offset) {
+ let ptr_rtype = globalThis.inkwasm.Load.UintPtr(go, sp, offset)
+ let ptr_data = globalThis.inkwasm.Load.Int(go, sp, offset + 8)
+
+ let kind = globalThis.inkwasm.Load.Byte(go, ptr_rtype, 8 + 8 + 4 + 1 + 1 + 1)
+ switch (kind) {
+ case 0: // Invalid
+ return undefined
+ case 1: // Bool
+ return globalThis.inkwasm.Load.Bool(go, ptr_data, 0)
+ case 2: // Int
+ return globalThis.inkwasm.Load.Int(go, ptr_data, 0)
+ case 3: // Int8
+ return globalThis.inkwasm.Load.Int8(go, ptr_data, 0)
+ case 4: // Int16
+ return globalThis.inkwasm.Load.Int16(go, ptr_data, 0)
+ case 5: // Int32
+ return globalThis.inkwasm.Load.Int32(go, ptr_data, 0)
+ case 6: // Int64
+ return globalThis.inkwasm.Load.Int64(go, ptr_data, 0)
+ case 7: // Uint
+ return globalThis.inkwasm.Load.Uint(go, ptr_data, 0)
+ case 8: // Uint8
+ return globalThis.inkwasm.Load.Uint8(go, ptr_data, 0)
+ case 9: // Uint16
+ return globalThis.inkwasm.Load.Uint16(go, ptr_data, 0)
+ case 10: // Uint32
+ return globalThis.inkwasm.Load.Uint32(go, ptr_data, 0)
+ case 11: // Uint64
+ return globalThis.inkwasm.Load.Uint64(go, ptr_data, 0)
+ case 12: // Uintptr
+ return globalThis.inkwasm.Load.UintPtr(go, ptr_data, 0)
+ case 13: // Float32
+ return globalThis.inkwasm.Load.Float32(go, ptr_data, 0)
+ case 14: // Float64
+ return globalThis.inkwasm.Load.Float64(go, ptr_data, 0)
+ case 15: // Complex64
+ return undefined
+ case 16: // Complex128
+ return undefined
+ case 17: // Array
+ return undefined
+ case 18: // Chan
+ return undefined
+ case 19: // Func
+ return undefined
+ case 20: // Interface
+ return undefined
+ case 21: // Map
+ return undefined
+ case 22: // Pointer
+ return globalThis.inkwasm.Load.UintPtr(go, ptr_data, 0)
+ case 23: // Slice
+ let ptr_elem = globalThis.inkwasm.Load.UintPtr(go, ptr_rtype, 48)
+ let ptr_elem_kind = globalThis.inkwasm.Load.Byte(go, ptr_elem, 8 + 8 + 4 + 1 + 1 + 1)
+
+ let slice_fn = undefined;
+ switch (ptr_elem_kind) {
+ case 1: // Bool
+ slice_fn = globalThis.inkwasm.Load.ArrayByte
+ break;
+ case 2: // Int
+ slice_fn = globalThis.inkwasm.Load.ArrayInt64
+ break;
+ case 3: // Int8
+ slice_fn = globalThis.inkwasm.Load.ArrayInt8
+ break;
+ case 4: // Int16
+ slice_fn = globalThis.inkwasm.Load.ArrayInt16
+ break;
+ case 5: // Int32
+ slice_fn = globalThis.inkwasm.Load.ArrayInt32
+ break;
+ case 6: // Int64
+ slice_fn = globalThis.inkwasm.Load.ArrayInt64
+ break;
+ case 7: // Uint
+ slice_fn = globalThis.inkwasm.Load.ArrayUint64
+ break;
+ case 8: // Uint8
+ slice_fn = globalThis.inkwasm.Load.ArrayUint8
+ break;
+ case 9: // Uint16
+ slice_fn = globalThis.inkwasm.Load.ArrayUint16
+ break;
+ case 10: // Uint32
+ slice_fn = globalThis.inkwasm.Load.ArrayUint32
+ break;
+ case 11: // Uint64
+ slice_fn = globalThis.inkwasm.Load.ArrayUint64
+ break;
+ case 12: // Uintptr
+ slice_fn = globalThis.inkwasm.Load.ArrayUint64
+ break;
+ case 13: // Float32
+ slice_fn = globalThis.inkwasm.Load.ArrayFloat32
+ break;
+ case 14: // Float64
+ slice_fn = globalThis.inkwasm.Load.ArrayFloat64
+ break;
+ }
+
+ if (slice_fn === undefined) {
+ return undefined
+ }
+
+ return globalThis.inkwasm.Load.Slice(go, ptr_data, 0, slice_fn)
+ case 24: // String
+ return globalThis.inkwasm.Load.String(go, ptr_data, 0)
+ case 25: // Struct
+ const known_path_bytes = StringEncoder.encode("github.com/inkeliz/go_inkwasm/inkwasm")
+
+ let ptr_pkgPath = globalThis.inkwasm.Load.UintPtr(go, ptr_rtype, 48)
+ let pkgPath = globalThis.inkwasm.Load.ArrayByte(go, ptr_pkgPath, 2, known_path_bytes.length)
+
+ if (known_path_bytes.length !== known_path_bytes.length) {
+ return undefined
+ }
+
+ // Compare each element in the arrays
+ for (let i = 0; i < pkgPath.length; i++) {
+ if (pkgPath[i] !== known_path_bytes[i]) {
+ return undefined;
+ }
+ }
+
+ return globalThis.inkwasm.Load.InkwasmObject(go, ptr_data, 0)
+ case 26: // UnsafePointer
+ return globalThis.inkwasm.Load.UnsafePointer(go, ptr_data, 0)
+ }
+ },
Array: function (go, sp, offset, len, f) {
return f(go, sp, offset, len).slice(0, len)
diff --git a/parser/parser.go b/parser/parser.go
index 149788d..f1165ec 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -335,6 +335,10 @@ func parseArray(arg *bind.Argument, t *ast.ArrayType) error {
return parseIdent(arg.SubType, tt)
case *ast.SelectorExpr:
return parseSelector(arg.SubType, tt)
+ case *ast.InterfaceType:
+ arg.SubType.ArgType = bind.ModeStatic
+ arg.SubType.Type = "interface{}"
+ return nil
default:
return errors.New("array/slice of pointers isn't supported")
}