Duktape JavaScript engine bindings for Go

Overview

Duktape bindings for Go(Golang)

wercker status Travis status Appveyor status Gitter

Duktape is a thin, embeddable javascript engine. Most of the api is implemented. The exceptions are listed here.

Usage

The package is fully go-getable, no need to install any external C libraries.
So, just type go get gopkg.in/olebedev/go-duktape.v3 to install.

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()
  ctx.PevalString(`2 + 3`)
  result := ctx.GetNumber(-1)
  ctx.Pop()
  fmt.Println("result is:", result)
  // To prevent memory leaks, don't forget to clean up after
  // yourself when you're done using a context.
  ctx.DestroyHeap()
}

Go specific notes

Bindings between Go and Javascript contexts are not fully functional. However, binding a Go function to the Javascript context is available:

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()
  ctx.PushGlobalGoFunction("log", func(c *duktape.Context) int {
    fmt.Println(c.SafeToString(-1))
    return 0
  })
  ctx.PevalString(`log('Go lang Go!')`)
}

then run it.

$ go run *.go
Go lang Go!
$

Timers

There is a method to inject timers to the global scope:

package main

import "fmt"
import "gopkg.in/olebedev/go-duktape.v3"

func main() {
  ctx := duktape.New()

  // Let's inject `setTimeout`, `setInterval`, `clearTimeout`,
  // `clearInterval` into global scope.
  ctx.PushTimers()

  ch := make(chan string)
  ctx.PushGlobalGoFunction("second", func(_ *Context) int {
    ch <- "second step"
    return 0
  })
  ctx.PevalString(`
    setTimeout(second, 0);
    print('first step');
  `)
  fmt.Println(<-ch)
}

then run it

$ go run *.go
first step
second step
$

Also you can FlushTimers().

Command line tool

Install go get gopkg.in/olebedev/go-duktape.v3/....
Execute file.js: $GOPATH/bin/go-duk file.js.

Benchmarks

prog time
otto 200.13s
anko 231.19s
agora 149.33s
GopherLua 8.39s
go-duktape 9.80s

More details are here.

Status

The package is not fully tested, so be careful.

Contribution

Pull requests are welcome! Also, if you want to discuss something send a pull request with proposal and changes. Convention: fork the repository and make changes on your fork in a feature branch.

Comments
  • Change API to make possible serialize/deserialize duktape function

    Change API to make possible serialize/deserialize duktape function

    1. Changed API with respect of the rule when duktape C function returns (void *), API returns (unsafe.Pointer).
    2. Added example with serializtion/deserialization duktape function to/from bytecode.
    opened by mosolovsa 15
  • Fix DUK_VARARGS C -> Go overflow issue for all platforms

    Fix DUK_VARARGS C -> Go overflow issue for all platforms

    Originally go-duktape used the exact code from the upstream repo in the declaration of the DUK_VARARGS:

    #define DUK_VARARGS                       ((duk_int_t) (-1))
    

    This was wrapped into an int in the Go wrapper code:

    idx := d.PushCFunction((*[0]byte)(C.goFunctionCall), C.DUK_VARARGS)
    
    func (d *Context) PushCFunction(fn *[0]byte, nargs int) int
    

    This looked kind of ok, but for some reason broke on Windows builds with gopkg.in\olebedev\go-duktape.v3\duktape.go:132: constant 18446744073709551615 overflows int, so https://github.com/olebedev/go-duktape/pull/53 fixed it by changing the type of DUK_VARARGS from duk_int_t to duk_uint_t. Windows builds passed, everyone was happy.

    Unfortunately all 32 bit platforms (386, arm, mips32) blow up now with gopkg.in/olebedev/go-duktape.v3/duktape.go:132: constant 4294967295 overflows int. Apparently there was something very weird happening with duk_int_t and duk_uint_t within the C code, causing wildly different interpretations on different platforms.


    Taking a closer look into the definition of duk_int_t to duk_uint_t, they boil down to these lines of code (excerpt):

    /* The best type for an "all around int" in Duktape internals is "at least
     * 32 bit signed integer" which is most convenient.  Same for unsigned type.
     * Prefer 'int' when large enough, as it is almost always a convenient type.
     */
    #if defined(UINT_MAX) && (UINT_MAX >= 0xffffffffUL)
        typedef int duk_int_t;
        typedef unsigned int duk_uint_t;
    #else
        typedef duk_int_fast32_t duk_int_t;
        typedef duk_uint_fast32_t duk_uint_t;
    #endif
    
    [...]
    
    typedef int_fast32_t duk_int_fast32_t;
    typedef uint_fast32_t duk_uint_fast32_t;
    

    I.e. Depending on various platform, architecture and libc specifics, duk_int_t might be either an int or int_fast32_t (similar for the unsigned version). If it resolves to a plain int the types match with Go, and everything compiles correctly.

    If however duk_int_t resolves to int_fast32_t, all hell breaks loose, since it's a funky non-fixed sized type defined in the CPP reference as:

    fastest signed integer type with width of at least 32 bits

    This means, that int_fast32_t is only guaranteed to be at least 32 bits, but may be larger on given platform/architectures if those lead to better performance due to operations with native CPU types.

    The reason duktape has all these strange type overflow issues on different platforms is because DUK_VARARGS might actually be a 64 bit integer, even though it looks innocuous as a 32 bit int only.


    This PR fixes the issue by reverting the DUK_VARARGS to its upstream version of ((duk_int_t) (-1)), and changes the receiver type for this value from Go int to int64. This fixes the build on all platforms. In addition it also fixes a type case in one of the tests on 32 bit platforms.

    In addition, a second commit enables running the tests and builds on Linux, OSX and Windows on 32/64 bits and various ARM architectures to ensure they won't break in the future. Travis and appveyor should just be pointed to these files and they will pick up everything without any manual configuration.

    • https://travis-ci.org/karalabe/go-duktape/builds/319080617
    • https://ci.appveyor.com/project/karalabe/go-duktape/build/fix-386-overflow.13
    opened by karalabe 6
  • Trying to get Duktape 1.6 working

    Trying to get Duktape 1.6 working

    I took the unmerged PR by @marbemac and @pytlesk4 and tried to get the one failing error to pass. From what I can tell, the test is testing that we get a proper sytax error when trying to compile a function. I can verify that when I use other invalid syntax, the test passes but for some reason when we try to compile "foo" as a function, it panics with some really cryptic errors.

    @olebedev I am really appreciative of you work here, is there anyway you could give me some guidance on how to get this issue fixed. I'm not very familiar with C-Go.

    Thanks so much in advance!

    opened by nicksrandall 6
  • ptr's used to track the golang functions

    ptr's used to track the golang functions

    • JS wrapper remove now the Go function is tracking with a ptr attached as a property to the function. heavy inspired by @ivan4th at https://github.com/ivan4th/go-duktape/blob/master/duktape.go
    • the functions are not stored any more on Context a functionIndex is used handling the mutex and the ptr malloc and free
    • const are now in a spare file
    • Default has gone New is a empty contexts
    opened by mcuadros 5
  • unset functions from Contect on GC

    unset functions from Contect on GC

    This PR avoid memory leacks thank to create a finalize function for each registered go function, this allow to clean the function map of the Context for the collected function

    opened by mcuadros 3
  • Duktape 1.1.1

    Duktape 1.1.1

    Quick pull request to update things to 1.1.1.

    • Obviously uses Duktape 1.1.1 sources.
    • Bindings for Error and PushErrorObject (see bf50bba) as well as GetErrorCode and IsError (19f1249).
    • Reformats DUK_ constants to use camelcase, strip the prefix (ffc7661 and 8e950de). This will break compatibility for anyone using those constants. The upside is that this results in more Go-like identifiers.
    • Adds 1.1.0 Context methods.
    • Adds tests to ensure Error/PushErrorObject functions work as intended.
    opened by nilium 3
  • Enable console flushing

    Enable console flushing

    Integrate some changes made to the console extra in duktape:

    https://github.com/svaarala/duktape/pull/1587 https://github.com/svaarala/duktape/pull/1588

    This allows a user of go-duktape to optionally enable the console flushing flag, which will flush the buffers after every console.log() - I need this because the buffering makes it hard for our users to use console.log() as a debugging tool. I am not enabling this by default as I am sure it will negatively impact the performance for all users that do not require this functionality.

    Since go-duktape has not exposed the flags options before, I have added in a new type Flags (to hold the flags) and a new API method NewWithFlags that accepts a set of Flags. This allows a VM to be started with:

    vm := duktape.NewWithFlags(&duktape.Flags{Console: duktape.FlagConsoleFlush})

    opened by sstone1 2
  • EvalWith(source, goMethods) lets JS call go without global state

    EvalWith(source, goMethods) lets JS call go without global state

    A message from Oleg asking me to make a PR has been waiting in my TODO list since 2/19/15.

    I'd still like to re-organize it and finish it someday, but who knows when I will.

    Meanwhile, in case the commits in my fork didn't make the license sufficiently clear, you're free to add this stuff under the license of your project.

    opened by dckc 2
  • Debugger functionality to go-duktape

    Debugger functionality to go-duktape

    This PR adds a fully functional debugger to go-duktape. Included in the commit is the actual debugger implementation which is backed directly by duktape's debugger API. It also enabled debugger support in duk_config.h.

    Furthermore it adds a basic example transport to access the debugger via a socket (TCP, UNIX tested). The socket transport can be tested using the node.js debug client which is part of duktape's standard distribution (https://github.com/svaarala/duktape/tree/master/debugger).

    Connection to the debug stream is available as: node duk_debug.js --source-dirs=/path/to/js/sources

    opened by noctarius 1
  • Use DUK_SIZE_MAX instead of SIZE_MAX in duk_minimal_printf

    Use DUK_SIZE_MAX instead of SIZE_MAX in duk_minimal_printf

    When cross compiling to android with xgo, there is a compile error, because SIZE_MAX is missing from stdint.h. This fixes that (an alternative solution would be to use limits.h on android).

    Compile output:

    % xgo -targets=android-16/aar -v github.com/olebedev/go-duktape 
    Checking docker installation...
    Client:
     Version:	17.12.0-ce
     API version:	1.35
     Go version:	go1.9.2
     Git commit:	c97c6d6
     Built:	Wed Dec 27 20:03:51 2017
     OS/Arch:	darwin/amd64
    
    Server:
     Engine:
      Version:	17.12.0-ce
      API version:	1.35 (minimum version 1.12)
      Go version:	go1.9.2
      Git commit:	c97c6d6
      Built:	Wed Dec 27 20:12:29 2017
      OS/Arch:	linux/amd64
      Experimental:	true
    
    Checking for required docker image karalabe/xgo-latest... found.
    Cross compiling github.com/olebedev/go-duktape...
    Fetching main repository github.com/olebedev/go-duktape...
    github.com/olebedev/go-duktape (download)
    Assembling toolchain for android-16/arm...
    Bootstrapping android-16/arm...
    Assembling toolchain for android-16/arm...
    Bootstrapping android-16/arm...
    Compiling for android-16/arm...
    # github.com/olebedev/go-duktape
    duk_minimal_printf.c: In function 'duk_minimal_sprintf':
    duk_minimal_printf.c:286:35: error: 'SIZE_MAX' undeclared (first use in this function)
      ret = duk_minimal_vsnprintf(str, SIZE_MAX, format, ap);
                                       ^
    duk_minimal_printf.c:286:35: note: each undeclared identifier is reported only once for each function it appears in
    
    opened by agazso 1
  • Fix

    Fix "constant 18446744073709551615 overflows int" errors

    Fixes the following errors:

    olebedev\go-duktape.v2\duktape.go:83: constant 18446744073709551615 overflows int
    olebedev\go-duktape.v2\duktape.go:87: constant 18446744073709551615 overflows int
    

    OS/Machine:

    • Windows 10, 64-bit, Home Edition,

    The problem: ducktape.h uses #define for this value, i.e #define DUK_VARARGS ((duk_int_t) (-1))

    My assumption is that the Golang compiler assumes this is Uint/Uint64 rather than Int/Int64. Not sure if there's a more robust way to solve this.

    opened by silbinarywolf 1
  • duk_config.h increase RECLIMITs

    duk_config.h increase RECLIMITs

    Hi, @olebedev

    As described in this PR when geth calls JsonEncode function from your library it fails in case of reaching the DUK_USE_JSON_ENC_RECLIMIT = 1000.

    So what is the purpose of setting the reclimits of 1000? Are there any risks in increasing them?

    Thank you!

    opened by linuxion 10
  • leave the user set up the module-require method

    leave the user set up the module-require method

    Let the user choose which module loading method should be used, by adding two new methods: SetupNodeRequire and SetupDukRequire

    For SetupNodeRequire, extra steps are required, but those are specific for the node way (see: https://github.com/svaarala/duktape/blob/master/extras/module-node/README.rst)

    opened by juanolon 0
Owner
Oleg Lebedev
Don’t let the Canva bugs bite
Oleg Lebedev
🦁 A Super fast and lightweight runtime for JavaScript Scripts

Kimera.js - A super fast and lightweight JavaScript Runtime for Scripts.

Eliaz Bobadilla 22 Aug 14, 2022
Esprima-Go: A high performance JavaScript parser written in Go

Esprima-Go is a JavaScript parser written in Go. Esprima is a JavaScript parser written in TypeScript, it's widely used in javascript-realt

CHEN Yuan 0 Jan 9, 2022
PHP bindings for the Go programming language (Golang)

PHP bindings for Go This package implements support for executing PHP scripts, exporting Go variables for use in PHP contexts, attaching Go method rec

Alex Palaistras 877 Nov 14, 2022
naive go bindings to the CPython C-API

go-python Naive go bindings towards the C-API of CPython-2. this package provides a go package named "python" under which most of the PyXYZ functions

Sebastien Binet 1.4k Nov 25, 2022
Go bindings for Lua C API - in progress

Go Bindings for the lua C API Simplest way to install: # go get github.com/aarzilli/golua/lua You can then try to run the examples: $ cd golua/_examp

Alessandro Arzilli 599 Nov 17, 2022
Expression evaluation engine for Go: fast, non-Turing complete, dynamic typing, static typing

Expr Expr package provides an engine that can compile and evaluate expressions. An expression is a one-liner that returns a value (mostly, but not lim

Anton Medvedev 3.2k Nov 20, 2022
Golang-WASM provides a simple idiomatic, and comprehensive API and bindings for working with WebAssembly for Go and JavaScript developers

A bridge and bindings for JS DOM API with Go WebAssembly. Written by Team Ortix - Hamza Ali and Chan Wen Xu. GOOS=js GOARCH=wasm go get -u github.com/

TeamOrtix 88 Nov 24, 2022
Go bindings to QuickJS: a fast, small, and embeddable ES2020 JavaScript interpreter.

quickjs Go bindings to QuickJS: a fast, small, and embeddable ES2020 JavaScript interpreter. These bindings are a WIP and do not match full parity wit

Kenta Iwasaki 129 Nov 17, 2022
ECMAScript/JavaScript engine in pure Go

Goja is an implementation of ECMAScript 5.1 in pure Go with emphasis on standard compliance and performance.

Dmitry Panov 3.4k Nov 19, 2022
ECMAScript/JavaScript engine in pure Go

goja ECMAScript 5.1(+) implementation in Go. Goja is an implementation of ECMAScript 5.1 in pure Go with emphasis on standard compliance and performan

Dmitry Panov 3.4k Nov 28, 2022
v8 javascript engine binding for golang

Go-V8 V8 JavaScript engine bindings for Go. Features Thread safe Thorough and careful testing Boolean, Number, String, Object, Array, Regexp, Function

Hoping White 208 Nov 21, 2022
A Go API for the V8 javascript engine.

V8 Bindings for Go The v8 bindings allow a user to execute javascript from within a go executable. The bindings are tested to work with several recent

Augusto Roman 381 Nov 13, 2022
ECMAScript/JavaScript engine in pure Go

goja ECMAScript 5.1(+) implementation in Go. Goja is an implementation of ECMAScript 5.1 in pure Go with emphasis on standard compliance and performan

Dmitry Panov 3.4k Nov 28, 2022
This library provides WebAssembly capability for goja Javascript engine

This module provides WebAssembly functions into goja javascript engine.

YC-L 1 Jan 10, 2022
Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

Terra Informatica Software, Inc 2.5k Nov 18, 2022
A full-featured regex engine in pure Go based on the .NET engine

regexp2 - full featured regular expressions for Go Regexp2 is a feature-rich RegExp engine for Go. It doesn't have constant time guarantees like the b

Doug Clark 641 Nov 24, 2022
Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly

Introduction Qt is a free and open-source widget toolkit for creating graphical user interfaces as well as cross-platform applications that run on var

null 9.5k Nov 22, 2022
Glue - Robust Go and Javascript Socket Library (Alternative to Socket.io)

Glue - Robust Go and Javascript Socket Library Glue is a real-time bidirectional socket library. It is a clean, robust and efficient alternative to so

DesertBit 408 Nov 25, 2022
Glue - Robust Go and Javascript Socket Library (Alternative to Socket.io)

Glue - Robust Go and Javascript Socket Library Glue is a real-time bidirectional socket library. It is a clean, robust and efficient alternative to so

DesertBit 407 Nov 6, 2022
A JavaScript interpreter in Go (golang)

otto -- import "github.com/robertkrimen/otto" Package otto is a JavaScript parser and interpreter written natively in Go. http://godoc.org/github.com/

Robert Krimen 6.9k Nov 19, 2022