Package otto is a JavaScript parser and interpreter written natively in Go.

import (

Run something in the VM

vm := otto.New()
    abc = 2 + 2;
	console.log("The value of abc is " + abc); // 4

Get a value out of the VM

value, err := vm.Get("abc")
	value, _ := value.ToInteger()

Set a number

vm.Set("def", 11)
	console.log("The value of def is " + def);
	// The value of def is 11

Set a string

vm.Set("xyzzy", "Nothing happens.")
	console.log(xyzzy.length); // 16

Get the value of an expression

value, _ = vm.Run("xyzzy.length")
	// value is an int64 with a value of 16
	value, _ := value.ToInteger()

An error happens

value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length")
if err != nil {
	// err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined
	// If there is an error, then value.IsUndefined() is true

Set a Go function

vm.Set("sayHello", func(call otto.FunctionCall) otto.Value {
    fmt.Printf("Hello, %s.\n", call.Argument(0).String())
    return otto.Value{}

Set a Go function that returns something useful

vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value {
    right, _ := call.Argument(0).ToInteger()
    result, _ := vm.ToValue(2 + right)
    return result

Use the functions in JavaScript

result, _ = vm.Run(`
    sayHello("Xyzzy");      // Hello, Xyzzy.
    sayHello();             // Hello, undefined

    result = twoPlus(2.0); // 4


A separate parser is available in the parser package if you're just interested in building an AST.

Parse and return an AST

filename := "" // A filename is optional
src := `
    // Sample xyzzy example
        if (3.14159 > 0) {
            console.log("Hello, World.");

        var xyzzy = NaN;
        console.log("Nothing happens.");
        return xyzzy;

// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
program, err := parser.ParseFile(nil, filename, src, 0)


You can run (Go) JavaScript from the commandline with:

$ go get -v

Run JavaScript by entering some source on stdin or by giving otto a filename:

$ otto example.js


Optionally include the JavaScript utility-belt library, underscore, with this import:

import (
	_ ""

// Now every otto runtime will come loaded with underscore

For more information:

Caveat Emptor

The following are some limitations with otto:

* "use strict" will parse, but does nothing.
* The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification.
* Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.

Regular Expression Incompatibility

Go translates JavaScript-style regular expressions into something that is "regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires backtracking for some patterns, and backtracking is not supported by the standard Go engine:

Therefore, the following syntax is incompatible:

(?=)  // Lookahead (positive), currently a parsing error
(?!)  // Lookahead (backhead), currently a parsing error
\1    // Backreference (\1, \2, \3, ...), currently a parsing error

A brief discussion of these limitations: "Regexp (?!re)"

More information about re2:

In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc.

Halting Problem

If you want to stop long running executions (like third-party code), you can use the interrupt channel to do this:

package main

import (


var halt = errors.New("Stahp")

func main() {
    runUnsafe(`var abc = [];`)
    while (true) {
        // Loop forever

func runUnsafe(unsafe string) {
    start := time.Now()
    defer func() {
        duration := time.Since(start)
        if caught := recover(); caught != nil {
            if caught == halt {
                fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration)
            panic(caught) // Something else happened, repanic!
        fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration)

    vm := otto.New()
    vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking

    go func() {
        time.Sleep(2 * time.Second) // Stop after two seconds
        vm.Interrupt <- func() {

    vm.Run(unsafe) // Here be dragons (risky code)

Where is setTimeout/setInterval?

These timing functions are not actually part of the ECMA-262 specification. Typically, they belong to the `windows` object (in the browser). It would not be difficult to provide something like these via Go, but you probably want to wrap otto in an event loop in that case.

For an example of how this could be done in Go with otto, see natto:

Here is some more discussion of the issue:




otto is referenced in 88 repositories