webR logo
Magic with WebAssembly and webR

George Stagg
Senior Software Engineer @ Posit

Magic with Wasm and webR

With webR, it’s possible to execute R code directly in a web browser

But, webR can do more than just executing lines of code!

Interact with the running R process and manipulate the environment

🤯

“This is magic!”

A Wasm and webR refresher

The WebAssembly logo

WebAssembly (Wasm) is a portable binary format designed so that code can run anywhere

Client-side — in web browsers

Server-side — in the cloud and on the edge

A Wasm and webR refresher

The webR logo

webR is a version of the R interpreter built for WebAssembly

Execute R code directly in a web browser, without a supporting R server

Alternatively, run an R process server-side using Node.js

Why webR?

  • Educational materials, package documentation

  • Interactive presentations

  • Notebook & literate programming

  • Portable R applications, reproducibility

Thanks James Balamuta — coatless/quarto-webr

Today’s talk

🧙‍♂️

  • I’ll show off some webR magic
  • I’ll explain why it’s useful and describe how the magic works
  • I’ll be using JavaScript …but I won’t assume any particular knowledge

Mind reading: Getting data from R’s environment

Mind reading: Getting data from R’s environment

Mind reading: Getting data from R’s environment

Mind reading: Getting data from R’s environment

Conjuring variables: Putting data into R’s environment

Conjuring variables: Putting data into R’s environment

Conjuring variables: Putting data into R’s environment

Conjuring variables: Putting data into R’s environment

Conjuring variables: Putting data into R’s environment

Conjuring variables: Putting data into R’s environment

Spooky action at a distance 👻: Invoking R functions

Spooky action at a distance 👻: Invoking R functions

Spooky action at a distance 👻: Invoking R functions

Spooky action at a distance 👻: Invoking R functions

Spooky action at a distance 👻: Invoking R functions

Why is this useful?

These examples are relatively simple, but demonstrate a new and useful workflow using webR,

  • Moving data into the R environment
  • Running R functions
  • Retrieving data back into JavaScript

Why is this useful?

These examples are relatively simple, but demonstrate a new and useful workflow using webR,

  • Database connection, user data upload (e.g. CSV), data from a REST API
  • Running R functions
  • Retrieving data back into JavaScript

Why is this useful?

These examples are relatively simple, but demonstrate a new and useful workflow using webR,

  • Database connection, user data upload (e.g. CSV), data from a REST API
  • Complex data manipulation using dplyr, sophisticated statistical modelling with tidymodels
  • Retrieving data back into JavaScript

Why is this useful?

These examples are relatively simple, but demonstrate a new and useful workflow using webR,

  • Database connection, user data upload (e.g. CSV), data from a REST API
  • Complex data manipulation using dplyr, sophisticated statistical modelling with tidymodels
  • Dashboards, file download, interactive visualisation: D3.js, Observable

WebR enables a level of computation that might otherwise be awkward in JavaScript alone

Example: Plotting data from webR using Observable

const ret = await webR.evalR("penguins");
const data = await ret.toJs();
const penguins = data.values[0].values.map((_, idx) => {
  return {
    species: data.values[0].values[idx],
    island: data.values[1].values[idx],
    bill_length_mm: data.values[2].values[idx],
    bill_depth_mm: data.values[3].values[idx],
    sex: data.values[6].values[idx],
  }
});

Plot.dot(penguins, {
  x: "bill_length_mm",
  y: "bill_depth_mm",
  stroke: "species", symbol: "species",
  channels: {island: "island", sex: "sex"},
  tip: true
}).plot({ grid: true, symbol: { legend: true } })

Example: Plotting data from webR using Observable

Loading...

A look behind the curtain

Revealing the magic 🪄✨

The webR worker thread and communication channel

  • The R Wasm process runs in a JavaScript Web Worker
  • The browser’s main thread remains responsive while R is running
  • All communication to and from R is by message passing over a communication channel

Example: Evaluating R code

JavaScript Proxies

  • In webR, objects are returned to the user as references to R objects
  • An R object pointer is stored in a JavaScript Proxy object

  • A Proxy is a type of JavaScript object that allows you to intercept certain fundamental operations

  • Operations on R objects are converted into webR messages

  • R’s C API used to interact directly with objects in Wasm memory

Putting it all together…

  • Service Workers are another type of JavaScript Worker

  • Similar to Web Workers, but act as a Network Proxy for HTTP and WebSocket traffic

  • Service Workers can intercept network traffic and forward it to a running Wasm process

  • This is essentially how Shinylive for Python already works!

  • The webR JavaScript API acts as a bridge between the R process and the JS Service Worker

Shinylive for R

Thanks!

🔗 webR REPL

https://webr.r-wasm.org/v0.2.1/

🌎 Shinylive for R

https://shinylive.io/r/

📦 NPM

npm install webr

📙 Docs

https://docs.r-wasm.org/webr/v0.2.0/