WebAssembly (WASM) Build

But why?

There is already a fast and powerful scripting language that integrates nicely with WASM – JavaScript.

Anyhow, do it because you can!

It is possible to use Rhai when compiling to WebAssembly (WASM).

This yields a scripting engine (and language) that can be run in a standard web browser, among other places.

Unavailable features

When building for WASM, certain features will not be available, such as the script file API’s and loading modules from external script files.

Sample

Check out the Online Playground project which is driven by a Rhai Engine compiled into WASM.

JavaScript Interop

Specify either of the wasm-bindgen or stdweb features when building for WASM that requires interop with JavaScript. This selects the appropriate JavaScript interop layer to use.

It is still possible to compile for WASM without either wasm-bindgen or stdweb, but then the interop code must then be explicitly provided.

Target Environments

WASI: wasm32-wasi

There is no particular setting to tweak when building for WASI.

JavaScript: wasm32-unknown-unknown + wasm-bindgen/stdweb

Rhai requires a system-provided source of random numbers (for hashing).

Such random number source is available from JavaScript (e.g. if the WASM module is intended for a browser).

In such circumstances, it is necessary to enable the js feature on the getrandom crate.

[dependencies]
getrandom = { version = "0.2", features = [ "js" ] }

See also: https://docs.rs/getrandom/latest/getrandom/#webassembly-support

Raw: wasm32-unknown-unknown

Rhai requires a system-provided source of random numbers (for hashing).

Non-JavaScript/non-browser environments may not have random numbers available, so it is necessary to opt out of default-features in order to enable static hashing which uses fixed (non-random) keys.

[dependencies]
rhai = { version = "1.11.0", default-features = false, features = [ "std" ] }

Size

Also look into minimal builds to reduce generated WASM size.

A typical, full-featured Rhai scripting engine compiles to a single WASM32 file that is less than 400KB (non-gzipped).

When excluding features that are marginal in WASM environment, the gzipped payload can be shrunk further.

Standard packages can also be excluded to yield additional size savings.

Speed

In benchmark tests, a WASM build runs scripts roughly 1.7-2.2x slower than a native optimized release build.

Common Features

Some Rhai functionalities are not necessary in a WASM environment, so the following features are typically used for a WASM build:

FeatureDescription
wasm-bindgen or stdwebuse wasm-bindgen or stdweb as the JavaScript interop layer, omit if using custom interop code
uncheckedwhen a WASM module panics, it doesn’t crash the entire web app; however this also disables maximum number of operations and progress tracking so a script can still run indefinitely – the web app must terminate it itself
only_i32WASM supports 32-bit and 64-bit integers, but most scripts will only need 32-bit
f32_floatWASM supports 32-bit single-precision and 64-bit double-precision floating-point numbers, but single-precision is usually fine for most uses
no_modulea WASM module cannot load modules from the file system, so usually this is not needed, but the savings are minimal; alternatively, a custom module resolver can be provided that loads other Rhai scripts
no_custom_syntaxif custom syntax is not used, this results in a small size saving

The following features are typically not used because they don’t make sense in a WASM build:

FeatureWhy unnecessary
syncWASM is single-threaded
no_stdstd lib works fine with WASM
metadataWASM usually doesn’t need access to Rhai functions metadata
internalsWASM usually doesn’t need to access Rhai internal data structures, unless you are walking the AST
debuggingunless debugging is needed