library(knitr)
knit_engines$set(V8 = function(options) {
require(V8)
context <- ifelse(!is.null(options$V8.context), options$V8.context, "ct")
if(!exists(context)){
assign(context, new_context(), envir = .GlobalEnv)
if(!is.null(options$V8.libraries)){
for(library in options$V8.libraries){
eval(parse(text=sprintf('%s$source("%s")', context, library)))
}
}
}
code <- as.character(c(options$code))
if(!eval(parse(text=sprintf("%s$validate(code)", context)))) stop("unvalid javascript code")
output <- eval(parse(text=sprintf("%s$eval(code)", context)))
code <- knitr:::wrap.source(list(src= paste(code, collapse = "\n")), options)
if(options$results=="hide") return(code)
else return(c(code, knitr:::wrap.character(output, options)))
})
Define x in Javascript context using the chunk option engine='V8':
var x=[];
x.push([1,2]);
x.push([3,4]);
x.push([5,6]);
JSON.stringify(x)
## [[1,2],[3,4],[5,6]]
By default the Javascript context is a R variable named ct. You can set another name by doing opts_chunk$set(V8.context="mycontext"). Then using the context variable you can import a variable from the Javascript context to R or vice-versa (see ?V8::V8 for details) :
x in R :( x.in.R <- ct$get("x") )
## [,1] [,2]
## [1,] 1 2
## [2,] 3 4
## [3,] 5 6
x in R and assign in Javascript context :ct$assign("double_x", 2*x.in.R)
The Javascript JSON.stringify function is nice for displaying an object in a V8 chunk:
JSON.stringify(double_x);
## [[2,4],[6,8],[10,12]]
You can load a Javascript library like this :
ct$source(system.file("js/underscore.js", package="V8"))
As you can see, it works:
JSON.stringify(_.flatten(x))
## [1,2,3,4,5,6]
Another way is to give the libraries as a character vector in the V8.libraries chunk option:
opts_chunk$set(V8.libraries=c(system.file("js/underscore.js", package="V8"), "http://coffeescript.org/extras/coffee-script.js"))
The libraries given by this way are loaded only once, at the moment the Javascript context is created.