Pass value from JS to go with interface argument

We have a basic k6 extension written:

type K6Ext struct{}

func init() {
	modules.Register("k6/x/ext", new(K6Ext))
}

type Reader interface {
	Foo() error
}

type ReaderImpl struct {}

func (r * ReaderImpl) Foo() error {} // Implementation omitted for brevity

type Stream struct {
	reader Reader
}


func (s *K6Ext) XReaderImpl(ctx *context.Context) interface{} {
	rt := common.GetRuntime(*ctx)
	return common.Bind(rt, &ReaderImpl{}, ctx)
}

func (s *K6Ext) XClient(ctx *context.Context, reader Reader) interface{} {
	rt := common.GetRuntime(*ctx)
	return common.Bind(rt, &Stream{reader: reader}, ctx)
}

which we try to use in js:

import ext from 'k6/x/ext'

const reader = ext.ReaderImpl()
const stream = ext.Client(reader)

When running this code, it fails with ERRO[0000] GoError: could not convert [object Object] to ext.Reader

I’m not sure if I’m passing this reader incorrectly here but it feels like I should be able to pass a golang struct to a go method even if the go method argument expects an interface. Any pointers as to how I should properly pass this?

Hi @vishalkuo, welcome to the community forum!

You can and should completely drop common.Bind for this use case.
It has one function and it is to facilitate the use of context in k6:
To wrap the methods of a struct which take context as the first argument … to actually get it when called from js code, without their first argument at the call site being a context object ;). This is already being done for each module such as yours due to the way modules.Register (and other things) work.

If you need to return an object that then will have to be called with context, as in the grpc module or metrics, you will need to use common.Bind, and at that point, we are actually moving around a different object and the current implementation does not support getting the original one in some way so … :man_shrugging: .

If this is your use case - please open an issue.

Hope this clears things out and helps you :slight_smile:

This works. Thanks a ton!