Create R Objects from JavaScript
Once webR has been loaded into a web page, new R objects can be created from the JavaScript environment. For example, it is possible to construct an R object using data provided as a JavaScript array, and then perform some computation in R with that data.
Creating new R objects
New R objects can be created from the main JavaScript thread by using the new
operator with proxy classes on an initialised instance of the WebR
class.
When an R object is instantiated in this way, webR communicates with the worker thread to orchestrate object creation in WebAssembly memory. As such, new R objects can only be created once communication with the worker thread has been established and the promise returned by WebR.init()
has resolved.
Once the object has been created on the worker thread, a promise is returned resolving as a reference to the new R object in the form of an RObject
. In a modern asynchronous JavaScript environment, the await
and new
keywords can be combined.
await webR.init();
let d = await new webR.RObject([2, 4, 6]);
await d.toArray();
[2, 4, 6]
Newly created RObject
references are protected by the default shelter unless otherwise specified. It is your responsibility to call the destroy()
method to release these objects.
Sometimes webR constructs new R objects implicitly behind the scenes. For instance new R objects are constructed automatically when executing R functions with JavaScript arguments. In this case memory management is in the hands of webR and doesn’t need intervention on your part.
Constructing R objects from JavaScript objects
The WebR
proxy classes take a single JavaScript argument in their constructor functions which will be used for the content of the new R object. JavaScript objects that are able to be converted for use as R objects have type WebRData
.
The resulting R object type is chosen based on the contents of the JavaScript argument provided. When there is ambiguity, the following conversion rules are used,
Constructor Argument | R Type |
---|---|
null |
Logical NA |
boolean |
Logical atomic vector |
number |
Double atomic vector |
{ re: 1, im: 2 } |
Complex atomic vector |
string |
Character atomic vector |
JavaScript array | An atomic vector with type based on the above rules and following the coercion rules of R’s c() function |
Object of type WebRDataJs |
An R object type given by the type property in the provided object |
Other JavaScript object | Reserved for future use |
In the case of R lists provided as an WebRDataJs
, the above rules are applied recursively to also construct the objects provided within the list.
Creating an R object with specific type
As an alternative to constructing an WebRDataJs
with an explicit type
property, several class proxies of different type are available on the WebR
instance. For example, the WebR.RList
class proxy can be used to specifically construct an R list object, rather than an atomic vector, using a JavaScript array of values.
To see how this can be useful, consider the difference in structure between the following two R object construction examples, using the same JavaScript object as the constructor argument,
let foo = await new webR.RObject([123, 'abc']);
await foo.toJs();
{ type: 'character', names: null, values: ['123', 'abc'] }
let foo = await new webR.RList([123, 'abc']);
await foo.toJs();
{
type: 'list',
names: null,
values: [
{ type: 'double', names: null, values: [ 123 ] },
{ type: 'character', names: null, values: ['abc'] }
]
}
Creating objects using RObject
references
An RObject
can be used as part of R object construction, either on its own, included in a JavaScript array, or as the values in an WebRDataJs
.
In such cases a new RObject
instance will be created, but the R object will not be copied as part of construction. The resulting RObject
will be a reference to the same point in WebAssembly memory as the source object.
This mechanism can be useful for creating new R lists or environments, or when re-constructing partially serialised objects in the form of an WebRDataJs
.
Binding objects to an R environment
The globalEnv
property, one of webR’s cached R objects, can be used to quickly bind JavaScript objects to variables in the global R environment,
await webR.objs.globalEnv.bind('foo', ['x', 'y', 'z'])
await webR.evalR('print(foo)');
[1] "x" "y" "z"
Alternatively, and to avoid adding to the global scope, a new environment can be directly constructed to be used with WebR.evalR()
,
let arr = await new webR.RObject([10, 21, 32]);
let env = await new webR.REnvironment({ foo: arr });
await webR.evalR('print(foo)', env);
[1] 10 21 32