5

There is a gocode, which is compiled into a wasm file. I want one of the functions to return an array, but when I do so I see a panic: ValueOf: invalid value error. js.ValueOf function seems to be able to handle an array:

...
case []interface{}:
    a := arrayConstructor.New(len(x))
    for i, s := range x {
        a.SetIndex(i, s)
    }
    return a
...

but still panics, when I give it a []int value.

package main

import (
    "fmt"
    "syscall/js"
)

var signal = make(chan int)

func keepAlive() {
    for {
        <-signal
    }
}

func main() {
    js.Global().Set("PanicStation", js.FuncOf(PanicStation))
    keepAlive()
}

func PanicStation(this js.Value, args []js.Value) interface{} {
    arr := make([]int, 1)
    return arr
}
icza
  • 389,944
  • 63
  • 907
  • 827
Don Baton
  • 53
  • 4
  • Can be helpful: for googlers ending up here, how to convert arrays to []interface{} (or map[string]interface{} with the same approach): https://stackoverflow.com/questions/27689058/convert-string-to-interface – Eric Burel Dec 08 '22 at 07:46

1 Answers1

6

Using []interface{}

[]int is not the same as []interface{}. If []interface{} suits you, create and return that:

arr := make([]interface{}, 1)

For example, if you return this slice:

func PanicStation(this js.Value, args []js.Value) interface{} {
    return []interface{}{1, "two"}
}

Running PanicStation() in the JavaScript console will output:

> PanicStation()
> (2) [1, "two"]

Returning a typed array

Documentation of js.ValueOf() details what types are supported and how they are converted:

| Go                     | JavaScript             |
| ---------------------- | ---------------------- |
| js.Value               | [its value]            |
| js.TypedArray          | typed array            |
| js.Func                | function               |
| nil                    | null                   |
| bool                   | boolean                |
| integers and floats    | number                 |
| string                 | string                 |
| []interface{}          | new array              |
| map[string]interface{} | new object             |

Note that it is possible to return a value which will be a typed array in JavaScript. For that, use js.TypedArray in Go (obtained by js.TypedArrayOf()). The supported types are:

The supported types are []int8, []int16, []int32, []uint8, []uint16, []uint32, []float32 and []float64. Passing an unsupported value causes a panic.

Here's an example how to do it:

func PanicStation(this js.Value, args []js.Value) interface{} {
    return js.TypedArrayOf([]int32{1, 2})
}

This time calling PanicStation() from JavaScript, the output will be:

> PanicStation()
> Int32Array(2) [1, 2]
icza
  • 389,944
  • 63
  • 907
  • 827
  • Excellent, thank You. I initially tried to return 2d arrays, so `js.TypedArrayOf()` wasn't really helpfull. – Don Baton Apr 05 '19 at 14:19