QuickJSR
uses the respective C
APIs of
R
and QuickJS
in order to pass values between
the two. This allows for increased efficiency in passing and returning
values (as no serialisation or de-serialisation is required) and also
allows for greater flexibility in working with R closures, functions,
and environments in JS code.
QuickJSR
aims to broadly follow the conventions of
jsonlite
in terms of how R types are converted to JS types
and vice-versa.
The following table outlines the basic mappings of primitive types between R and JS types:
R Type | JS Type |
---|---|
NULL | null |
logical | boolean |
integer | number |
double | number |
character | string |
date | date |
POSIXct | date |
factor | string |
Note that the handling of Date
/POSIXct
types differs from jsonlite
, where they are converted to
strings. In QuickJSR
, they are treated directly as
Date
objects in JS.
The following table outlines the basic mappings of container types between R and JS types:
R Type | JS Type |
---|---|
named list | object |
unnamed list | array |
vector | array |
array | array |
matrix | 2D number array |
data.frame | array of objects |
Examples of the matrix
and data.frame
conversions are shown below:
df <- data.frame(a = 1:3, b = c("x", "y", "z"))
cat(to_json(df))
#> [{"a":1,"b":"x"},{"a":2,"b":"y"},{"a":3,"b":"z"}]
Note that the to_json()
function operates by converting
R objects to their JS equivalents, and then calling
JSON.stringify()
on the result. This allows you to explore
how different types are being converted to JS.
Functions and closures can be passed between R and JS code. In JS,
functions are represented as Function
objects, and can be
called directly from JS code.
R environments are represented in JS as a custom class:
REnv
. The REnv
class simply wraps the pointer
to the R environment, and provides methods for getting and setting
values - this means that there is only a ‘cost’ for conversion when
values or accessed or updated.
Environment values can be accessed using either
env.value
or env["value"]
syntax:
ctx$source(code = 'function env_test(env) { return env.a + env["b"]; }')
env <- new.env()
env$a <- 1
env$b <- 2
ctx$call("env_test", env)
#> [1] 3
Values in the environment can also be updated from JS code:
QuickJSR
automatically adds a global object
R
to each context, which can be used to access the
namespaces of installed packages - and subsequently extract and use
functions and objects from them.