Skip to content

Commit

Permalink
Added support for variadic Go functions in ExportTo(). Closes #582
Browse files Browse the repository at this point in the history
  • Loading branch information
dop251 committed Jun 27, 2024
1 parent 393f6d4 commit 6639a88
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 6 deletions.
21 changes: 18 additions & 3 deletions runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -2206,9 +2206,24 @@ func (r *Runtime) toReflectValue(v Value, dst reflect.Value, ctx *objectExportCt

func (r *Runtime) wrapJSFunc(fn Callable, typ reflect.Type) func(args []reflect.Value) (results []reflect.Value) {
return func(args []reflect.Value) (results []reflect.Value) {
jsArgs := make([]Value, len(args))
for i, arg := range args {
jsArgs[i] = r.ToValue(arg.Interface())
var jsArgs []Value
if len(args) > 0 {
if typ.IsVariadic() {
varArg := args[len(args)-1]
args = args[:len(args)-1]
jsArgs = make([]Value, 0, len(args)+varArg.Len())
for _, arg := range args {
jsArgs = append(jsArgs, r.ToValue(arg.Interface()))
}
for i := 0; i < varArg.Len(); i++ {
jsArgs = append(jsArgs, r.ToValue(varArg.Index(i).Interface()))
}
} else {
jsArgs = make([]Value, len(args))
for i, arg := range args {
jsArgs[i] = r.ToValue(arg.Interface())
}
}
}

numOut := typ.NumOut()
Expand Down
56 changes: 53 additions & 3 deletions runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -941,8 +941,8 @@ func ExampleRuntime_ExportTo_funcThrow() {

func ExampleRuntime_ExportTo_funcVariadic() {
const SCRIPT = `
function f() {
return Array.prototype.join.call(arguments, ",");
function f(...args) {
return args.join("#");
}
`
vm := New()
Expand All @@ -957,7 +957,57 @@ func ExampleRuntime_ExportTo_funcVariadic() {
panic(err)
}
fmt.Println(fn("a", "b", 42))
// Output: a,b,42
// Output: a#b#42
}

func TestRuntime_ExportTo_funcVariadic(t *testing.T) {
const SCRIPT = `
function f(...args) {
return args.join("#");
}
`
vm := New()
_, err := vm.RunString(SCRIPT)
if err != nil {
panic(err)
}

t.Run("no args", func(t *testing.T) {
var fn func(args ...any) string
err = vm.ExportTo(vm.Get("f"), &fn)
if err != nil {
panic(err)
}
res := fn()
if res != "" {
t.Fatal(res)
}
})

t.Run("non-variadic args", func(t *testing.T) {
var fn func(firstArg any, args ...any) string
err = vm.ExportTo(vm.Get("f"), &fn)
if err != nil {
panic(err)
}
res := fn("first")
if res != "first" {
t.Fatal(res)
}
})

t.Run("non-variadic and variadic args", func(t *testing.T) {
var fn func(firstArg any, args ...any) string
err = vm.ExportTo(vm.Get("f"), &fn)
if err != nil {
panic(err)
}
res := fn("first", "second")
if res != "first#second" {
t.Fatal(res)
}
})

}

func TestRuntime_ExportToFuncFail(t *testing.T) {
Expand Down

0 comments on commit 6639a88

Please sign in to comment.