New in V8: Calling R, from JavaScript, from R, from Javascript...

February 2, 2016


The V8 package provides an R interface to Google’s open source JavaScript engine. The package is completely self contained and requires no runtime dependencies, making it very easy to execute JavaScript code from R. A hand full of CRAN packages use V8 to provide R bindings to useful JavaScript libraries. Have a look at the v8 vignette to get started.

Callback To R

New in version 0.10 is the ability to call back to R from within JavaScript using the console.r API. This is most easily demonstrated via V8’s interactive JavaScript console:

ctx <- V8::v8()
ctx$console()

From JavaScript we can read/write R objects via console.r.get and console.r.assign, analogous to get and assign in R. The final argument is an optional list with arguments passed to toJSON or fromJSON which are used behind the scenes to convert objects between R and JavaScript.

// read the iris object into JS
var iris = console.r.get("iris")
var iris_col = console.r.get("iris", {dataframe : "col"})

//write an object back to the R session
console.r.assign("iris2", iris)
console.r.assign("iris3", iris, {simplifyVector : false})

Use console.r.call to call R functions. The first argument should be a string which evaluates to a function. The second argument contains a list of arguments passed to the function, similar to do.call in R. Both named and unnamed lists are supported. The return object is returned to JavaScript via JSON.

//calls rnorm(n=2, mean=10, sd=5)
var out = console.r.call('rnorm', {n: 2,mean:10, sd:5})
var out = console.r.call('rnorm', [2, 20, 5])

//anonymous function
var out = console.r.call('function(x){x^2}', {x:12})

There is also a console.r.eval function, which evaluates raw R code. It takes only a single argument (the string to evaluate) and does not return anything. Output is printed to the console.

console.r.eval('sessionInfo()')

Besides automatically converting objects, V8 also propagates exceptions between R, C++ and JavaScript up and down the stack. Hence you can catch R errors as JavaScript exceptions when calling an R function from JavaScript or vice versa. If nothing gets caught, exceptions bubble all the way up as R errors in your top-level R session.

//raise an error in R
console.r.call('stop("ouch!")')

//catch error from JavaScript
try {
   console.r.call('stop("ouch!")')
} catch (e) {
   console.log("Uhoh R had an error: " + e)
}

Thanks to Barret Schloerke for suggesting this feature and Dirk for pointing me in the right direction on how to call R functions from Rcpp (which is surprisingly easy).