robertkrimen / otto

A JavaScript interpreter in Go (golang)
http://godoc.org/github.com/robertkrimen/otto
MIT License
8.04k stars 584 forks source link

Compile throws error #443

Open ssharish opened 1 year ago

ssharish commented 1 year ago

Consider the following function

function swap(a) {
  var c = a['name'].split(' ');
  a['name'] = c[1] + ' ' + c[0];
}

swap(args);

args is a map passed during runtime before Run(), using Set(), this code executes perfectly well, however, the same when passed to Compile() throws the following error.

(anonymous): Line 1: 32 Unexpected identifier (and 3 more errors)

I'm using the latest version of otto github.com/robertkrimen/otto v0.0.0-20221025135307-511d75fba9f8 from go.mod. Any help is really appreciated.

stevenh commented 1 year ago

This seems to work just fine for me, here's my code:

package otto

import (
        "testing"

        "github.com/stretchr/testify/require"
)

var jsIssue443 = `
function swap(a) {
  var c = a['name'].split(' ');
  a['name'] = c[1] + ' ' + c[0];
}

swap(args);

result = args['name'];
`

func TestIssue443(t *testing.T) {
        vm := New()
        vm.Set("args", map[string]string{"name": "first second"})
        val, err := vm.Run(jsIssue443)
        require.NoError(t, err)
        require.Equal(t, "second first", val.String())
}
ssharish commented 1 year ago

Could you please try doing Compile() the issue is with Compile() not with .Run(). Here is another example code where .Compile() throws the error.

fn := `
function fact(n) {
    if (n === 0 || n === 1) {
        return 1
    } else {
        return n * fact(n - 1)
    }
}

function factorial(m) {
    let n = m['num']
    m['num'] = fact(n)
}

factorial(args) 
`
vm := otto.New()
p := map[string]interface{} {"num":"17"}
vm.Set("args", p)
pg, er = vm.Compile("", fn)

if er != nil {
   log.Println(er.Error())
}

This throws the following error, however, if I do a Run() without Compile it just works. I intend to cache the compiled code for repetitive executions.

(anonymous): Line 11:8 Unexpected identifier (and 2 more errors)
stevenh commented 1 year ago

let is not ES 5. This works:

func Test_issue443(t *testing.T) {
    fn := `
function fact(n) {
    if (n === 0 || n === 1) {
        return 1
    } else {
        return n * fact(n - 1)
    }
}

function factorial(m) {
    var n = m['num']
    m['num'] = fact(n)
}

factorial(args) 
`
    vm := New()
    p := map[string]interface{}{"num": "17"}
    vm.Set("args", p)
    pg, err := vm.Compile("", fn)
    require.NoError(t, err)
    fmt.Printf("pg: %#v\n", pg)
}