dop251 / goja

ECMAScript/JavaScript engine in pure Go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can `.toString()` call the types `.String()` method in Go if it implements the stringer interface?

BrianLeishman opened this issue · comments

Example Go program:

package main

import (
	"fmt"

	"github.com/dop251/goja"
	"github.com/rs/xid"

	_ "embed"
)

//go:embed handler.js
var js string

func main() {
	type Data struct {
		ID *xid.ID `json:"id"`
	}

	vm := goja.New()
	vm.SetFieldNameMapper(goja.TagFieldNameMapper("json", true))
	_, err := vm.RunString(js)
	if err != nil {
		panic(err)
	}

	var handler func(data *Data) any
	err = vm.ExportTo(vm.Get("handler"), &handler)
	if err != nil {
		panic(err)
	}

	id := xid.New()
	data := &Data{
		ID: &id,
	}

	ret := handler(data)

	fmt.Println(ret)
}

handler.js

function handler(data) {
    return `My ID: ${data.id}`;
}

This example program prints

My ID: 98,235,253,24,67,226,17,2,101,133,205,181

Which is strange imo, especially since the type implements .String(), I would expect it to look like My ID: cblvq8q3s88g5ng1bmh0.

If I change the js line to

return `My ID: ${data.id.string()}`;

, then it does print what I'm expecting, but I'm not sure what the toString method is doing.


Even stranger, if I add a String method to my Data type to just return the string output from the id like

func (d *Data) String() string {
	return d.ID.String()
}

and then change the js to concat the object itself like

function handler(data) {
    return `My ID: ${data}`;
}

then it does actually print what I expect.

My ID: cblvsu23s88hhud9kvr0

So I suspect my expected behavior is actually the intended behavior, but the bug lies with something about stringing arrays (or specifically arrays of uint8s).