Awesome
<div align="center"> <a href="https://github.com/rust-lang/rust"> <img height="200" alt="binaryen logo" src="https://www.rust-lang.org/logos/rust-logo-blk.svg"> </a> <a href="https://github.com/rollup/rollup"> <img height="200" alt="webpack logo" src="https://jestjs.io/img/jest.svg"> </a> </div> <!-- [![cover][cover]][cover-url] -->rs-jest
<sup><sup>tl;dr -- see examples</sup></sup>
This is a jest transformer that loads Rust code so it can be interop with Javascript base project. Currently, the Rust code will be compiled as:
- WebAssembly module/instance
- Node.js addon/ffi
Requirements
<ul> <li>Node v8 or later</li> <li>Jest v23 or later</li> <li><details> <summary>Rust v1.28.0 with wasm32-uknown-unknown installed</summary>rustup default 1.28.0
rustup target add wasm32-unknown-unknown
</details></li>
</ul>
Getting Started
To begin, you'll need to install rs-jest
:
npm install rs-jest --save-dev
Then configure Jest to make rs-jest
to transform the Rust (*.rs
) file. For example:
<b>jest.config.js</b>
module.exports = {
transform: {
"^.+\\.rs$": "rs-jest"
}
};
or if you prefer to put the config in <b>package.json</b>
"jest": {
"transform": {
"^.+\\.rs$": "rs-jest"
}
}
<details>
<summary>quick usage</summary>
<b>lib.rs</b>
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
<b>index.js</b>
import wasm from "lib.rs";
export async function increment(a) {
const { instance } = await wasm;
return instance.exports.add(1, a);
}
</details>
And run jest
via your preferred method.
Options
Pretty much like ts-jest, you can configure rs-jest
by using global variables under the "rs-jest"
key:
How wasm code would be exported. This options is identical with option export
in webassembly-loader. (see examples)
{
"globals": {
"rs-jest": {
"export": "instance"
}
},
"transform": {
"^.+\\.rs$": "rs-jest"
}
}
</details>
<details>
<summary><b><code>target</code></b></summary>
- Type:
String
- Default:
wasm32-unknown-unknown
- Expected value: see supported platform
The Rust target to use. Currently it only support wasm related target
{
"globals": {
"rs-jest": {
"target": "wasm32-unknown-emscripten"
}
},
"transform": {
"^.+\\.rs$": "rs-jest"
}
}
</details>
<details>
<summary><b><code>release</code></b></summary>
- Type:
Boolean
- Default:
true
Whether to compile the Rust code in debug or release mode.
{
"globals": {
"rs-jest": {
"release": false
}
},
"transform": {
"^.+\\.rs$": "rs-jest"
}
}
</details>
Examples
See the test cases and example projects in fixtures and examples for more insight.
<details> <summary>The exported module are pretty much like <a href="https://github.com/DrSensor/rollup-plugin-rust">rollup-plugin-rust</a> so it can be used alongside with it</summary>Given this Rust code
<b>lib.rs</b>
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
<b>Cargo.toml</b>
[package]
name = "adder"
version = "0.1.0"
authors = ["Full Name <email@site.domain>"]
[lib]
crate-type = ["cdylib"]
path = "lib.rs"
With options
{export: 'buffer'}
import wasmCode from "./lib.rs";
WebAssembly.compile(wasmCode).then(module => {
const instance = new WebAssembly.Instance(module);
console(instance.exports.add(1, 2)); // 3
});
{export: 'module'}
import wasmModule from "./lib.rs";
const instance = new WebAssembly.Instance(wasmModule);
console(instance.exports.add(1, 2)); // 3
{export: 'instance'}
import wasm from "./lib.rs";
console(wasm.exports.add(1, 2)); // 3
{export: 'async'}
extern {
fn hook(c: i32);
}
#[no_mangle]
pub fn add(a: i32, b: i32) -> i32 {
hook(a + b)
}
import wasmInstantiate from "./lib.rs";
wasmInstantiate(importObject | undefined).then(({ instance, module }) => {
console(instance.exports.add(1, 2)); // 3
// create different instance, extra will be called in different environment
const differentInstance = new WebAssembly.Instance(module, {
env: {
hook: result => result * 2
}
});
console(differentInstance.exports.add(1, 2)); // 6
});
{export: 'async-instance'}
import wasmInstantiate from "./lib.rs";
wasmInstantiate(importObject | undefined).then(instance => {
console(instance.exports.add(1, 2)); // 3
});
{export: 'async-module'}
import wasmInstantiate from "./lib.rs";
wasmCompile(importObject | undefined).then(module => {
const differentInstance = new WebAssembly.Instance(module);
console(differentInstance.exports.add(1, 2)); // 3
});
</details>
You may also want to look at
Who use this?
- example-stencil-rust
- [add yours 😉]
Contributing
- CONTRIBUTING.md for how you can make contribution
- HACKING.md for technical details